The Modality Worklist Feature ?

I am sort of a hobbyist and developer, now somewhat interested in Orthanc.

Just wondering how the MWL feature, https://book.orthanc-server.com/plugins/worklists-plugin.html

Documented for Orthanc would work with an MRI scanner. I have Horos and Osirix, so I guess I could test with that, but I would want to use it with a DICOM acquisition device if that is how it is suppose to work. I already have HOROS set up on a dev server to work with AMBRAHEALTH through their gateway and I can query retrieve exams, so it should be similar with Orthanc.

Can a scanner/device be added just by adding another entry, like “mri_main” : [ “MRI_MAIN”, “192.168.0.2”, 104 ] ?

to:

"DicomModalities" : {
  "horos" : [ "HOROS", "192.168.0.8", 11112 ],
  "findscu" : [ "FINDSCU", "127.0.0.1", 1234 ]
},

And then can I just dynamically generate worklist files and update them for Orthanc to use ? If so, which entries are dynamic ? Is the Meta Information always the same ?

It looks like the Data-Set is all dynamic except for maybe the CharacterSet. How is a StudyInstanceUID generated ?

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 202                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI [1.2.276.0.7230010.3.1.0.1]              #  26, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.276.0.7230010.3.1.4.2831176407.11154.1448031138.805061] #  58, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =LittleEndianExplicit                    #  20, 1 TransferSyntaxUID
(0002,0012) UI [1.2.276.0.7230010.3.0.3.6.0]            #  28, 1 ImplementationClassUID
(0002,0013) SH [OFFIS_DCMTK_360]                        #  16, 1 ImplementationVersionName

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Explicit
(0008,0005) CS [ISO_IR 100]                             #  10, 1 SpecificCharacterSet
(0008,0050) SH [00000]                                  #   6, 1 AccessionNumber
(0010,0010) PN [VIVALDI^ANTONIO]                        #  16, 1 PatientName
(0010,0020) LO [AV35674]                                #   8, 1 PatientID
(0010,0030) DA [16780304]                               #   8, 1 PatientBirthDate
(0010,0040) CS [M]                                      #   2, 1 PatientSex
(0010,2000) LO [METASTASIS]                             #  10, 1 MedicalAlerts
(0010,2110) LO [TANTAL]                                 #   6, 1 Allergies
(0020,000d) UI [1.2.276.0.7230010.3.2.101]              #  26, 1 StudyInstanceUID
(0032,1032) PN [SMITH]                                  #   6, 1 RequestingPhysician
(0032,1060) LO [EXAM6]                                  #   6, 1 RequestedProcedureDescription
(0040,1001) SH [RP454G234]                              #  10, 1 RequestedProcedureID
(0040,1003) SH [LOW]                                    #   4, 1 RequestedProcedurePriority

If that is capable of receiving queries from an MRI and responding with the worklist that would be awesome.
Are there hooks from a PHP web App to some of Orthanc commands such that worklists could be created via the PHP web app.
i.e. The web app maintains the database of orders and patients, so I could pretty easily create text files that have most of the information above.  Not sure about how to generate a StudyInstanceUID, but here must be some standard and simple way to do that.

My understanding is that acquisition devices can query the DICOM server and basically get a "pick list" for scheduled exams such that no or minimal entry of data is required.

AMBRA'S orders with an MWL entry have something like this.  I presume that that is similar to what is shown above, except there is no date in the example above ?  The StudyInstanceUID looks kind of like their study_uid.

Replying to my own question.

I actually went ahead and wrote a PHP class that does what I was looking for. I had to install dcmtk on my Mac, using brew install dcmtk.

DiCOM@OFFIS has more information about the DCMTK. That put the binaries on my Mac at /usr/local/opt/dcmtk/bin/ probably something similar for LINUX.

I also need the path for where ORTHANC is storing the modality worklists, so that has to be set in my PHP script and also in the ORTHANC CONFIG FILE. /Users/sscotti/Desktop/orthancAndPluginsOSX.stable/WorklistsDatabase/ for Mac OS abs path and ./WorklistsDatabase relative path in the ORTHANC config file. With that and a txt template for a MWL file it is actually easy to create a .wl file using the PHP script. I have no way to check if the .wl file is valid by using an acquisition device, although if I convert back to a .txt file it is reversible, so it is probably valid.

I am still not sure if some of the other fields in the .txt template have to be changed also, and where to get the values for that.

If anyone is interested I am including an example PHP script. The script actually dumps both the created .txt file and the converted .wl file to the WL folder. I could put the .txt file somewhere else, i.e.

Dicom-Meta-Information-Header

