DICOM Modality Worklist

Modality worklist (MWL) is one of DICOM’s workflow services that really make a difference. It’s the difference between grocery store workflow with notes on little pieces of paper and a true modern accountable workflow.

Technically speaking, DICOM Modality Worklist is a task manager just like a piece of paper with short text and a check box or the tasks application on your iPhone (or Android). But for the imaging center or RAD department the advantages are enormous. The most obvious benefit is that there’s no need to reconcile all kind of miss spelled names in the PACS because the patient name is no longer keyed in on the modality workstation but received electronically via the MWL query. The fact that the requested procedure is also received electronically reduces the chance for doing the wrong procedure to the wrong patient. Combined with Modality Performed Procedure step (MPPS), that allows the modality to report the task status, take ownership over the task and checkmark it as done when completed, the up side is obvious. No wonder then, that many HMO’s require Modality Worklist as a mandatory feature for every imaging device they purchase. 

The most basic abstraction of a task is a short description of what should be done and a checkbox. That’s all it takes. The MWL data model is a bit more complicated and has two levels.
The top, parent, level is called “Requested Procedure” (RP) and holds the information about the patient (name, id), the study (accession number, study instance UID) and the procedure. The procedure can be described as text using attribute (0032,1060) – “Requested Procedure Description” or in a more sophisticated manner using the (0032,1064) – “Requested Procedure Code Sequence” where static tables of codes and meanings can be used to configure and maintain procedures in the RIS or HIS.
The child level is called “Scheduled Procedure Step” (SPS) and holds attributes relevant to the modality and the actual procedure to be made. A single requested procedure may hold more than one SPS if the request is for a multi-modality study, for example a chest X-Ray and a CT or whatever combination, or if for example two protocols should be applied (e.g. Chest and Abdomen). As a modality, we will use the data in the RP to identify the patient and eliminate re-typing of the name and ID and the SPS to determine what exactly to do.

The DICOM images that the modality will create should use the attributes received from the MWL. When MWL is implemented, the Study Instance UID is generated in the RIS so if a multi-modality procedure is done, each modality will create a series and attach it to the Study by using the Study Instance UID received in the MWL query.
The Modality Worklist Server is responsible for managing the tasks. On one hand it provides means to schedule new tasks (e.g. via HL7 or using a web form) and on the other hand it provides means to get the list of scheduled tasks (via DICOM).
In this post, we’re going to write a simple MWL client using RZDCX DICOM Toolkit and discuss the details of the service and how the workflow is implemented. We’ll leave the MPPS for a future post.
Let’s start with a simplified overview of the workflow at the imaging center or the radiology department.
  1. An order is made for an imaging service, let’s say for example a chest X-Ray. The order can be made in various ways. For example it can arrive as a HL7 message from the HIS (Hospital Information System), or it can be that the patient walks in an the order is made at the reception desk. In either case, a new record is created in the worklist manager with the information for the service.
  2. The order is scheduled and assigned to the X-Ray machine or Room that will perform the exam. If there are many X-Ray machines, the order may be assigned to one of them. The assignment is made by setting the AE title on the order and setting a date. The exact way it is done, is very much the business of the worklist manager implementation. DICOM only defines the data model entities. The relevant entity for this is scheduled procedure step. It’s an abstraction of a task with description of what should be done, when it should be done and who should do it.
  3. When the X-Ray machine makes a modality worklist query, it gets the list of scheduled tasks and performs them.
Let’s have a look at a modality worklist client.

On the upper left of this single form application you see the DICOM network parameters that we’ve already seen on chapter 5 of the DICOM tutorial when talking about DICOM networking.
On the upper right side we have some filter attributes that we can use that make a lot of sense. We can filter by the AE title that the procedure was scheduled for, by the type of modality it was scheduled for and using the scheduled date. For demonstration purpose, the date matching attributes here are very detailed in order to show all possible date and time exact, open and closed range matching.
The Query button packs the filter into a DICOM object and then sends it to the MWL server using the Query method of the DCXREQ interface. The SOP class for Modality Worklist is “1.2.840.10008.5.1.4.31”.
The construction of the query object is a bit tricky because we have to build the parent-child hierarchy. The mechanism of making queries for hierarchical objects is called sequence matching. The server (Q/R SCP) should search all the matching Requested Procedures that have at least one child Scheduled Procedure Step with attributes that matches the query. If it finds such, the complete RP with all its child nodes is sent as a result. The client (Query SCU) may set exactly one child node in the query.

