DICOM Basics using .NET and C# - Understanding DICOM Verification

This is part of my series of articles on the DICOM standard. If you are totally new to DICOM, please have a quick look at my earlier article titled “Introduction to the DICOM Standard” for a quick introduction to the standard. It might be useful to also look at my other tutorials that have been completed so far to get up to speed on a number of topics including DICOM Encoding, SOPs and IODs. This should aid in the understanding of the material in this tutorial as they show you how DICOM information is transmitted. This tutorial also assumes that you know the basics of Java or any equivalent object-oriented language such as C# or C++.

Introduction

This will be our first venture into the area of DICOM networking which enables the workflows to occur in a medical setting. I will discuss an extremely important but also very useful feature of DICOM networking covering only the minimal amount of jargon we need to understand to verify DICOM connectivity between devices in this tutorial. I will be digging deeper into what occurs at a lower level in my next tutorial where I cover DICOM Association (or handshaking) in more detail. Let us proceed.

Things that many of us take for granted such as ordering a scan procedure when you walk into a clinic, archiving the images taken at the modality such as CT or MR, retrieving and reviewing these scanned images later, diagnosis reporting and printing of desired images on film could not happen without modern DICOM-based networking services between devices even when they are made by various manufacturers within a hospital network. If you are even somewhat familiar with computer networking, you should recognize a popular term called “Ping”. This is an utility that is implemented one way or the other by most operating systems to enable computer network-related troubleshooting. By using this utility, one can test the reachability or availability of a particular host or a network and also measure the total round trip time for test messages that are transmitted to the destination. Although this enables us to test whether a specific host is available or not, it does not tell us whether the device is DICOM-capable or its DICOM features are turned on for instance. This is where the DICOM Verification Service comes in. But before we go any further, we have to understand some technical jargon that will be necessary to understand this topic better.

“I realized when you look at your mother, you are looking at the purest love you will ever know.” ~ Mitch Albom

Inside any DICOM network, there may be number of applications running on various devices that consume as well as provide services to/from one another (recall my explanation of Service Class Users and Service Class Providers from my earlier tutorial “DICOM Basics - Making Sense of the DICOM File”). For instance, there may a scan unit such as CT, MR or ultrasound, a PACS server that provides storage and retrieval of scanned images when required, and there may also be a number of DICOM printers that help print images of interest to a radiologist on to film. All these devices may be requesting services to or providing services to one another. Some of these devices can in fact be running multiple software applications as well. For example, on the same machine, two different DICOM software may be installed: one may be a viewing workstation software that provides features such as viewing a well as query and retrieval of images from a remote archive. On the same machine, they may be another software which is perhaps responsible for the printing of DICOM images. Both these applications can be listening for communication with other devices on the network by communicating on completely different ports (note, one application entity can use two different ports as well - one to transmit and other to receive). Each of these unique applications (whether they are running on separate devices or not) are known in the DICOM jargon as “Application Entity” or an “AE” for short. When any two of these entities communicate with one another within a DICOM network, the entity that is the consumer of a service being requested is referred to as the Service Class User or SCU. The provider of the service is known as the Service Class Provider or SCP. DICOM stipulates that each of these entities be uniquely identified by giving them an unique name called “Application Entity Title” (often abbreviated to “AET”). The titles are often coded with numbers and with uppercase characters only (more on this later).

A real life scenario may be necessary to set the context for explaining the DICOM verification service. Suppose, you only spoke English and someone who is perhaps lost came to you on the street and said “Hola señor” in Spanish, you wouldn’t understand anything the person said and they might simply smile and walk away. However, if the person said “Hello” to you, you might reply with a “Hello, How are you?”, and now both of you are in a better position to continue the conversation. The person then may proceed to ask “Do you know how to get to the MET Museum using the bus system?”. If you knew the directions, and you may then reply that you don’t know the answer in which case he may reply back with “No problem.Thanks” and walk away, or you may reply back with directions saying “Please take the M1, M2, M3, or M4 bus along Madison Avenue up to 83rd Street” and the person may then thank you and depart. What happens here is that you both first established a common medium of communication, and once that was established you proceeded to ask each other some services. DICOM works pretty much like that as well.

When troubleshooting an existing connection or configuring a new connection between two devices, the technologist or technician uses a preliminary check between the two entities to ensure that they can speak to one another in the same language of DICOM. This check is achieved by a DICOM service called Verification Service (also known as C-Echo or DICOM Ping). This check is necessary as mere verification of network availability or physical connection between the two devices alone not enough, and they must both “speak” basic DICOM to be able to respond to understand what is being asked before they can reply with a “Yes” or “No”. Further communication between the two entities can only occur after this initial validation is established. DICOM implements this initial validation through the DICOM Verification Service which is identified by its own unique SOP UID (1.2.840.10008.1.1) like many other operations in DICOM which we will be covering in future tutorials. For those who are curious, you can see a comprehensive list here.

During this verification operation, command objects called DIMSE (which we will cover in depth in my next tutorial) are exchanged between the two devices. These DIMSEs (stands for “DICOM Message Service Element”) are encoded in the same/familiar pattern of DICOM elements that we have already seen when dealing with DICOM files and are in the form a request and response objects. These commands may or may not carry a payload depending on the operation being carried out. In the case of a CT image store operation, a DIMSE command is transmitted followed by the CT image (in the form of an IOD) for example. However, for the verification operation, there is no other data but the command itself that is exchanged between the two entities. Please see my tutorial on DICOM Associations where I cover these details in more depth.

DICOM Verification