`

<?php class DICOMController extends Controller { /** * Construct this object by extending the basic Controller class. */ private $FileMetaInformationGroupLength; private $FileMetaInformationVersion; private $MediaStorageSOPClassUID; private $MediaStorageSOPInstanceUID; private $TransferSyntaxUID; private $ImplementationClassUID; private $ImplementationVersionName; private $CharSet; private $AccessionNumber; private $PatientName; private $PatientID; private $PatientBirthDate; private $PatientSex; private $MedicalAlerts; private $Allergies; private $StudyInstanceID; private $RequestingPhysician; private $RequestedProcedureDescription; private $RequestedProcedureID; private $RequestedProcedurePriority; private static $dcmtk_path; private static $ORTHANC_MWL; public function __construct() { parent::__construct(); self::$dcmtk_path = '/usr/local/opt/dcmtk/bin/'; self::$ORTHANC_MWL = '/Users/sscotti/Desktop/orthancAndPluginsOSX.stable/WorklistsDatabase/'; $name = []; $name[] = $_POST['lname']; $name[] = $_POST['fname']; if (!empty($_POST['mname'])) $name[] = $_POST['mname']; $name = implode($name, "^"); $referring_physician = json_decode($_POST['referring_physician'], true); $referring_physician = implode($referring_physician,"^"); $description = json_decode($_POST['description']); $this->CharSet = 'ISO_IR 100'; $this->AccessionNumber = $_POST['accession_number']; $this->PatientName = $name; $this->PatientID = $_POST['patientid']; $this->PatientBirthDate = $_POST['patient_birth_date']; $this->PatientSex = $_POST['patient_sex']; $this->MedicalAlerts = $_POST['indication']; $this->Allergies = ""; $this->StudyInstanceID = "1.2.276.0.7230010.3.2.101"; $this->RequestingPhysician = $referring_physician; $this->RequestedProcedureDescription = $description->exam_name; $this->RequestedProcedureID = $description->cpt; $this->RequestedProcedurePriority = "routine"; } public static function dcmtk_command($command) { //--logfile dcmlogfile.cfg echo exec(self::$dcmtk_path . $command); //print_r($output); } public function makeMWLFile () { //print_r($_POST); $template = '# Dicom-File-Format # Dicom-Meta-Information-Header # Used TransferSyntax: Little Endian Explicit (0002,0000) UL 202 # 4, 1 FileMetaInformationGroupLength (0002,0001) OB 00\01 # 2, 1 FileMetaInformationVersion (0002,0002) UI [1.2.276.0.7230010.3.1.0.1] # 26, 1 MediaStorageSOPClassUID (0002,0003) UI [1.2.276.0.7230010.3.1.4.2831176407.11154.1448031138.805061] # 58, 1 MediaStorageSOPInstanceUID (0002,0010) UI =LittleEndianExplicit # 20, 1 TransferSyntaxUID (0002,0012) UI [1.2.276.0.7230010.3.0.3.6.0] # 28, 1 ImplementationClassUID (0002,0013) SH [OFFIS_DCMTK_360] # 16, 1 ImplementationVersionName # Dicom-Data-Set # Used TransferSyntax: Little Endian Explicit (0008,0005) CS [' . $this->CharSet . '] # 10, 1 SpecificCharacterSet (0008,0050) SH [' . $this->AccessionNumber . '] # 6, 1 AccessionNumber (0010,0010) PN [' . $this->PatientName . '] # 16, 1 PatientName (0010,0020) LO [' . $this->PatientID . '] # 8, 1 PatientID (0010,0030) DA [' . $this->PatientBirthDate . '] # 8, 1 PatientBirthDate (0010,0040) CS [' . $this->PatientSex . '] # 2, 1 PatientSex (0010,2000) LO [' . $this->MedicalAlerts . '] # 10, 1 MedicalAlerts Indication (0010,2110) LO [' . $this->Allergies . '] # 6, 1 Allergies (0020,000d) UI [1.2.276.0.7230010.3.2.101] # 26, 1 StudyInstanceUID (0032,1032) PN [' . $this->RequestingPhysician . '] # 6, 1 RequestingPhysician (0032,1060) LO [' . $this->RequestedProcedureDescription . '] # 6, 1 RequestedProcedureDescription (0040,1001) SH [' . $this->RequestedProcedureID . '] # 10, 1 RequestedProcedureID (0040,1003) SH [' . $this->RequestedProcedurePriority . '] # 4, 1 RequestedProcedurePriority'; //echo $template;dump2dcm.exe sampleWorklist.txt newWorklist.wl file_put_contents (self::$ORTHANC_MWL . "samplephp.txt", $template); echo '[{"status":"Sent to ORTHANC"}]'; self::dcmtk_command('dump2dcm ' . self::$ORTHANC_MWL . "samplephp.txt " . self::$ORTHANC_MWL . "samplephp.wl"); } } ?>

`

Hi Stephen,

Your questions are quite vague so it’s quite difficult to answer. So I’ll just answer a few.
Thanks BTW for all the info you’ve been sharing.

You need a new StudyInstanceUID for each worklist file you generate. You can get one from Orthanc: https://demo.orthanc-server.com/tools/generate-uid?level=study

To test your WL, you can use DCMTK too:

In another command-line prompt, launch a findscu request to ask Orthanc to return all worklists for CT modalities:

findscu -W -k "ScheduledProcedureStepSequence[0].Modality=CT" 127.0.0.1 4242

Don’t forget to remove your worklist files from the folder i.e the day after they have been generated since they are usually valid only for one day (for a specific patient visit).

HTH,

Alain.