Tutorial

For most users, it is sufficient to use spydcmtk is via the command-line interface.

Access via:

spydcmtk -h

to see the command-line usage available to you.

If you would like to incorporate spydcmtk into your Python project, then some tutorial snippets showing primary functionality are provided below.

import spydcmtk

listOfStudies = spydcmtk.dcmTK.ListOfDicomStudies.setFromDirectory(MY_DICOM_DIRECTORY)
# Example filtering
dcmStudy = listOfStudies.getStudyByDate('20230429') # Dates in DICOM standard string format: YYYYMMDD
dcmSeries = dcmStudy.getSeriesBySeriesNumber(1)
# Example writing new DICOM files with anonymization
dcmStudy.writeToOrganisedFileStructure(tmpDir, anonName='Not A Name')

Work with pixel data and metadata

listOfStudies = spydcmtk.dcmTK.ListOfDicomStudies.setFromDirectory(MY_DICOM_DIRECTORY)
dcmStudy = listOfStudies[0]
dcmSeries = dcmStudy.getSeriesBySeriesNumber(4)
A, patientMeta = dcmSeries.getPixelDataAsNumpy()
print(A.shape)
print(patientMeta)
# OUTPUT (e.g.):
# 'ImageOrientationPatient': [1.0, 0.0, 0.0, 0.0, 1.0, 0.0],
# 'PixelSpacing': [1.0, 1.0],
# 'SliceThickness': 1.0,
# 'ImagePositionPatient': [0.0, 0.0, 0.0],
# 'SliceLocation0': 0.0

Convert image(s) to DICOM

pixArray # A numpy array of shape (nC, nR, nS, nChannels)
# Expand dimensions to include a single channel dimension if necessary
pixArray = np.expand_dims(pixArray, 3)

# Define image spacing / orientation / thickness
patMatrix = {'PixelSpacing': [0.02, 0.02],
                'ImagePositionPatient': [0.0, 0.1, 0.3],
                'ImageOrientationPatient': [0.0,0.0,1.0,0.0,1.0,0.0],
                'SliceThickness': 0.04,
                'SpacingBetweenSlices': 0.04}
patMeta = dcmTK.dcmVTKTK.PatientMeta()
# Initialise patient meta from dictionary - optional - defaults will be used if not provided
patMeta.initFromDictionary(patMatrix)

# Define tag values to update: Note Name:Value or Name:(Code, VR, Value) is supported
tagUpdateDict = {'SeriesNumber': 88,
                    'StudyDescription': ([0x0008,0x1030], 'LO', "TestDataB"),
                    'SeriesDescription': ([0x0008,0x103e], 'LO', "SeriesLaugh"),
                    'StudyID': ([0x0020,0x0010], 'SH', '1088')}

# DCM Template - Optional - will use defaults if not provided. May be filepath or pydicom dataset.
dcmTemplate = None
# OR
dcmTemplate = 'path/to/dcm/template.dcm'
# OR
dcmTemplate = dcm_series_object[0]

# Write to DICOM
dcmTK.writeNumpyArrayToDicom(pixelArrray=pixArray,
                            dcmTemplate_or_ds=dcmTemplate,
                            patientMeta=patMeta,
                            outputDir=tmpDir,
                            tagUpdateDict=tagUpdateDict)

Anonymise multiple data for blinded reading - then reidentify

Assume “WORKING_DIR” is a directory containing multiple studies, each with multiple series. Such a structure is typical output from a commanline action:

spydcmtk -i DICOM_DIR -o WORKING_DIR
# Read each study individually (save memory)
matchingList = []
for k1, iDir in enumerate(sorted(os.listdir(WORKING_DIR))):
    fullDir = os.path.join(WORKING_DIR, iDir)
    print(f"Working on: {fullDir}")
    dmcStudy = spydcmtk.dcmTK.DicomStudy.setFromDirectory(fullDir, HIDE_PROGRESSBAR=True)
    filteredList = dmcStudy.filterByTag("SeriesDescription", "T1-Head") # Filter by series description
    for iSeries in filteredList:
        originalName = iSeries.getTag('PatientName')
        thisSeriesUID = iSeries.getTag('SeriesInstanceUID')
        newName = f"anon_for_readerA_{k1}"
        newPatID = k1
        iSeries.anonymise(newName, newPatID)
        newStudyUID = spydcmtk.dcmTK.generate_uid()
        iSeries.resetUIDs(newStudyUID)
        newSeriesUID = iSeries.getTag('SeriesInstanceUID')
        newStudyDir = os.path.join(WORKING_ANON, f"anon_for_readerA_{k1}")
        os.makedirs(newStudyDir, exist_ok=True)
        dirOut = iSeries.writeToOrganisedFileStructure(newStudyDir)
        matchingList.append([originalName, thisSeriesUID, newName, newPatID, newSeriesUID])
# now, e.g., write matchinglist to csv file for later reidentification.