Is there a way to wait until certain condition are met before continuing and deleting nodes in using a python script

I am currently going through directories, grabbing fcsv and image pairs, and then loading them into slicer using a python script.

# Image/fcsv loading
[success, markupNode] = slicer.util.loadMarkupsFiducialList(fcsv, returnNode=True)
[success, imageNode] = slicer.util.loadVolume(image, returnNode=True)

#want to wait here until some condition is met

# Node deletion
slicer.mrmlScene.RemoveNode(markupNode)
slicer.mrmlScene.RemoveNode(imageNode)

My goal is to be able to somehow wait inbetween the reading and the removing of the node, so I can check the fcsv files for accuracy and edit them if possible.

Is there a way to do this?

I tried using a simple input() command to wait for an enter keypress , but I get an ā€˜EOFError: EOF when reading a lineā€™ when trying to do this

It looks like you want to continuous the processing once the user had an opportunity to validate the content of the files by inspecting the loaded image and markups.

To achieve this, you could look at what is done https://github.com/JoostJM/SlicerCaseIterator

Thanks, Ill take a look at this.

I found a workaround using raw_input() that waits for an enter press command, but the embedded python in 3d slicer requires you to enter 3 characters before the input is interpreted as a string/keypress.

otherwise it gives you an EOFError, which im thinking is because it places the start of the user input before the ā€˜>>>ā€™ that ive seen used by python in other places

Hi,

Iā€™m facing the same problem. I have an script that helps the user through various steps. For example:

def functionName():
  # step1:
  _Ask the user to segment
  
  # step2:
  _Save segmentation
  
  # step3:
  _Ask the user to place tow fiducials
  
  # step4:
  _Use those fiducials to generate a centerline
  
  # step5:
  _Save results

I need my code to wait between step1 and step2 and between step3 and step4, since I need the user to manually segment or place the control points. Now Iā€™m using (ex) input("Place fiducial points and press key to continue...") but I donā€™t want the user to come back to the python interactor each time. Instead I want a key shortcut ā€œcontinueā€.

I know I can implement this using:

shortcutNext = qt.QShortcut(slicer.util.mainWindow())
shortcutNext.setKey(qt.QKeySequence('C'))

shortcutNext.connect('activated()', someFunction)

But then I guess I need to rewrite the code in functionName() and replace it with different funcions like step1(), step2()ā€¦ and call them in order depending the number of times the user has pressed ā€œCā€. Am I right? Is there another posibility similar to input() that can be in the same place in the code?

Iā€™m thinking about something like:

while(not continue):
   wait

but slicer gets blocked.

Your code could be event driven, in the sense that you should be observing the scene for nodes being added or modified and then you can move through from step to step. Since Slicer operates asynchronously you can implement these state changes either base on events from the scene or from users pressing buttons to move from step to step and you can validate if the step change is allowed based on what data is in the scene.

Another solution would be to develop a python module that would allow you to carry out the steps via GUI. You would still need to break up the function logic to the various steps, but you would gain making it easy to have others carry out your process. There is definitely a bit of a learning curve getting started, but the working example module code provided by the Extension Wizard module is a great starting point if you want to try heading in this direction.

Another alternative is to have the user do the segmentation and place the fiducials first, and run your code at that point, with the segmentation and fiducials is inputs. That way there arenā€™t any steps your code has to wait for. It can save the segmentation to a file, use the fiducials to generate a centerline (I presume using the segmentation), and save the results.

1 Like

Thanks. Where I can find an example of this kind of implementation?

Iā€™ll take a look at the Extension Wizard Module, if you know where to find documentation or examples, it would be great :slight_smile:

Basically all modules work this way. For example if you look at the Endoscopy code you can see that some of the buttons arenā€™t enabled until some of the prerequisite combo boxes have valid values selected. So in a similar way, your module could have a combo box to select a segmentation and a button that when clicked creates a segmentation and shows the segment editor widget. The use would then need to perform the segmentation and then push a button to create the fiducials. You just donā€™t enable the next steps until the input data is available.

1 Like

The PerkLab programming tutorial is a good way to get started with Python scripting in Slicer. You can find the link from the Slicer developer training page.

1 Like