Python - Editing Feature Size Local Threshold

In the local threshold code on GitHub, there is a function updateMRMLfromGUI:

def updateMRMLFromGUI(self):
SegmentEditorThresholdEffect.updateMRMLFromGUI(self)

minimumDiameterMm = self.minimumDiameterSpinBox.value
self.scriptedEffect.setParameter(MINIMUM_DIAMETER_MM_PARAMETER_NAME, minimumDiameterMm)

featureSizeMm = self.featureSizeSpinBox.value
self.scriptedEffect.setParameter(FEATURE_SIZE_MM_PARAMETER_NAME, featureSizeMm)

segmentationAlgorithm = self.segmentationAlgorithmSelector.currentText
self.scriptedEffect.setParameter(SEGMENTATION_ALGORITHM_PARAMETER_NAME, segmentationAlgorithm)

How would I edit this code to set the feature size to 6.000 mm? Do I just replace featureSizeMm with 6?

Thanks!

1 Like

You don’t need to change the source code of a Segment Editor effect if you just want to change effect parameters from a Python script. Instead, you simply call effect.setParameter method from outside. See complete examples in the script repository: https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#How_to_run_segment_editor_effects_from_a_script

2 Likes

So for local threshold effect, I would type in:
localThresholdEffect.setFeatureSize(6)
localThresholdEffect.setMinimumThreshold(250)
localThresholdEffect.setMaximumThreshold(1000)

Our code just takes in a point on a vertebra and runs local threshold from that point. We have already coded the taking in a point.

1 Like

Do we also need to include values for BACKGROUND_VALUE and LABEL_VALUE in the apply function?

Also SELECTED_ISLAND_VALUE and OUTSIDE_THRESHOLD_VALUE

You don’t need to do anything with BACKGROUND_VALUE, LABEL_VALUE, etc. - they are internal constants.

The only parameter for apply method is ijkPoints and the method uses scripted effect parameters:

1 Like

Thank you very much!

Hello Andras!

We are in the testing stage of the entire code now. To confirm, we are running it line by line in the python interactor. The GitHub code uses an apply function(which appears to be synonymous with run the algorithm). The parameters for apply are self and ijkPoints.

Whenever we run the apply function:’

apply(ijkPoints)

It says apply() missing 1 required positional argument: ‘ijkPoints’

We have defined it already, so what do we do?

Thanks!

1 Like

You need to call apply like this: effect.apply(ijkPoints)

2 Likes

It says effect is not defined when I attempted this…

1 Like

Screen Shot 2020-07-06 at 2.42.25 PM

1 Like

You need to set an active effect first.

1 Like

Call setActiveEffectByName, as it is done in all the examples.

2 Likes

We set an active effect by name, but once again receive another error. It says:

Attribute Error: qSlicerSegmentEditorScriptEffect has no attribute named ‘apply’

This was after running effect.apply(ijkPoints)

We defined the function apply, what should we do?

1 Like

Indeed, in case of this effect, which is derived from C++ effect, the syntax is slightly different, as effect refers to the C++ effect, and you need to call effect.self() to access the methods added in Python. So, a complete example:

segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
segmentEditorWidget.setActiveEffectByName("Local Threshold")
effect = segmentEditorWidget.activeEffect()
ijkPoints = vtk.vtkPoints()
ijkPoints.InsertNextPoint(127,102,80)
effect.self().apply(ijkPoints)
1 Like

A post was merged into an existing topic: Python Module Logic Class

@lassoan

I am sorry to bother you again. I copied all of the functions from the Local Threshold into the Python Interactor and created a segmentationNode around a pre-determined point. Then, I run this code:

segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
segmentEditorWidget.setActiveEffectByName(“Local Threshold”)
effect.setParameter(“Minimum Threshold”, 265)
effect.setParameter(“Maximum Threshold”, 1009)
effect = segmentEditorWidget.activeEffect()
ijkPoints = vtk.vtkPoints()
ijkPoints.InsertNextPoint(world[0], world[1], world[2]) ##world has the coordinates of the point
effect.self().apply(ijkPoints)

This gives me an error saying that “None Type” has no attribute self. I feel like we have the necessary elements to the code(many thanks to your GitHub resources), but I just cannot get the code to actually work when run. Thank you

1 Like

You can only select an effect if you selected a master volume and created a segment. See the examples.

Also note that the order of operations need to be fixed (effect = comes first) and that world coordinate is physical (RAS) coordinate and not IJK. You need to convert to RAS to IJK before inserting the point coordinates into ijkPoints.

1 Like

Thank you! I found out how to convert the RAS coordinates to IJK coordinates, but we are still having trouble with the effect line:

segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
slicer.mrmlScene.AddNode(segmentEditorNode)
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
segmentEditorWidget.setActiveEffectByName(“Local Threshold”)
effect = segmentEditorWidget.activeEffect()
effect.self().apply(fidIJK)

The setActiveEffectByName line(and lines where we setParameters after it) still have errors regarding attributes and identifiers. Do you have any idea why @lassoan?

1 Like

Can you send the link to your module’s source code?

2 Likes