I have this code, which iteratively opens different scannings of baboon skulls placed in different folders:
import os
from DICOMLib import DICOMUtils
yourpath = r"C:/Users/mario.modesto/Desktop/TEST DICOM SLICE"
# walk through DICOM directory
# https://stackoverflow.com/questions/77865010/run-python-script-in-each-subfolder-automatically
for dir in os.scandir(yourpath):
# Load DICOM files
dicomDataDir = dir.path # path to input folder with DICOM files
baboon_skull = dir.name
loadedNodeIDs = [] # this list will contain the list of all loaded node IDs
# 1. Load DICOM files
# https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#dicom
with DICOMUtils.TemporaryDICOMDatabase() as db:
DICOMUtils.importDicom(dicomDataDir, db)
patientUIDs = db.patients()
for patientUID in patientUIDs:
loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))
# 2. Load volume
# https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#display-volume-using-volume-rendering
logic = slicer.modules.volumerendering.logic()
volumeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLScalarVolumeNode1')
I have 95 baboon scans (therefore 95 subfolders), and each scan has two series:
A topogram (512x512x1)
Facial bones (512x512x288*) (*although 288 varies from one skull to another)
As an example, next image shows only three baboon scans already loaded
The loadedNodeIDs will have a list of the ids of all nodes corresponding to that set of dicom instances (based on the default best interpretation). Instead of using the hard-coded vtkMRMLScalarVolumeNode1 as the id, you can use the loaded ids to iterate through the nodes that were loaded. You can either introspect the name of the node, which is based on the series description, or your an use the node attributes that map slices from a volume back to dicom SOPInstanceUIDs that can be used with the dicom database to get any of the instance header values, from which you can decide which series has the data you want.
I walked through and now I solved the problem by adding an if/else statement.
I copy here the code I used in case anyone in the future gets into this question:
import os
from DICOMLib import DICOMUtils
yourpath = r"C:/Users/mario.modesto/Desktop/TEST DICOM SLICE"
# yourpath = r"D:/Baboons/slice"
# walk through DICOM directory
# https://stackoverflow.com/questions/77865010/run-python-script-in-each-subfolder-automatically
for dir in os.scandir(yourpath):
# Load DICOM files
dicomDataDir = dir.path # path to input folder with DICOM files
baboon_skull = dir.name
loadedNodeIDs = [] # this list will contain the list of all loaded node IDs
# 1. Load DICOM files
# https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#dicom
with DICOMUtils.TemporaryDICOMDatabase() as db:
DICOMUtils.importDicom(dicomDataDir, db)
patientUIDs = db.patients()
for patientUID in patientUIDs:
loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))
print(loadedNodeIDs)
print(len(loadedNodeIDs))
# 2. Load volume
# https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#display-volume-using-volume-rendering
logic = slicer.modules.volumerendering.logic()
# This "if-else" is to select the second volume to skip the Topogram, which is the first
if len(loadedNodeIDs) == 2:
volumeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLScalarVolumeNode2')
else:
volumeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLScalarVolumeNode1')
With print(loadedNodeIDs) and print(len(loadedNodeIDs)) I was able to see which and how many volumes I was having in the scanning. I had two: vtkMRMLScalarVolumeNode1 and vtkMRMLScalarVolumeNode2.
This is why in the last part of the code I added an if/else statement.