VMTK vessel centerline network extraction in Slicer

I’ve installed Vascular Modelling Toolkit extension in Slicer4.11.
I could find
Centerline computation
Level set segmentation
Vesselness filtering

I couldn’t find vmtknetworkextraction . I’d like to know if there a separate plugin for networkextraction.

SlicerVMTK extension is available in Slicer-4.11. There are some temporary issues with the extension server today, but you can use a Slicer release from a couple of days before, for the version that you can download from here: Download 3D Slicer | 3D Slicer

@jcfr @Sam_Horvath many extensions reported upload errors - see for example this.

If you installed SlicerVMTK and the modules did not appear then maybe you have closed the application manually before the installation has been completed. The installation is completed when “Restart” button becomes active.

“Centerline Computation” module performs network extraction. You can process the network further and extract additional data by Python code snippets as shown here.

If you can describe the clinical problem you are trying to solve and the analysis that you would like to perform then we can give more specific help with how to achieve that.

1 Like

@lassoan

Thank you very much for the recent video that has been shared. I could follow and obtain the centerlines and curve tree root for a test geometry.

I’d like to extract the geometry in the form of a network. In the end, I wish to obtain the length( Abscissas) and radius( MISR) of each branch with the corresponding branch ids and the ids of start and
end points associated with each branch.
So, I tried

import vtkvmtkNetworkExtractionPython as vmtkNetworkExtraction

But it didn’t work.

Traceback (most recent call last):
File “”, line 1, in
ModuleNotFoundError: No module named ‘vtkvmtkNetworkExtractionPython’

The code that I use in python for doing the same task can be found here

Could you please offer suggestions on how to do this in Slicer?

There is no such module as NetworkExtraction. See list of modules in VMTK repository: Common, ComputationalGeometry, DifferentialGeometry, etc.

You don’t need to run NetworkExtraction, as “Centerline computation” module already performs network extraction. The result is available in the polydata of the it is already done as part of the output “Centerline model” node (call GetPolyData() on this node to access it).

Radius is available as point scalar in “Centerline model” node polydata.

Branch lengths are available in the extracted contour nodes in Markups module, but if you want to have radius and branch length information in a single data structure then you can use vtkvmtkCenterlineAttributesFilter.

How do you plan to process the radius and length information? Are you going to compute some overall statistics?

@lassoan Thank you

From what I know, it is available as a python class.

I’m interested in using this for CFD simulations.

Yes, I would like to have radius and length in a single data structure.
Should I use vtkvmtkCenterlineAttributesFilter on centerline_model node?

I am not sure how to do this?
Could you please add a short video tutorial?

The page you referred to documentats usage of VMTK’s special “pypes” scripts. These scripts are not Python classes that you import and use, but scripts that you can use via command line. They are very thin wrappers over Python classes, which are useful for people who prefer to work using command-line. For example, you can have a look at vmtknetworkextraction script and how it calls uses vtkvmtkPolyDataNetworkExtraction class. I would recommend to use the VTK classes directly instead of going through the extra layer of pypes scripts.

1 Like

@lassoan
Thank you very much for the clarification. I’m sorry about the confusion, I am really new to all of this.

Sure, I’d like to know how to process the branchids and the ids of endpoints associated with each branch.
For instance, I could do the following on polyData obtained after networkextraction.

edgeNode0 = edge.GetPointId(0)
edgeNode1 = edge.GetPointId(1)

This will give information on the topology.

What would like to compute exactly as end result? Average vessel radius over the entire tree? Average vessel segment length over the entire tree?

@lassoan
Yes, I would like to compute the average vessel segment length and average vessel segment radius
of all the branches in a tree.
Please check sample

I’ve added computation of branch length, average radius, curvature, torsion, and tortuosity to the centerline computation module. All you need to do to compute these metrics is to select a node for “Centerline properties”. This feature will be available in tomorrow’s Slicer Preview Release.

@lassoan Excellent! I am super happy to know about this new feature. Thanks a ton. I look forward to use this.

From what I understand, CellId refers to the branchid. It will be super helpful if you could also add
4 more columns branchNode0 and branchNode1, xyz_branchNode0, xyz_branchNode1.

