38 def setupOptionsFrame(self):
39 operationLayout = qt.QVBoxLayout()
49 self.
scriptedEffect.addLabeledOptionsWidget(_(
"Use current segment as:"), operationLayout)
60 self.
shellThicknessLabel.setToolTip(_(
"Closest achievable thickness. Constrained by the segmentation's binary labelmap representation spacing."))
62 shellThicknessFrame = qt.QHBoxLayout()
69 _(
"Apply hollow effect to all visible segments in this segmentation node. This operation may take a while."))
75 self.
applyButton.objectName = self.__class__.__name__ +
"Apply"
76 self.
applyButton.setToolTip(_(
"Makes the segment hollow by replacing it with a thick shell at the segment boundary."))
95 def getShellThicknessPixel(self):
96 selectedSegmentLabelmapSpacing = [1.0, 1.0, 1.0]
97 selectedSegmentLabelmap = self.
scriptedEffect.selectedSegmentLabelmap()
98 if selectedSegmentLabelmap:
99 selectedSegmentLabelmapSpacing = selectedSegmentLabelmap.GetSpacing()
101 shellThicknessMM = abs(self.
scriptedEffect.doubleParameter(
"ShellThicknessMm"))
102 shellThicknessPixel = [math.floor(shellThicknessMM / selectedSegmentLabelmapSpacing[componentIndex])
for componentIndex
in range(3)]
103 return shellThicknessPixel
105 def updateGUIFromMRML(self):
106 shellThicknessMM = self.
scriptedEffect.doubleParameter(
"ShellThicknessMm")
124 selectedSegmentLabelmapSpacing = [1.0, 1.0, 1.0]
125 selectedSegmentLabelmap = self.
scriptedEffect.selectedSegmentLabelmap()
126 if selectedSegmentLabelmap:
127 selectedSegmentLabelmapSpacing = selectedSegmentLabelmap.GetSpacing()
129 if shellThicknessPixel[0] < 1
or shellThicknessPixel[1] < 1
or shellThicknessPixel[2] < 1:
134 self.
shellThicknessLabel.text = _(
"Actual:") +
" {} x {} x {} mm ({}x{}x{} pixel)".format(*thicknessMM, *shellThicknessPixel)
141 applyToAllVisibleSegments = qt.Qt.Unchecked
if self.
scriptedEffect.integerParameter(
"ApplyToAllVisibleSegments") == 0
else qt.Qt.Checked
164 def getShellThicknessMM(self):
165 selectedSegmentLabelmapSpacing = [1.0, 1.0, 1.0]
166 selectedSegmentLabelmap = self.
scriptedEffect.selectedSegmentLabelmap()
167 if selectedSegmentLabelmap:
168 selectedSegmentLabelmapSpacing = selectedSegmentLabelmap.GetSpacing()
171 shellThicknessMM = [abs((shellThicknessPixel[i]) * selectedSegmentLabelmapSpacing[i])
for i
in range(3)]
173 if shellThicknessMM[i] > 0:
174 shellThicknessMM[i] = round(shellThicknessMM[i], max(int(-math.floor(math.log10(shellThicknessMM[i]))), 1))
175 return shellThicknessMM
181 def processHollowing(self):
184 selectedSegmentLabelmap = self.
scriptedEffect.selectedSegmentLabelmap()
188 thresh = vtk.vtkImageThreshold()
189 thresh.SetInputData(selectedSegmentLabelmap)
190 thresh.ThresholdByLower(0)
191 thresh.SetInValue(backgroundValue)
192 thresh.SetOutValue(labelValue)
193 thresh.SetOutputScalarType(selectedSegmentLabelmap.GetScalarType())
196 shellThicknessMM = abs(self.
scriptedEffect.doubleParameter(
"ShellThicknessMm"))
200 margin = vtkITK.vtkITKImageMargin()
201 margin.SetInputConnection(thresh.GetOutputPort())
202 margin.CalculateMarginInMMOn()
204 spacing = selectedSegmentLabelmap.GetSpacing()
205 voxelDiameter = min(selectedSegmentLabelmap.GetSpacing())
206 if shellMode == MEDIAL_SURFACE:
207 margin.SetOuterMarginMM(0.5 * shellThicknessMM)
208 margin.SetInnerMarginMM(-0.5 * shellThicknessMM + 0.5 * voxelDiameter)
209 elif shellMode == INSIDE_SURFACE:
210 margin.SetOuterMarginMM(shellThicknessMM + 0.1 * voxelDiameter)
211 margin.SetInnerMarginMM(0.0 + 0.1 * voxelDiameter)
212 elif shellMode == OUTSIDE_SURFACE:
213 margin.SetOuterMarginMM(0.0)
214 margin.SetInnerMarginMM(-shellThicknessMM + voxelDiameter)
216 modifierLabelmap.DeepCopy(margin.GetOutput())
219 modifierLabelmap.ShallowCopy(margin.GetOutput())
222 self.
scriptedEffect.modifySelectedSegmentByLabelmap(modifierLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet)
231 qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)
234 applyToAllVisibleSegments = int(self.
scriptedEffect.parameter(
"ApplyToAllVisibleSegments")) != 0 \
235 if self.
scriptedEffect.parameter(
"ApplyToAllVisibleSegments")
else False
237 if applyToAllVisibleSegments:
239 inputSegmentIDs = vtk.vtkStringArray()
240 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
241 segmentationNode.GetDisplayNode().GetVisibleSegmentIDs(inputSegmentIDs)
243 selectedStartSegmentID = self.
scriptedEffect.parameterSetNode().GetSelectedSegmentID()
244 if inputSegmentIDs.GetNumberOfValues() == 0:
245 logging.info(
"Hollow operation skipped: there are no visible segments.")
248 for index
in range(inputSegmentIDs.GetNumberOfValues()):
249 segmentID = inputSegmentIDs.GetValue(index)
251 .format(segmentName=segmentationNode.GetSegmentation().GetSegment(segmentID).GetName()))
252 self.
scriptedEffect.parameterSetNode().SetSelectedSegmentID(segmentID)
255 self.
scriptedEffect.parameterSetNode().SetSelectedSegmentID(selectedStartSegmentID)
260 qt.QApplication.restoreOverrideCursor()