Model To Model Distance running as CLI

Hi everyone,

I’m trying to use the Model-to-Model Distance extension in 3D Slicer to quantify the average displacement between two structures (one with deformation and one without).

However, I’ve run into an issue:

  • I’ve installed the extension multiple times and restarted Slicer each time

  • The module does not appear to function correctly in the GUI

  • The only way I can access it is via the CLI

The problem is that running it through the CLI does not provide the specific output I need, particularly the average displacement metric between the models.

Has anyone encountered a similar issue or knows:

  1. How to properly enable/use the extension through the GUI?

  2. How to retrieve average displacement (or equivalent statistics) using this tool or an alternative workflow?

Any guidance would be greatly appreciated.

Thanks in advance!

Can you elaborate? In what way does it not function correctly?

I hope the below AI generated response is helpful; I have verified the snippets work.

:robot: This post contains AI-generated content.

ModelToModelDistance is a CLI module, so it does not have a custom GUI. In Slicer, its “GUI” is the automatically generated CLI module panel. After installing the extension and restarting Slicer, search for:

Model To Model Distance

or look under the Quantification category.

The module does not print an average distance as a CLI return value. Instead, it writes distance arrays into the output model’s point data. You can then compute the average from those arrays in the Python console.

First, inspect the available arrays:

modelNode = slicer.util.getNode("VTK Output File")  # use your output model name

pointData = modelNode.GetPolyData().GetPointData()
for i in range(pointData.GetNumberOfArrays()):
    print(i, pointData.GetArrayName(i))

The array name depends on the selected distance mode.

For corresponding_point_to_point, use:

import numpy as np

distances = slicer.util.arrayFromModelPointData(
    modelNode, "AbsolutePointToPointDistance"
)

print("mean displacement:", np.mean(distances))
print("std:", np.std(distances))
print("min:", np.min(distances))
print("max:", np.max(distances))
print("median:", np.median(distances))
print("95th percentile:", np.percentile(distances, 95))

Or compute the magnitude from the displacement vectors:

import numpy as np

vectors = slicer.util.arrayFromModelPointData(modelNode, "PointToPointVector")
magnitudes = np.linalg.norm(vectors, axis=1)

print("mean displacement:", np.mean(magnitudes))

For absolute_closest_point, use:

import numpy as np

distances = slicer.util.arrayFromModelPointData(modelNode, "Absolute")
print("mean closest-point distance:", np.mean(distances))

For signed_closest_point, use:

import numpy as np

distances = slicer.util.arrayFromModelPointData(modelNode, "Signed")
print("mean signed closest-point distance:", np.mean(distances))

One caveat: if the option Save target name in distance fields / --targetInFields is enabled, the array name gets a suffix based on the target filename, for example:

Absolute_to_targetModelName
Signed_to_targetModelName

That is why it is best to print the point-data array names first.

Also, be careful about the interpretation. If the two models have matching point order, corresponding_point_to_point gives a true pointwise displacement. If they do not have corresponding points, use closest-point distance, but that is a surface-to-surface distance, not necessarily a physical displacement vector.