Something you must also know is that unlike other communication protocols that you might be used to already, and although DICOM standard does not mandate this, information regarding both sides must often be configured at each entity when setting up DICOM connectivity. So, if you are setting up a new DICOM printer in your network for instance, you must not only configure this entity with its unique Application Entity Title within the network, but you must also configure the list of the other entities that might potentially request services from it as well as on this device in order for it respond to them when communicated with. Let us proceed to look at a code example to see how this works in real life.

Before We Get Started…

Much like my previous programming examples, I will use the most bare minimum code and approach to help illustrate the concepts that I cover in this tutorial. This means that the code I write here is best suited to simply show the concept that I am trying to explain and is not necessarily the most efficient code to deploy in real life and in your production application.

To get started, you will need to configure a few things on your machine including a .NET development environment as well as the Fellow Oak (fo-dicom) DICOM library before you can run the example if you want to try this out yourself.

  1. Download a .NET IDE or Editor such as Visual Studio IDE or Visual Studio Code (even a text editor should suffice)

  2. Download the Fellow Oak DICOM library either through NuGet Package Manager or download the source code directly from here

  3. You can also find the source code used in this tutorial on GitHub

  4. You must set up a DICOM remote peer (a “Verification SCP”) to try out this example. For the code below, I am using a public DICOM server provided by Dr.Dave Harvey. Other options including downloading free DICOM software such as Orthanc Server (available for Windows and Macs) as well as ClearCanvas Open Source Community Edition (for Windows only). See my article on using Orthanc DICOM Server if you wanted to try it out.

DICOM Verification using Fellow Oak DICOM Toolkit

The Fellow Oak DICOM Toolkit provides a number of classes to perform DICOM networking-related operations. These classes can be found in the Dicom.Network namespace of the library. All DICOM SCU operations including DICOM verification are achieved by using the DicomClient class. The class provides easy to use methods (both synchronous as well as asynchronous) to invoke a number of DICOM operations on any remote peers. In the code shown below, I am simply instantiating a dicom client and adding a "echo request" to it. I then provide additional details about the DICOM remote peer that we are sending this echo request to. I have also registered a callbacks with the client so that we are notified about the verification/echo response. I cover what happens during the association establishment in the next tutorial in depth.

    using System;
    using System.Diagnostics;
    using Dicom.Network;
    namespace UnderstandingDicomVerification
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    //replace these with your settings
                    //Here, I am using Dr.Dave Harvey's public server 
                    //please be careful not to send any confidential info as all traffic is logged
                    var dicomRemoteHost = "www.dicomserver.co.uk";
                    var dicomRemoteHostPort = 11112;
                    var useTls = false;
                    var ourDotNetTestClientDicomAeTitle = "Our Dot Net Test Client";
                    var remoteDicomHostAeTitle = "Dr.Dave Harvey's Server";

                    //create DICOM echo verification client with handlers
                    var client = CreateDicomVerificationClient();

                    //send the verification request to the remote DICOM server
                    client.Send(dicomRemoteHost, dicomRemoteHostPort, useTls, ourDotNetTestClientDicomAeTitle, remoteDicomHostAeTitle);
                    LogToDebugConsole("Our DICOM ping operation was successfully completed");
                }
                catch (Exception e)
                {
                    LogToDebugConsole($"Error occured during DICOM verification request -> {e.StackTrace}");
                }
            }

            private static DicomClient CreateDicomVerificationClient()
            {
                var client = new DicomClient();

                //register that we want to do a DICOM ping here
                var dicomCEchoRequest = new DicomCEchoRequest();

                //attach an event handler when remote peer responds to echo request 
                dicomCEchoRequest.OnResponseReceived += OnEchoResponseReceivedFromRemoteHost;
                client.AddRequest(dicomCEchoRequest);

                return client;
            }

            private static void OnEchoResponseReceivedFromRemoteHost(DicomCEchoRequest request, DicomCEchoResponse response)
            {
                LogToDebugConsole($"DICOM Echo Verification request was received by remote host");
                LogToDebugConsole($"Response was received from remote host...");
                LogToDebugConsole($"Verification response status returned was:{response.Status.ToString()}");
            }

            private static void LogToDebugConsole(string informationToLog)
            {
                Debug.WriteLine(informationToLog);
            }
        }
    }

Output shown in program console when running the code sample above is shown below:


DICOM Echo Verification request was received by remote host
Response was received from remote host...
Verification response status returned was:Success
Our DICOM ping operation was successfully completed

Please note that I have only shown you Verification SCU functionality here. Later on, I will be showing you how to implement the Verification SCP functionality as well which is a recommended feature for all DICOM-enabled applications. I will first need to cover some material on abstract syntaxes and presentation contexts before I do this.

Testing Tools for DICOM Echo Verification

Yet another way of troubleshooting and verifying DICOM connections is to use one of the many useful DICOM testing tools out there. The one that I have used in the past and have liked is DCMTK. The toolkit comes with many standalone testing utilities that help you test various aspects related to DICOM processing through a command line interface. The echoscu command is the one that I will demonstrate here to verify connectivity with an Orthanc DICOM server installed and running locally on my machine. Please see screen capture below showing the association request and response between the two DICOM peers.

Dicom Verification using DCMTK Testing Tool

This concludes my short introductory tutorial on DICOM networking where I covered the basics of DICOM verification which is an important feature that devices should implement to help during initial set ups as well as during any troubleshooting activity that occurs after. There are lot more things to talk about in the area of DICOM networking, and I will be covering most of these areas in my tutorials that are to follow. If you have any questions or comments regarding this tutorial, please feel free to send me an email. Please note that I may not get back to you right away due to work and other commitments. In my next tutorial, I will cover DICOM association/negotiations (or “handshaking”) in more detail whereby the entities actually request services from one another. See you then.