branchNode0 = branch.GetPointId(0) # nodeid of the one end of a branch
branchNode1 = branch.GetPointId(1) # nodeid of the other end of a branch

and xyz_branchNode0, xyz_branchNode1 are the corresponding coordinates.

I had obtained the above in the following manner (code).

 for branchId in range(cleanedGraph.GetNumberOfCells()):
        branch = cleanedGraph.GetCell(branchId )  # this will be a vtkLine, which only has two points

    branchNode0 = branch .GetPointId(0)
    branchNode1 = branch .GetPointId(1)

output.
Deepa

You can cross-reference the displayed curve with the computed properties in the table based on the CellId displayed in parentheses in the widget’s node name, so you can find out quite easily which numbers are for which vessel segment.

Anyway, I have now added branch start and end point positions to the properties table.

1 Like

@lassoan

Thank you very much. This is extremely helpful.

If my understanding is right, the cellId displayed in parentheses are the numbers assigned to the vessel segments/ branches.
In my previous response, nodeid of the one end of a branch - I was referring to the ids of
StartPointPosition and EndPointPosition.

For instance, if I manually map the positions to ids for this simple input structure
CellId StartPointId EndPointId
0 0 1
1 1 2
2 2 3
3 2 4

and so on …

Can we retrieve these ids from the polyData? I think these can be mapped to the indices of the array
that stores these positions.

Thanks a lot again for these extensions!

Deepa

Parent/child relationships are the easiest to get from the curve hierarchy (you can get list of all immediate or all children nodes, etc.), but of course it is very easy to add any additional columns to the table, too. Could you describe what do you plan to compute and how?

Yes, that will be really helpful.

I plan to use this as an input for CFD studies where the endpoint ids will be useful for setting up external inputs.

What software do you plan to use and how? For CFD analysis, you probably need a couple of more things, such as:

  • use the original surface mesh instead of just centerline&radius (e.g., to model non-circular vessel geometry or aneurysms more accurately)
  • use a volumetric mesh
  • add straight extensions so that you can prescribe known boundary conditions at the end of those segments

These are all perfectly doable and have all the tools in Slicer and VMTK, but probably it would be better to implement these in a script first. Once you have a working script, it can be easily converted to a scripted module so that it is easier to use (you can select input/output nodes, parameters using a convenient GUI).

Let me know what exactly you would like to do and I’ll help with creating the script, and then with the conversion to scripted module.

Hi @lassoan

Thank you very much for offering to build scripted modules in Slicer for this study. This will be tremendously helpful for researchers working in this field.

For now, I’ve written my own code that models the underlying physics for performing the CFD analysis. I will be using the centerline properties obtained from Slicer as input. I would be super happy to share more details for developing a scripted module in Slicer in another 1-2 months. From my experience so far, Slicer will serve as a great platform since most of the tools are readily avaiable.

Kindly let me know after the ids of StartPointPosition EndPointPosition are appended to the centerline properties table. I look forward to use this feature.

@lassoan

This is a polite reminder about the inclusion of StartPointPosition EndPointPosition in the centerline properties table. I would like to know if this will be included.

Also, after the CenterlineComputationModel is created can we delete certain branches using the nodes defined in tree? I prefer to delete the branches with free ends, I want to retain only two free ends. Can we do this programmatically? If we can obtain the ids of all the free nodes from the network that is generated during computation of centerlines , the user can select the free ends to be retained and the branches that are connected to the other free ends can be deleted. The use case would be in CFD simulations where the boundary conditions can be defined. Defining boundary condition gets complicated when there are a lot of boundaries .

If this deletion cannot be directly done in Slicer, I would like to request for a export option that will allow the user to export the generated centerline network. The free ends can be deleted in an external tool by the user. This will be really helpful.

Branch deleting is now implemented, see:

1 Like

Hi @lassoan

Branch deleting works well for updating centerlines (i.e removal of branch in centerline model) when an endpoint is deleted. But the network branch doesn’t get removed. I’d like to know if it is possible to enable removal of the branches in network model too.