The RP and SPS entities have many attributes but for this post what’s important is to understand that we, as a modality, are performing a schedule procedure step so we are looking for the child entity. The AE title, modality and scheduled date are all attributes of the schedule procedure step so in order to perform the matching, we create a filter for the scheduled procedure step and then put it into a requested procedure object as a sequence element and this is the query we send. Here’s the code:

// Fill the query object
rp = new DCXOBJ();
sps = new DCXOBJ();
el = new DCXELM();

// Build the Scheduled procedure Step (SPS) item
el.Init((int)DICOM_TAGS_ENUM.ScheduledStationAETitle);
sps.insertElement(el);

// A lot of code to handle all the cases of date and time matching
// that eventually goes into the elements: ScheduledProcedureStepStartDate and ScheduledProcedureStepStartTime
el.Init((int)DICOM_TAGS_ENUM.ScheduledProcedureStepStartDate);

/// This adds a filter for time
el.Init((int)DICOM_TAGS_ENUM.ScheduledProcedureStepStartTime);

// Handle the modality Combo Box
el.Init((int)DICOM_TAGS_ENUM.Modality);
if (comboBoxModality..SelectedItem.ToString() != "Any")
    el.Value = comboBoxModality.SelectedItem.ToString();
sps.insertElement(el);

// Now we put it as an item to sequence
spsIt = new DCXOBJIterator();
spsIt.Insert(sps);

// and add the sequence Scheduled Procedure Step Sequence to the requested procedure (parent) object
el.Init((int)DICOM_TAGS_ENUM.ScheduledProcedureStepSequence);
el.Value = spsIt;
rp.insertElement(el);

/// Add the Requested Procedure attributes that we would like to get
el.Init((int)DICOM_TAGS_ENUM.RequestedProcedureID);
rp.insertElement(el);

el.Init((int)DICOM_TAGS_ENUM.RequestedProcedureDescription);
rp.insertElement(el);

el.Init((int)DICOM_TAGS_ENUM.studyInstanceUID);
rp.insertElement(el);

el.Init((int)DICOM_TAGS_ENUM.PatientsName);
rp.insertElement(el);

el.Init((int)DICOM_TAGS_ENUM.patientID);
rp.insertElement(el);

el.Init((int)DICOM_TAGS_ENUM.AccessionNumber);
rp.insertElement(el);

// Create the requester object and connect it's callback to our method
req = new DCXREQClass();
req.OnQueryResponseRecieved += new IDCXREQEvents_OnQueryResponseRecievedEventHandler(OnQueryResponseRecievedAction);

rp.Dump("query.txt");

// send the query command
it = req.Query(LocalAEEdit.Text,
               TargetAEEdit.Text,
               HostEdit.Text,
               ushort.Parse(PortEdit.Text),
               "1.2.840.10008.5.1.4.31"/// Modality Worklist SOP Class
               rp);

At the bottom of the form we have a grid that will show the results.
We can handle the results either in the callback OnQueryResponseRecievedAction or iterate over the items in DCXREQ.Query return value. In this example we’ll do the later and unpack some of the attributes of the RP into a data grid. Here’s the code for it:

private void LoadResultsToGrid(DCXOBJIterator it)
{
    DCXOBJ currObj = null;

    try
    {
        DataTable dt = new DataTable();
        DataRow dr;

        dt.Columns.Add(new DataColumn("Patient Name", typeof(string)));
        dt.Columns.Add(new DataColumn("Accession Number", typeof(string)));
        dt.Columns.Add(new DataColumn("Requested Procedure ID", typeof(string)));
        dt.Columns.Add(new DataColumn("Requested Procedure Description", typeof(string)));
       
        // Iterate over the query results
        for (; !it.AtEnd(); it.Next())
        {
            currObj = it.Get();
            dr = dt.NewRow();
            dr["Patient Name"] = TryGetString(currObj, DICOM_TAGS_ENUM.patientName);
            dr["Accession Number"] = TryGetString(currObj,DICOM_TAGS_ENUM.AccessionNumber);
            dr["Requested Procedure ID"] = TryGetString(currObj,DICOM_TAGS_ENUM.RequestedProcedureID);
            dr["Requested Procedure Description"] = TryGetString(currObj,DICOM_TAGS_ENUM.RequestedProcedureDescription);
            dt.Rows.Add(dr);
        }
        DataView dv = new DataView(dt);
        dgvQueryResults.DataSource = dv;
    }
    finally
    {
        ReleaseComObject(currObj);
    }

} 

