In the middle of the desert you can say anything you want
EDIT: this may be all wrong, in the debugger I can just edit the code and it gets automatically used by slicer — logical, since it’s just a CLI script.
It’s the .xml with the interface that’s problematic and it can’t be reloaded using the method below, or at least I couldn’t.
A scriptedcli module imported to Slicer doesn’t show for me the usual “reload” buttons as seen in scripted modules in dev. mode. To develop, I need my changes I need to reload it w/o restarting 3dslicer.
Based on this more complete example1 linked in the script repository2
>>> mpath = "/full/path/to/the/my_module.py"
>>> factoryManager = slicer.app.moduleManager().factoryManager()
>>> factoryManager.registerModule(qt.QFileInfo(mpath))
>>> factoryManager.loadModules(["my_module"])
True
BONUS:
import pydevd_pycharm
pydevd_pycharm.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True)
os.getpid()
is my friend/opt/pycharm-professional/debug-eggs/pydevd-pycharm.egg
Loads the module automatically (for some reason doing it manually doesn’t preserve it across restarts?..)
Slicer --additional-module-path /path/to/my/extension/one/lower/than/what/i/would/pick/in/Slicer/GUI
logging.warning("test")
in the python console and it worksDifferent types of modules exist: Module Overview — 3D Slicer documentation
In the first tests there was a lot of latency.
Solution: CLI modules (not extensions) that can run in the background and whose status can be queried, which can be added to new extension from extension editor.
Now I understad this better:
scripted
. It’s the sample thresholding extension
I hope it’s the same as type CLI, but only with python
Is a CLI script w/ an XML that has module metadata + examples
Adding it added it to CMakeLists.xml: add_subdirectory(my_scripted_cli)
python dev tools actually show the CLI used to run a CLI module!
can’t debug it the usual way, I guess I’ll have to add the pydevd-pycharm things to the code
[VTK] /opt/3dslicer/bin/python-real /home/.../cli_model_service.py /tmp/Slicer-sh/IACHCI_vtkMRMLScalarVolumeNodeD.nrrd 1 /tmp/Slicer-sh/IACHCI_vtkMRMLScalarVolumeNodeF.nrrd
Slicer/Docs/developer_guide/parameter_nodes/gui_creation.md at main · Slicer/Slicer seems interesting
CLI modules have an interface specified by the .xml file, and the interface is generated based on it
Bits about the XML
channel
is either input
or output
, and only for pics.index
If I read the volume as volume, it uses the .nrrd
file extension by default — and I want .nii
Module from console with arguments - Support - 3D Slicer Community
Slicer.exe --python-code "selectModule('SampleData'); getModuleGui('SampleData').setCategoryVisible('BuiltIn', False)"
Script repository — 3D Slicer documentation:
# Create a new directory where the scene will be saved into
import time
sceneSaveDirectory = slicer.app.temporaryPath + "/saved-scene-" + time.strftime("%Y%m%d-%H%M%S")
if not os.access(sceneSaveDirectory, os.F_OK):
os.makedirs(sceneSaveDirectory)
outputSegmentation.AddDefaultStorageNode()
outputSegmentation.GetStorageNode().SetFileName(output_segmentation_path)
outputSegmentation.GetStorageNode().ReadData(outputSegmentation)
Main links
slicerrc.py is a thing! sample: 3D-Slicer-Scripts/.slicerrc.py at master · jzeyl/3D-Slicer-Scripts · GitHub
Slicer custom application deployment to many computers - Development - 3D Slicer Community
SlicerQReads.exe --python-code "folder='S:\SlicerQREADS\TestImages'; import os; slicer.util.loadVolume(folder + '/' + os.listdir(folder)[0], {'singleFile': False})"
Slicer.exe --python-script "/full/path/to/myscript.py" --no-splash --no-main-window
3Slicer can run in Docker4
Slicer can run in webbrowser5
Slicer can run in jupyter5, including partially (e.g. only a single view etc!)
Slicer --help
:
--testing Activate testing mode. It implies --disable-settings and --ignore-slicerrc. (default: false)
--disable-python Disable python support. This is equivalent to build the application with Slicer_USE_PYTHONQT=OFF.
--python-script Python script to execute after slicer loads.
--python-code Python code to execute after slicer loads.
-c Python code to execute after slicer loads. By default, no modules are loaded and Slicer exits afterward.
--ignore-slicerrc Do not load the Slicer resource file (~/.slicerrc.py).
--additional-module-path Additional module path to consider when searching for modules to load.
--additional-module-paths List of additional module path to consider when searching for modules to load.
Slicer modules — todo, CLI things with easy arguments
Slicer extensions/modules creation
Extension manager
CI/CD exists for extensions published officially
Misc:
Script repository — 3D Slicer documentation has this:
This code snippet can be useful for sharing code in development without requiring a restart of Slicer.
Fazit:
Other bits
Run Slicer in your web browser - as a Jupyter notebook or as a full application - Announcements - 3D Slicer Community ↩︎
GitHub - Slicer/SlicerDocker: Build, package, test, and run 3D Slicer and Slicer Extensions in Docker. ↩︎
Run Slicer in your web browser - as a Jupyter notebook or as a full application - Announcements - 3D Slicer Community ↩︎ ↩︎
inotifywait(1) - Linux man page
#!/bin/sh
while inotifywait --format '%:e %f' p.* *.bib; do
sleep 1 # files get moved often
echo "rsync!"
rsync -avzirh --progress p.* *.bib me@server.net:dir
done
boltctl monitor
shows changes as they happens — nice when something breaks. I used to do a lot of watch boltctl list
before in this exact scenario
(having a monitor
subcommand in your thing says a lot about stuff, actually, — the best interpretation is that it’s written with developers in mind)
Very proud of this idea, haha :)
For absolute positioned elements one needs to “guess” the correct sizes etc., may not be trivial. Using a pixel ruler won’t help because the .absolute coords don’t map to the screen ones.
Solution:
.grid {
// https://stackoverflow.com/questions/4191260/drawing-a-grid-using-css
background-image:
repeating-linear-gradient(lightblue 0 2px, transparent 2px 100%),
repeating-linear-gradient(90deg, lightblue 0 2px, transparent 2px 100%);
background-size: 50px 50px;
//border: 2px solid red;
}
.smallgrid {
background-image:
repeating-linear-gradient(#ccc 0 1px, transparent 1px 100%),
repeating-linear-gradient(90deg, #ccc 0 1px, transparent 1px 100%);
background-size: 10px 10px;
width: 100%;
height: 100%;
}
::::: {.absolute left=0 right=0 top=0 bottom=0 .grid}
::: {.smallgrid}
:::
:::::
It’s not exactly aligned but close enough to judge the widths and heights involved!
Rectangle in the pic is:
:::: {.redrect .absolute right=200 top=130 width=200 height=100}
::::
(And the small grid can be omitted if not needed by removing the div in the middle. )
For bonus points, can be saved as a file and included if needed:
{\{< include ../_shared/smallgrid.qmd >}\}
ALSO:
// show the border of the slide
.reveal .slides {
border: 1px dashed red;
}
DAMN.
:::: {layout="1,1,1],[1],[1,1,1" layout-valign="center"}
if it’s a layout I do get a valign thing. I just have to use layouts, not columns. Damn.
This doesn’t work on SVGs for me:
![](images/02/svgs/02_seqsiii.svg){.absolute top=0 left=0}
This does:
::: {.absolute top=0 left=0}
![](images/02/svgs/02_seqsiii.svg)
:::
SO.
One can literally generate a plot w/ graphviz, export as svg, open and edit in inkscape, save as optimized svg, paste into quarto, and manually add the correct class="fragment" data-fragment-index=4
bits to the relevant groups.
Insert with the usual {=html} thing.
Damn.
almost works with quarto, except that line.position needs to be called on slide change — ergo likely won’t work in pdf export mode.