Running Slicer without GUI?

I’ve installed Slicer on an Ubuntu cloud instance (AWS/GCP) and I want to run it with a self-made extension and no GUI… Is there documentation on the slicer site that I’m missing to be able to do this? I’ve found info about using Python to do things, but I want to essentially go: Slicer, do this task, using this folder, and put the output in this location.

Is docker an option for you? Here’s an example of a command line tool based on Slicer and this is another one. If you don’t use docker you would need a different way of having a desktop to access all of Slicer. If you don’t need graphics you might be able to get by with PythonSlicer and access just logic classes.

Maybe you can describe your processing task in more detail if you need more explicit suggestions.

I have dicom images I want to turn into OBJ models using an extension that’s already made. My idea was to use a form to upload the images to AWS/GCP and there have Slicer take them as input with the extension and then output the obj. The extension segments the file to create a 3D render.

I’ve never worked with docker, but I can check it out as well as PythonSlicer.

If you don’t want to learn Javascript to create a frontend, then it is also an option to create a web application using Slicer Jupyter notebook and Voila.

You can use standard IPython widgets for file upload/download/display. Voila takes care of selectively locking down the notebook, so users can still interact with widgets but they will not see or able to modify code in the notebook.

See a number of example web applications here:

https://voila-gallery.org/

They are all hosted on the free binder service and a new container is created for each user from scratch, so initial loading of the page may take a minute, but of if you set up your own server then page loading should be instantaneous.

From my recent experience on headless Slicer on Ubuntu, I think something like the following on the command line could be one way to go:

xvfb-run -a /slicer_path/Slicer --no-splash --python-script mycode.py

here “xvfb” is a package you need to install on your Ubuntu instance. Running “xvfb-run program” will start “program” with a dummy graphical interface, otherwise it complains that it can’t connect to X server.

If it works for you, you can put everything you want in mycode.py.

5 Likes

Hi Lenny, this isn’t directly related to your question, but I am working on a similar project (DICOM -> OBJ). Is the extension that you are using something that is custom to your project or an open source extension. If its open source, would you mind sharing a link to it?

Thanks,
Jeff

thanks! it works like magic

1 Like

Hi, I have been working on developing a web app as suggested by @lassoan following this link:

. I successfully created a Slicer Jupyter notebook. However, on integrating with Voila I have some issues.

The application fails to launch, even after several tries.

This happens as soon as I add “docker” and “start” file in my repository.

Am I missing some thing? Can you provide any example repository which works with slicer jupyter notebook and voila.

For your reference, my repository link is:

Does everything work well (Slicer kernel starts without problems) if you don’t use Voila?

Thank you for your reply @lassoan. Yes, slicer works well. I just need to integrate it with Viola. I think I am missing something in the Docker file.
I have tried slicer in my other repository. It works well. I am following your repository. Just the integration with viola is a bit difficult.

hi @lassoan . This is the example I have been following to generate my own repository and notebook. It works fine. The problem arises only when I try to run the app through Voila.

Can you help me with this?
Thanks alot

For reference, this has been discussed at the weekly developer meeting: 2021.04.06 Hangout - #3 by jcfr

I had trouble importing DICOM files using xvfb. I kept receiving database not open/filenotfound errors when using the DICOMUtils.TemporaryDICOMDatabase(). I was running ubuntu 21 on GCS. In case anyone else has this issue, manually setting the database solved the issue.

dicomDataDir = 'path/to/dicoms'
dbDir = 'path/to/database'

db = ctk.ctkDICOMDatabase()
db.openDatabase(dbDir)
slicer.dicomDatabase = db

import DICOMLib
DICOMLib.importDicom(dicomDataDir)
dicomFiles = slicer.util.getFilesInDirectory(dicomDataDir)
loadablesByPlugin, loadEnabled = DICOMLib.getLoadablesFromFileLists([dicomFiles])
loadedNodeIDs = DICOMLib.loadLoadables(loadablesByPlugin)

Could you please copy here the command that launches Slicer and the full console output?

Yes here they are. I tried the method in the script repository and also a second attempt from here:Fastest way to load DICOM - #2 by lassoan

slicer_load_scans_debug.py

dicomDataDir = 'path/to/dicoms'

loadedNodeIDs = []

from DICOMLib import DICOMUtils

with DICOMUtils.TemporaryDICOMDatabase() as db:
	DICOMUtils.importDicom(dicomDataDir, db)
	patientUIDs = db.patients()
	for patientUID in patientUIDs:
		loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))

Command

xvfb-run -a Slicer-4.11.20210226-linux-amd64/Slicer --no-splash --no-main-window --python-script 'startup/slicer_load_scans_debug.py'

Output:


