Headless DICOM, loadSeriesByUID fails

Hi everyone,

I’m trying to load DICOM files to scene (within a headless CI-pipeline) by using DICOMUtils.loadSeriesByUID, as linked here.

However, trying to load the scene fails, although no error is thrown.

Importing the files to the db works, using DICOMUtils.importDicom, as linked here.

> New patient inserted: 1
> New patient inserted as :  1
> Need to insert new study:  "1.2.826.0.1.3680043.2.146.2.20.3103689.1600244093.0"
> Study Added
> Need to insert new series:  "1.3.12.2.1107.5.6.1.2013.31330116120712460953700001577"
> Series Added
> "DICOM indexer has successfully processed 130 files [0.95s]"

The series can also be retrieved:

slicer.dicomDatabase.seriesForStudy(studyList[0])
> ('1.3.12.2.1107.5.6.1.2013.31330116120712460953700001577',)

To load the series, I use:

seriesInstanceUID = '1.3.12.2.1107.5.6.1.2013.31330116120712460953700001577'
ok = utils.loadSeriesByUID([seriesInstanceUID])

The loading does not throw an error, but shows this warning:

> Warning in DICOM plugin Scalar Volume when examining loadable <SeriesName>: Images are not equally spaced (a difference of 3 vs 3 in spacings was detected).  If loaded image appears distorted, enable 'Acquisition geometry regularization' in Application settings / DICOM / DICOMScalarVolumePlugin. Please use caution.

The function returns True, although this seems to be the case even if you import a seriesUID with an invalid UID:

utils.loadSeriesByUID(['1.3.12.2.1107.5.6.1.2013.31330116120712460953700001577'])
> True

utils.loadSeriesByUID(['an invalid seriesUID'])
> True

Either way, after the loading, there are no child items attached to the scene:

shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
sceneID = shNode.GetSceneItemID()
items = vtk.vtkIdList()
shNode.GetItemChildren(sceneID, items)
items.GetNumberOfIds()
> 0

Is this behaviour linked with the newest announcements of decoupling the widget from the logic?
Does anyone have a clue why my approach does not work?

Thanks in advance for any feedback! :slight_smile:

Interesting - this sounds like something that should work. So if you run the same command in the python console with the gui it does load?

Hi @pieper,

Yes exactly, this code works perfectly on my local machine (with GUI), but somehow fails in the pipeline.
Btw. the pipeline uses nightly-master:b54b2ea (link).

Do you think this could be the issue?

With the DICOM browser rework, GUI classes are no more needed for indexing and loading DICOM files, so it should be easier to do DICOM operations on a headless node (you should not need to set up X server, etc). However, not all possible use cases are checked by automated testing so maybe there are some regressions.

Do you run the same script exactly the same way?
Do you launch Slicer using --no-main-window?
Could you provide a minimal example of a complete script that reproduces the issue?

2 Likes

Hi @lassoan,

  1. Yes, the locally run code is also used for our pipeline - and is therefore exactly the same.
  2. We don’t specifically run Slicer, we use ctest to run the tests for our extension within our gitlab-ci.
  3. Sure, the example code below is used for loading the scene:
1.  import DICOMLib.DICOMUtils as utils
2.
3.  databaseFilePath = 'path/to/slicer/database'
4.  slicer.dicomDatabase.openDatabase(databaseFilePath)
5.  if not slicer.dicomDatabase.isOpen:
6.     self.logger.error('Unable to connect to database')
7.        
8.  seriesInstanceUID = '1.3.12.2.1107.5.6.1.2013.31330116120712460953700001577'
9.  ok = utils.loadSeriesByUID([seriesInstanceUID])
10. if not ok:
11.    self.logger.error('Could not load files from database.')
12.
13. shNode = vtkmrmlutils.getSubjectHierarchyNode()
14. studyID = vtkmrmlutils.getStudyIDs()[0]
15. itemID = vtkmrmlutils.getAllFolderChildren(studyID)[0]
16. 
17. return itemID

Previous to this function, files already have been successfully written to the database.

The error-logs for testing the database connection and the loading are both not written. As already mentioned, only the following warning is shown:

Warning in DICOM plugin Scalar Volume when examining loadable 3: CT LU177  3.0  I31s STD: Images are not equally spaced (a difference of 3 vs 3 in spacings was detected).  If loaded image appears distorted, enable 'Acquisition geometry regularization' in Application settings / DICOM / DICOMScalarVolumePlugin. Please use caution.

But there is an error thrown at line 14:

subjectID = vtkmrmlutils.getSubjectIDs()[0]
> IndexError: list index out of range

As an info, our vtkmrmlutils basically wraps all functionality dealing with vtkmrml elements. vtkmrmlutils.getStudyIDs() returns all nodes with Level:Study for the first subject found as a child element of the scene.

shNode = vtkmrmlutils.getSubjectHierarchyNode()
sceneID = shNode.GetSceneItemID()
try:
    subjectID = vtkmrmlutils.getSubjectIDs()[0]
except:
    raise

When trying to find any subjects after loading (with no apparent error thrown by DICOMUtils), there is no subject to be found in the scene. This means, the files are not correctly loaded, otherwise we would find 1 Subject -> 1 Study -> 1 Series:

Does this help?

How do you determine databaseFilePath? When you launch Slicer in testing mode the database is set to a temporary location (see here).

The database is attempted to be opened on application startup (see here). Maybe the database is switched to the temporary one after you open yours? You can print the database folder and filesForSeries from the database after your failed attempts to retrieve subject hierarchy items.

But all these are really just guessing. The best would be if you could give complete example of your test and CMake file that runs it.

Hi @lassoan,

Thanks for your input! We didn’t change anything, but updated the version of nightly-master that we use to commit b485c8b and this fixed the issue that we had!

2 Likes