Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 69 additions & 12 deletions SimpleFilters/SimpleFilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,23 @@ def setup(self):
hlayout.addWidget(self.applyButton)
self.layout.addLayout(hlayout)

#
# Advanced Area
#
advancedCollapsibleButton = ctk.ctkCollapsibleButton()
advancedCollapsibleButton.text = "Advanced"
advancedCollapsibleButton.collapsed = True
self.layout.addWidget(advancedCollapsibleButton)

# Layout within the advanced collapsible button
advancedFormLayout = qt.QFormLayout(advancedCollapsibleButton)

self.showOutputCheckbox = qt.QCheckBox()
self.showOutputCheckbox.checked = True
self.showOutputCheckbox.toolTip = "Automatically show output volume in slice views and fit slices to volume after execution is completed."
self.showOutputCheckbox.connect('toggled(bool)', self.onShowOutputCheckboxToggled)
advancedFormLayout.addRow("Auto-show output:", self.showOutputCheckbox)

# connections
self.restoreDefaultsButton.connect('clicked(bool)', self.onRestoreDefaultsButton)
self.applyButton.connect('clicked(bool)', self.onApplyButton)
Expand Down Expand Up @@ -290,6 +307,14 @@ def onApplyButton(self):
self.filterParameters.prerun()

self.logic = SimpleFiltersLogic()
self.logic.showOutput = self.showOutputCheckbox.checked

if self.filterParameters.outputSelector.currentNode() is None:
# create a new output volume
if self.filterParameters.outputLabelMap:
self.filterParameters.outputSelector.addNode("vtkMRMLLabelMapVolumeNode")
else:
self.filterParameters.outputSelector.addNode("vtkMRMLScalarVolumeNode")

self.printPythonCommand()

Expand Down Expand Up @@ -320,6 +345,11 @@ def onCancelButton(self):
self.logic.abort = True


def onShowOutputCheckboxToggled(self, checked):
if self.logic:
self.logic.showOutput = checked


def onLogicEventStart(self):
self.filterStartTime = time.time()
self.currentStatusLabel.text = "Running"
Expand Down Expand Up @@ -365,6 +395,7 @@ def __init__(self):
self.main_queue_running = False
self.thread = threading.Thread()
self.abort = False
self.showOutput = True


def __del__(self):
Expand Down Expand Up @@ -438,13 +469,37 @@ def thread_doit(self,sitkFilter,*inputImages):
self.main_queue.put(lambda img=img:self.updateOutput(img))

except Exception as e:
import traceback
traceback.print_exc()

if hasattr(e, 'message'):
msg = e.message
else:
msg = str(e)

# Check if this is a pixel type error and retry with float cast
if re.search(r'Pixel type:.*is not supported', msg):
try:
print("This filter is not compatible with the pixel type of the input images. Attempting to retry filter after casting all input images to float.")

# Cast all input images to float
floatImages = [sitk.Cast(img, sitk.sitkFloat32) for img in inputImages]
img = sitkFilter.Execute(*floatImages)

if not self.abort:
self.main_queue.put(lambda img=img:self.updateOutput(img))
return
except Exception as e2:
import traceback
traceback.print_exc()
if hasattr(e2, 'message'):
msg = e2.message
else:
msg = str(e2)

else:
# It is some other error, just log it
import traceback
traceback.print_exc()

self.abort = True

self.yieldPythonGIL()
Expand Down Expand Up @@ -502,21 +557,22 @@ def main_queue_process(self):
def updateOutput(self,img):

node = slicer.mrmlScene.GetNodeByID(self.outputNodeID)

# Volume is temporarily set to empty during reading from file, pause rendering to avoid warnings
with slicer.util.RenderBlocker():
sitkUtils.PushVolumeToSlicer(img, node)

applicationLogic = slicer.app.applicationLogic()
selectionNode = applicationLogic.GetSelectionNode()
if self.showOutput:
applicationLogic = slicer.app.applicationLogic()
selectionNode = applicationLogic.GetSelectionNode()

if self.outputLabelMap:
selectionNode.SetReferenceActiveLabelVolumeID(node.GetID())
else:
selectionNode.SetReferenceActiveVolumeID(node.GetID())
if self.outputLabelMap:
selectionNode.SetReferenceActiveLabelVolumeID(node.GetID())
else:
selectionNode.SetReferenceActiveVolumeID(node.GetID())

applicationLogic.PropagateVolumeSelection(0)
applicationLogic.FitSliceToAll()
applicationLogic.PropagateVolumeSelection(0)
applicationLogic.FitSliceToAll()

def run(self, filter, outputMRMLNode, outputLabelMap, *inputs):
"""
Expand Down Expand Up @@ -864,8 +920,9 @@ def create(self, json):
self.outputSelector.showHidden = False
self.outputSelector.showChildNodeTypes = False
self.outputSelector.baseName = json["name"]+" Output"
self.outputSelector.setMRMLScene( slicer.mrmlScene )
self.outputSelector.setToolTip( "Pick the output to the algorithm." )
self.outputSelector.noneDisplay = "(Create New Volume)"
self.outputSelector.setMRMLScene( slicer.mrmlScene )

self.outputSelector.connect("nodeActivated(vtkMRMLNode*)", lambda node:self.onOutputSelect(node))
self.widgetConnections.append((self.outputSelector, "nodeActivated(vtkMRMLNode*)"))
Expand Down
2 changes: 1 addition & 1 deletion SimpleFilters/Testing/Python/SimpleFiltersModuleTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def delayDisplay(self,message,msec=1000):
self.info.exec_()

# make sure all events are processed before moving on
qt.QApplication.flush()
slicer.app.processEvents()

def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
Expand Down