Importing Dicom Directory via Temporary Database

Hiya! I am trying to get the module I put together to run on the start-up of 3DSlicer. Right now I am getting the following error:

  File "Z:/SegmentDicom/SegmentDicom/SegmentDicom/SegmentDicom.py", line 103, in LoadSegment
    with DICOMUtils.TemporaryDICOMDatabase() as db:
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Slicer-4.11\qt-scripted-modules\DICOMLib\DICOMUtils.py", line 306, in __enter__
    self.originalDatabaseDir = openTemporaryDatabase(self.temporaryDatabaseDir)
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Slicer-4.11\qt-scripted-modules\DICOMLib\DICOMUtils.py", line 206, in openTemporaryDatabase
    originalDatabaseDir = settings.value(slicer.dicomDatabaseDirectorySettingsKey)
AttributeError: module 'slicer' has no attribute 'dicomDatabaseDirectorySettingsKey'

This is the code snippet where the error is occuring

    from DICOMLib import DICOMUtils
    loadedNodeIDs = []


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

May the issue have to do with running this module on the start-up? And if it is, then is there a better way to have my module run automatically on startup~ Thank you in advance!!!

Does the script work well if you launch it manually after Slicer is started?

Yes, it works perfectly fine after Slicer has fully loaded.
I imagine that some elements need to load before running this module. In this case, is there some way I can add a delay to the module or have it load the dicom module before running?

How do you launch your code at startup?

I just went into Application Settings and set the module to be the startup module.
In code I have the logic running by having the apply button be true. Which to my understanding and the way it usually works is when the module loads the button, then the logic runs.

At the time a module’s constructor is executed, not all the modules have been initialized yet. If you want to run in your module something at startup then you need to use startupCompleted signal of the application:

slicer.app.connect("startupCompleted()", self.someMethodToRunAtStartup)
1 Like

Ohh! Thank you so much! This is what I have been searching for~

I would place this in the Widget Class of the module I created or somewhere else?

This connection has to be created when the module is created (in the module class constructor), but it can call methods anywhere. Since widget is only created when you open the module the first time and module logic is created even later, the called method should be in the module class (or a static method in the widget or logic class).

1 Like

Heya! Congrats on your anniversary!!! I believe I did what you suggested and placed the line slicer.app.connect in the Module Class.

I got the following error, which seems like the one I was having before.

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Python\Lib\imp.py", line 170, in load_source
    module = _exec(spec, sys.modules[name])
  File "<frozen importlib._bootstrap>", line 618, in _exec
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "Z:/SegmentDicom/SegmentDicom/SegmentDicom/SegmentDicom.py", line 11, in <module>
    class SegmentDicom(ScriptedLoadableModule):
  File "Z:/SegmentDicom/SegmentDicom/SegmentDicom/SegmentDicom.py", line 137, in SegmentDicom
    slicer.app.connect("startupCompleted()", LoadSegment())
  File "Z:/SegmentDicom/SegmentDicom/SegmentDicom/SegmentDicom.py", line 40, in LoadSegment
    with DICOMUtils.TemporaryDICOMDatabase() as db:
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Slicer-4.11\qt-scripted-modules\DICOMLib\DICOMUtils.py", line 306, in __enter__
    self.originalDatabaseDir = openTemporaryDatabase(self.temporaryDatabaseDir)
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Slicer-4.11\qt-scripted-modules\DICOMLib\DICOMUtils.py", line 206, in openTemporaryDatabase
    originalDatabaseDir = settings.value(slicer.dicomDatabaseDirectorySettingsKey)
AttributeError: module 'slicer' has no attribute 'dicomDatabaseDirectorySettingsKey'

Maybe the signal is called too early. You can call a singleshot timer with a 1-second delay in the method that is called by startupCompleted to give some time for the DICOM module to initialize itself.

1 Like

Turns out a 0.1 second delay using the solution you provided worked out! Thank you so much!!!

1 Like

Hello there! I thought it be best I post in this thread since it is related.
I found that when I don’t import the dicom directory manually before running the module it gives me the following error. It does work when I manually add it beforehand, but I would like to fully automate the process.

Traceback (most recent call last):
  File "Z:/SegmentDicom/SegmentDicom/SegmentDicom/SegmentDicom.py", line 54, in ProceduralSegmentation
    loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))
  File "Z:\Slicer 4.11.0-2020-03-24\lib\Slicer-4.11\qt-scripted-modules\DICOMLib\DICOMUtils.py", line 41, in loadPatientByUID
    raise IOError('No patient found with DICOM database UID %s' % patientUIDstr)
OSError: No patient found with DICOM database UID 1

This is the error that I am getting. Any idea on what I may be missing? Also happy to answer any details needed~

You can only load images that have been already imported.

I took this code from the Nightly Script Repo for importing a dicom directory

    dicomDataDir = "C:/Users/Public/Pictures"
    from DICOMLib import DICOMUtils
    loadedNodeIDs = []

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

I put a 10 second delay just to make sure it wasn’t due to it loading right away and I found it gives me the same error and right before it this is posted:

“DICOM indexer has successfully inserted 81 files [0.05s]”
“DICOM indexer has successfully processed 82 files [0.15s]”
“DICOM indexer has updated display fields for 81 files [0.02s]”

The code above is incorrectly indented, which deletes the DICOM database immediately after import is completed. See the code with correct indentation in the script repository. Code indentation is not just formatting in Python, so you need to pay very close attention to it.

Wow, I completely missed that when I was pasting it in. Thanks for spotting that for me! I will do better to pay careful attention!!!

1 Like

hello,lassoan.i also have trouble in “AttributeError: module ‘slicer’ has no attribute ‘dicomDatabaseDirectorySettingsKey’” when i just code the below code:

PythonQt::init();
PythonQtObjectPtr context = PythonQt::self()->getMainModule();
context.evalScript(“import DICOMLib”);
context.evalScript(“slicer.util.selectModule(‘DICOM’)”);

i want import dicom by python script.but failed.i am troubled in this for 5 days.could you help me please?

it’s very helpful to have someone’s email to sovle this trouble.

slicer.dicomDatabaseDirectorySettingsKey is set in the DICOM module. Probably you run this script too early, before the application has been fully started up. If you want to run a script after startup is completed then you can connect a slot to the startupCompleted signal of the application.