Model point count changing after transformation

We have a visualization tool in SlicerMorph that applies a TPS transformation derived from PCA to a reference model. I have exported transformed models. I am trying to use the model to model distance to visualize a heatmap (using the reference model as the target), specifically with the “corresponding point to point option”.

This generates an error that says:

Model To Model Distance standard error:

Both input files must have the same number of points to use 'corresponding_point_to_point'
Source model has 172232 points
Target model has 172259 points

However, if I go to Models menu and check the point counts for these models, they are reported identically and as 173261. Any idea where/why the difference might be coming from?

Geometric transformation does not change number of points. How did you apply the transform? I suspect that normals were computed for one or both of the surfaces before or after transforming, which can duplicate points (to allow proper rendering of sharp edges).

As I export the file, I chose apply transform. But the thing is for the transformed models, Models module report point numbers identical to the original model. That baffles me.

It looks like there’s a step that is cleaning and removing degenerate points from the input and output models, maybe there’s an issue like this with the transformed model?

I tried one example with the GPA module and didn’t see this error.

Can you try with GitHub - SlicerMorph/Mouse_Models and skip the scaling at GPA?

I’m getting the expected result for this dataset:

That can’t be, I think you didn’t skip the scaling step. Make sure you are using the data from the repo linked (not the slicermorph sample data).

Points may become “degenerate” if their positions are changed, so it is normal that a geometric transform changes the number of points after such cleanup.

If the processing step is unavoidable then you can store PedigreeIds (point ID in the input of the filter) or GlobalIds (some global point ID) in point scalars and make sure that all the used filters preserve point data. ModelToModelDistance module could use these point data to match points between differently processed meshes.

1 Like

Yes, that was the SM sample data. I reran with the data from GitHub and am not seeing an error, but that could be the choice of reference model or transform type.

I chose the FVB_NJ, which should be the sample reported as the closest to the mean. You should see a really strong size effect overall.

After testing, we found it’s the SlicerMorph extension that breaks the operation of the model to model distance module, but it only happens on Windows. Linux and Mac work as expected with exactly the same Slicer version and settings.

I don’t see any libraries or other dependencies that could result in this kind of OS specific difference. @lassoan do you have any ideas? Even importing a single module from the SlicerMorph module causes this difference

And removing the SlicerMorph extension fixes the issue. And the only effected functionality is the point-to-point distance calculations, others work fine regardless whether SlicerMorph is installed or not on Windows.

We do not have any idea how to debug this, so your input is most welcomed.

@lassoan @pieper @jcfr

That’s really strange. It implies there’s some kind of environment change that causes a side effect, like a library path or variable setting. From a quick look it seems the ModelToModel distance is a pure C++ CLI so maybe it’s a windows system dll.

One way to debug could be to open the depends from Slicer with and without the SlicerMorph module and compare the trees when examining the CLI executable. Start it from python with something like os.system(r"C:\Users\piepe\Downloads\depends22_x86\depends.exe") then do File->Open and browse to the CLI executable.

What file format do you use for saving meshes? Have you changed any default node settings related to saving meshes?

Interesting point - the MorphPreferences do switch the storage node to ply by default.

but it works without slicermorph. All data is already saved as ply.

Check if you can see any difference when you save to file and load that file. There should be no difference when saving into VTK or VTP format, but there could be subtle differences when exporting/importing non-VTK file formats.

I saved the models under the PCA transform as VTK and OBJ and with both formats, and I am still seeing the same error in Model to Model Distance corresponding point to point calculation option if SlicerMorph is installed. Again, only windows build seems to be affected.

If SlicerMorph is uninstalled, calculation with any format (ply, obj, vtk) work fine. I don’t think the issue is coming from the export step.

I uploaded all six model here if anyone wants to try to.

I set PC1 as source model, and Mean as target (though order doesn’t seem to matter for error generation).

@pieper
I have uploaded the output from DW with and without SlicerMorph here. I can’t tell much from it.

ModelToModelDistance module runs the inputs through vtkCleanPolyData, which of course changes the number of points (merging of coincident points is one of the most useful cleaning feature). You can see that when you apply Clean step in Surface toolbox module in Slicer then the number of points in the meshes are reduced to exactly 172245 and and 172232 points as expected. Therefore, Model2ModelDistance extension must be fixed: cleaning must be skipped when corresponding_point_to_point mode is used.

The only somewhat mysterious finding is that why SlicerMorph appear to change the behavior. By the way, I was not able to reproduce the difference between installing SlicerMorph or not on Windows: if I use the .vtk files in the shared folder as inputs then Model to model distance module fails if corresponding_point_to_point option is used because of point count mismatch - even on a computer where SlicerMorph has never been installed. It may worth checking why on linux and macos model to model distance computation mode succeeds when corresponding point option is used; because it should fail on all platforms.