qSlicerSequencesModulePrivate::addToolBar: no main window is available, toolbar is not added
Switching to temporary DICOM database: /tmp/Slicer-neureal2020/20211107_173523_TempDICOMDatabase
TagCacheDatabase adding table
Patient ID is empty, using studyInstanceUID (#########) as patient ID # repeats x169
"DICOM indexer has successfully inserted 169 files [0.14s]"
"DICOM indexer has successfully processed 169 files [0.18s]"
Patient ID is empty, using studyInstanceUID (#########) as patient ID #repeats x169
"DICOM indexer has updated display fields for 169 files [0.07s]"
Loading with imageIOName: GDCM
vtkITKArchetypeImageSeriesReader::ExecuteInformation: Archetype file /tmp/Slicer-user/scan_name_TempDICOMDatabase/path/to/dicoms/FILE12 does not exist.
Algorithm vtkITKArchetypeImageSeriesScalarReader(0x5826580) returned failure for request: vtkInformation (0x58278e0)
  Debug: Off
  Modified Time: 128579
  Reference Count: 1
  Registered Events: (none)
  Request: REQUEST_INFORMATION
  ALGORITHM_AFTER_FORWARD: 1
  FORWARD_DIRECTION: 0
Could not read scalar volume using GDCM approach.  Error is: FileNotFoundError
Loading with imageIOName: DCMTK
vtkITKArchetypeImageSeriesReader::ExecuteInformation: Archetype file Archetype file /tmp/Slicer-user/scan_name_TempDICOMDatabase/path/to/dicoms/FILE12 does not exist.
Algorithm vtkITKArchetypeImageSeriesScalarReader(0x38bdd60) returned failure for request: vtkInformation (0x5a45430)
  Debug: Off
  Modified Time: 128662
  Reference Count: 1
  Registered Events: (none)
  Request: REQUEST_INFORMATION
  ALGORITHM_AFTER_FORWARD: 1
  FORWARD_DIRECTION: 0
Could not read scalar volume using DCMTK approach.  Error is: FileNotFoundError

This was the second attempt:

slicer_load_scans_debug.py

import DICOMLib
import re
DICOMLib.importDicom(dicomDataDir)
dicomFiles = slicer.util.getFilesInDirectory(dicomDataDir)
loadablesByPlugin, loadEnabled = DICOMLib.getLoadablesFromFileLists([dicomFiles])
loadedNodeIDs = DICOMLib.loadLoadables(loadablesByPlugin)
for loadedNodeID in loadedNodeIDs:
    node = slicer.mrmlScene.GetNodeByID(loadedNodeID)
    safeFileName = re.sub(r'(?u)[^-\w.]', '', node.GetName().strip().replace(' ', '_'))
    slicer.util.saveNode(node, '{0}/{1}.nrrd'.format(outputDir, safeFileName))

Output

qSlicerSequencesModulePrivate::addToolBar: no main window is available, toolbar is not added
Patient ID is empty, using studyInstanceUID (#########) as patient ID # repeats x169
"DICOM indexer has successfully inserted 169 files [0.14s]"
"DICOM indexer has successfully processed 169 files [0.18s]"
Patient ID is empty, using studyInstanceUID (#########) as patient ID #repeats x169
"DICOM indexer has updated display fields for 169 files [0.07s]"
Loading with imageIOName: GDCM
Could not load  "/tmp/Slicer-user/scan_name_TempDICOMDatabase/path/to/dicoms/FILE12" 
DCMTK says:  No such file or directory
File /tmp/Slicer-user/scan_name_TempDICOMDatabase/path/to/dicoms/FILE12 could not be initialized.
No geometry information available for DICOM data, skipping corner calculations

It goes on to give me errors related to saving the .nrrd. I could not reproduce the database not found error, apologies.

Please try with the latest Slicer Preview Release.

If it fails exactly the same way then check if there referred /tmp/Slicer-user/scan_name_TempDICOMDatabase/path/to/dicoms/FILE12 file exists or not.

Thanks for your reply. I retried on the latest Preview Release and I got the same error with an additional line saying “Failed to find patient…”:

"DICOM indexer has successfully processed 169 files [0.18s]"
Patient ID is empty, using studyInstanceUID (#########) as patient ID #repeats x169
Failed to find patient with PatientsName= and PatientID=

I made copies of the DICOM files and added PatientID and PatientName metadata. I reran and got the same error without that extra line, so it must be unrelated.

With regards to your second comment, I used the following code and the file does not exist.

with DICOMUtils.TemporaryDICOMDatabase() as db:
	DICOMUtils.importDicom(dicomDataDir, db)
	os.system('ls {}'.format(db.databaseDirectory))

Output:
ctkDICOM.sql
ctkDICOMTagCache.sql

Also just to be clear, I ran the same slicer_load_scans_debug.py with a GUI on my laptop and it loaded the scans without errors.

Your first example did not contain the node saving part. The second example used the Slicer DICOM database. So, I created a new script (based on the example in the Slicer script repository + adding your node saving) and it worked well for me:

dicomDataDir = r"c:\tmp\eclipse-8.1.20-phantom-ent-ctonly"
outputDir = r"c:\tmp\output"

from DICOMLib import DICOMUtils
import re

try:
    loadedNodeIDs = []  # this list will contain the list of all loaded node IDs
    from DICOMLib import DICOMUtils
    with DICOMUtils.TemporaryDICOMDatabase() as db:
        DICOMUtils.importDicom(dicomDataDir, db)
        patientUIDs = db.patients()
        for patientUID in patientUIDs:
            loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))

    for loadedNodeID in loadedNodeIDs:
        node = slicer.mrmlScene.GetNodeByID(loadedNodeID)
        safeFileName = re.sub(r'(?u)[^-\w.]', '', node.GetName().strip().replace(' ', '_'))
        print(f"Saving {safeFileName}...")
        slicer.util.saveNode(node, '{0}/{1}.nrrd'.format(outputDir, safeFileName))

finally:
    exit()

I’ve executed by this command (powershell and tee are used to redirect the output so that I can see it, but should not be needed on linux/macOS):

powershell ".\Slicer.exe --no-splash --no-main-window --python-script 'c:\Users\andra\AppData\Local\NA-MIC\Slicer 4.13.0-2021-11-03\slicer_load_scans_debug.py' 2>&1 | tee out.txt"

I saw that you used relative paths - I’m not sure what they should be resolved to, so I used absolute paths everywhere. You may try to do that, too.