I've been down a couple of rabbit holes trying to find suitable ways of creating a DICOM modality worklist (or .wl worklist files rather).
What I have setup so far:
My problem is with the creation of the DICOM text dump files.
I'm currently using Python's String.format()
function to format a template string. This then substitutes certain placeholders in my template string with actual patient data. Although not elegant, it works. But it's a very static solution and may not be very robust.
Is there a Python library that can be used to generate such text dump files? or even beter, the .wl files? I am willing to trade 3 magic beans, and our family recipe for potato salad, for such a library. (The secret ingredient is not paprika)
For completeness, here is how the template dicom worklist string looks:
dicom_wl_template_string = """
# Dicom-File-Format
# Dicom-Meta-Information-Header
# Used TransferSyntax: Unknown Transfer Syntax
# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0002,0000) UL [123]
(0002,0002) UI [1.2.111.222222.5.1.4.1.1.104.1]
(0002,0003) UI [1.2.3.4.5.6.132437.17.4.10123450.312346792082.12349.1]
(0002,0010) UI [1.2.840.10008.1.2.1]
(0002,0012) UI [1.2.276.0.7230010.3.0.3.6.6]
(0002,0013) SH [OFFIS_DCMTK_366]
(0008,0005) CS [{SpecificCharacterSet}] # 10, 1 SpecificCharacterSet e.g ISO_IR 100
(0008,0012) DA [{InstanceCreationDate}] # 8, 1 InstanceCreationDate e.g 20220101
(0008,0050) SH [{AccessionNumber}] # 8, 1 AccessionNumber e.g 1234
(0010,0010) PN [{PatientName}] # 14, 1 PatientName e.g SURNAME^ABC
(0010,0020) LO [{PatientID}] # 14, 1 PatientID e.g 7001011234080
(0010,0030) DA [{PatientBirthDate}] # 8, 1 PatientBirthDate e.g. 19700101
(0010,0040) CS [{PatientSex}] # 2, 1 PatientSex e.g. M
(0020,000d) UI [{StudyInstanceUID}] # 54, 1 StudyInstanceUID e.g 1.2.3.4.5.6.132437.17.4.10123450.312346792082.12349.1
(0032,1060) LO [{RequestedProcedureDescription}] # 16, 1 RequestedProcedureDescription
(0040,0100) SQ (Sequence with explicit length #=1) # 90, 1 ScheduledProcedureStepSequence
(fffe,e000) na (Item with ??explicit length #=5??) # 82, 1 Item
(0008,0060) CS [{Modality}] # 4, 1 Modality e.g. CT, MR, CR, NM, PT, US, XA
(0040,0001) AE [{ScheduledStationAETitle}] # 4, 1 ScheduledStationAETitle e.g Foo
(0040,0002) DA [{ScheduledProcedureStepStartDate}] # 8, 1 ScheduledProcedureStepStartDate e.g. 20220101
(0040,0003) TM [{ScheduledProcedureStepStartTime}] # 8, 1 ScheduledProcedureStepStartTime e.g. 080000
(0040,0006) PN [{ScheduledPhysicianName}] # 8, 1 Scheduled Performing Physicians Name e.g. EMMETBROWN
(0040,0007) LO [{ScheduledProcedureStepDescription}] # 22, 1 ScheduledProcedureStepDescription e.g SOMETHING
(0040,0009) SH [{ScheduledProcedureStepID}] # 4, 1 ScheduledProcedureStepID e.g 0001
(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem
(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem
(0040,1001) SH [unknown] # 8, 1 RequestedProcedureID
"""
Thank you for the response. Here is also some example code for future visitors.
import os
from os import path
from pydicom.dataset import Dataset, FileMetaDataset
from pydicom.uid import ExplicitVRLittleEndian
wl_file_name = "directory/file.wl"
txt_file_name = "directory/file.txt"
# Create data set
ds = Dataset()
# Add file meta information elements
ds.file_meta = FileMetaDataset()
ds.file_meta.TransferSyntaxUID = ExplicitVRLittleEndian
ds.file_meta.MediaStorageSOPClassUID = "0"
ds.file_meta.MediaStorageSOPInstanceUID = "0"
# Fill out the worklist query elements
ds.SpecificCharacterSet = "ISO_IR 6"
ds.InstanceCreationDate = "20220101"
ds.AccessionNumber = "12345-abc"
ds.PatientName = "SURNAME^NAME"
ds.PatientID = "123456"
ds.PatientBirthDate = "19700101"
ds.PatientSex = "M"
ds.StudyInstanceUID = "1a-2b-3c"
ds.RequestedProcedureDescription = "ProcedureDescription"
ds.ScheduledProcedureStepSequence = [Dataset()]
ds.ScheduledProcedureStepSequence[0].Modality = "OT"
ds.ScheduledProcedureStepSequence[0].ScheduledStationAETitle = "OT"
ds.ScheduledProcedureStepSequence[0].ScheduledProcedureStepStartDate = "20220101"
ds.ScheduledProcedureStepSequence[0].ScheduledProcedureStepStartTime = "080000"
ds.ScheduledProcedureStepSequence[0].ScheduledPerformingPhysicianName = "Doctor Emmet Brown"
ds.ScheduledProcedureStepSequence[0].ScheduledProcedureStepDescription = "SchedProcStepDesc"
ds.ScheduledProcedureStepID = "0001"
# more stuff if you need
# Save directly as a .wl file.
# Set write_like_original=False to be certain you’re writing the dataset in the DICOM File Format
ds.save_as(wl_file_name, write_like_original=False)
# Additionally, you can also make a readable txt file for humans
# Check if txt file already exists
if(path.exists(txt_file_name)): #if txt file exists, remove it first
try:
os.remove(txt_file_name)
except OSError as e:
print("Error: %s : %s" % (txt_file_name, e.strerror))
# Run dcmdump command to convert wl file to txt
convert_wl_to_txt_cmd = "dcmdump " + wl_file_name + " > " + txt_file_name
os.system(convert_wl_to_txt_cmd)
The txt version then looks like this:
# Dicom-File-Format
# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 120 # 4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01 # 2, 1 FileMetaInformationVersion
(0002,0002) UI [0] # 2, 1 MediaStorageSOPClassUID
(0002,0003) UI [0] # 2, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =LittleEndianExplicit # 20, 1 TransferSyntaxUID
(0002,0012) UI [1.2.826.0.1.3680043.8.498.1] # 28, 1 ImplementationClassUID
(0002,0013) SH [PYDICOM 2.2.2] # 14, 1 ImplementationVersionName
# Dicom-Data-Set
# Used TransferSyntax: Little Endian Explicit
(0008,0005) CS [ISO_IR 6] # 8, 1 SpecificCharacterSet
(0008,0012) DA [20220101] # 8, 1 InstanceCreationDate
(0008,0050) SH [12345-abc] # 10, 1 AccessionNumber
(0010,0010) PN [SURNAME^NAME] # 12, 1 PatientName
(0010,0020) LO [123456] # 6, 1 PatientID
(0010,0030) DA [19700101] # 8, 1 PatientBirthDate
(0010,0040) CS [M] # 2, 1 PatientSex
(0020,000d) UI [1a-2b-3c] # 8, 1 StudyInstanceUID
(0032,1060) LO [ProcedureDescription] # 20, 1 RequestedProcedureDescription
(0040,0009) SH [0001] # 4, 1 ScheduledProcedureStepID
(0040,0100) SQ (Sequence with explicit length #=1) # 110, 1 ScheduledProcedureStepSequence
(fffe,e000) na (Item with explicit length #=6) # 102, 1 Item
(0008,0060) CS [OT] # 2, 1 Modality
(0040,0001) AE [OT] # 2, 1 ScheduledStationAETitle
(0040,0002) DA [20220101] # 8, 1 ScheduledProcedureStepStartDate
(0040,0003) TM [080000] # 6, 1 ScheduledProcedureStepStartTime
(0040,0006) PN [Doctor Emmet Brown] # 18, 1 ScheduledPerformingPhysicianName
(0040,0007) LO [SchedProcStepDesc] # 18, 1 ScheduledProcedureStepDescription
(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem
(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem