Hi there,
I’m new to 3D Slicer.
Currently, I am trying to develop a python scripted module in 3D Slicer.
One of the features is to control the threshold of the volume rendering image through a slider.
In other words, I want to use python to achieve the same effect as the ‘Threshold’ slider in the ‘Volumes’ module.
As shown in the picture is my goal:
Under the premise that the value in the check box on the right is set to ‘Manual’ and the ‘Synchronize with Volumes module’ in the ‘Volume Rendering’ module is checked, the user can see the volume rendering image synchronized with the slider.
I found that the ‘Volumes’ module is a Loadable module written in C++. How can I achieve my target effect with python(Just for this single feature)?
I have found the corresponding method (C++) for ‘Threshold’ in the ‘Volumes’ module according to the prompts on this page: https://slicer.readthedocs.io/en/latest/developer_guide/python_faq.html#how-to-find-a-python-function-for-any-slicer-features.
void qMRMLVolumeThresholdWidget::setAutoThreshold(int autoThreshold)
{
this->setAutoThreshold(static_cast<ControlMode>(autoThreshold));
}
// --------------------------------------------------------------------------
void qMRMLVolumeThresholdWidget::setAutoThreshold(ControlMode autoThreshold)
{
Q_D(qMRMLVolumeThresholdWidget);
if (!d->VolumeDisplayNode)
{
return;
}
int oldAuto = d->VolumeDisplayNode->GetAutoThreshold();
int oldApply = d->VolumeDisplayNode->GetApplyThreshold();
int disabledModify = d->VolumeDisplayNode->StartModify();
if (autoThreshold == qMRMLVolumeThresholdWidget::Off)
{
d->VolumeDisplayNode->SetApplyThreshold(0);
}
else
{
d->VolumeDisplayNode->SetApplyThreshold(1);
d->VolumeDisplayNode->SetAutoThreshold(
autoThreshold == qMRMLVolumeThresholdWidget::Auto ? 1 : 0);
}
if (!oldApply && autoThreshold == qMRMLVolumeThresholdWidget::Manual)
{
// Previously the threshold was turned off and now it is set to manual.
// Since the default threshold range is VTK_SHORT_MIN to VTK_SHORT_MAX,
// we don't want these values to appear on the GUI but instead set
// the threshold range to the full scalar range of the volume (because
// this corresponds to the previous state of the thresholding: having
// the full scalar range of the volume in the threshold range).
d->VolumeDisplayNode->SetThreshold(d->DisplayScalarRange[0], d->DisplayScalarRange[1]);
}
d->VolumeDisplayNode->EndModify(disabledModify);
if (oldAuto != d->VolumeDisplayNode->GetAutoThreshold() ||
oldApply != d->VolumeDisplayNode->GetApplyThreshold())
{
emit this->autoThresholdValueChanged(autoThreshold);
}
}
However, I’m not sure if the above code(https://github.com/Slicer/Slicer/blob/c20e0a7849889e17224a5e605cc1df662b5ad977/Libs/MRML/Widgets/qMRMLVolumeThresholdWidget.cxx) is accurate or not and I’m confused about how to convert it into Python code next.
In addition, I also found another method by searching online:
displayNode->SetFollowVolumeDisplayNode(follow ? 1 : 0);
How can I integrate it into my code?
The following is the code of the slider I implemented in Python, FYI:
#
# thresholdRangeSlider
#
self.thresholdRangeSlider1 = ctk.ctkRangeWidget()
self.thresholdRangeSlider1.minimum = 0.0
self.thresholdRangeSlider1.maximum = 3522.0
self.thresholdRangeSlider1.singleStep = 0.1
self.thresholdRangeSlider1.minimumValue = 10.0
self.thresholdRangeSlider1.maximumValue = 3522.0
parametersFormLayout.addRow("Thresholds:", self.thresholdRangeSlider1)
# connections
self.thresholdRangeSlider1.connect('currentNodeChanged(vtkMRMLNode*)', self.onSlider)
# Custom function
def onSlider(self):
Should I implement my target feature in the custom ‘onSlider’ function? is that right? In addition, I am not sure whether the first parameter’currentNodeChanged(vtkMRMLNode*)’ in the ‘connect’ method is correct.
If possible, could you please give me some specific guidance to help me run in the right way, thank you very much for your help in advance!
Best regards,
Charles