The full source code modality worklist SCU example can be downloaded from here. This example has a master-detail  data grid view that shows the SPS’s of the selected RP.

Don’t forget to download and register RZDCX (32 or 64 depending on your OS) before building the project.


As always, comments and questions are most welcome.

15 comments:

  1. Really helpful article.
    Looking ahead for MPPS deciphering...
    Thank you

    ReplyDelete
  2. Thank you very much,
    All of these articles are very helpfull.

    I tried modality worklist,
    but got error like this
    'DUL Finite State Machine Error: No action defined, state 5 event 17'

    any idea?

    ReplyDelete
    Replies
    1. That's a protocol error.
      One of the sides, does not respond according to the expected.
      Can you add a log to the application and repeat the test.
      At the form load add this:

      app = new DCXAPP();
      app.StartLogging("c:\\rzdcxLog.txt");

      Than run again and post here the log file.
      We'll analyze it online

      Delete
    2. I solved it.
      The given port number was false.
      I changed it and it works :)

      Thanks a lot.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi! your contact page is broken :S,

    I thank your dicom posts, Im trying to create a SCP-MWL server, your appi is able to create it?

    thanks.

    ReplyDelete
    Replies
    1. Thanks no-body.
      I fixed it.
      Look at this post: http://dicomiseasy.blogspot.co.il/2012/07/dicom-modality-worklist-server.html
      about MWL SCP
      Roni

      Delete
  5. Hello.. i am using this client (DICOM Modality Worklist) but can't seem to make a connection to the server.. Maybe i just missed this info somewhere but what port number is this client listening to by default?

    ReplyDelete
    Replies
    1. Hi
      This DICOM Modality Worklist SCU (client) does not listen to any port.
      It initiates an association with the peer DICOM application that listen on a port on another computer.

      Delete
  6. Hi from Mexico!

    I'm traing to run your aplication but I got this error:

    Query failed: DUL Association Rejected.

    Any idea ?

    ReplyDelete
  7. Hi !

    I am a french student in computer science. In the context of my school, I've to code a Dicom software. I have decided to code a Worklist implementation but despite all my research some part of the Dicom standard escape me.
    I asked Roni (e-mail) about the "Admission ID", because I didn't know the meaning of this field. I share here his answer which can help everyone :

    "Admission id is an id that is created or assigned to the patient when admitted to the ward.
    For example when you visit a clinic, the secretary at the front desk opens a file for you and assigns an id to it.
    So this can be the admission id.
    It had no other logic attached to it in DICOM.
    In general you should look at the attribute type.
    There are types 1, 2, and 3.
    If it's not a 1, this means you can most probably live without it."

    I agree with that, but I have another question : how do you identify a patient ? With the Patient ID, the Accession Number or the Admission ID ? Do all the patients have an Admission id AND a Patient id ?

    Thank you so much again Roni for this first answer.
    Regards,
    Laura.

    ReplyDelete
    Replies
    1. Hi Laura,
      The identifier of the patient is Patient ID.
      Accession Number identifies the current page or incident or encounter of treatment in the patient record. It is related to study level.
      Regards,
      Roni

      Delete
  8. SCU has fired a query on SCP.but the SCP returns "The response from SCP was not success" and the Error comment returns a "."(dot). what may the problem.
    [DicomQueryAPI::list] The response from SCP was not success .
    [DicomQueryAPI::list] Error Comment : .

    ReplyDelete
    Replies
    1. I this with out toolkit? If so, post the complete log please.

      Delete
  9. Does the RZDCX toolkit is free?

    ReplyDelete