Showing posts with label RZDCX. Show all posts
Showing posts with label RZDCX. Show all posts

Wednesday, June 28, 2023

Introduction to DICOM - Chapter 5 – Solving a DICOM Communication Problem

Today we are going to diagnose a communication problem between two DICOM applications and hopefully find the reason for the problem and solve it. I know, we didn’t even start talking about the DICOM network protocol, but hey, we’re not going to read all this 3,000 pages standard together before getting our hands dirty, right?
In this post we'll discuss:
  1. Application Entities (AE’s) – the nodes in the DICOM network and their name – AE Title
  2. Association – a network peer-to-peer session between two DICOM applications
  3. Association Negotiation – The first part of the association in which the two AE’s agree on what can and can’t be done during the Association
  4. The Verification Service using the C-ECHO command – a DICOM Service Class that is used to verify a connection, sort of application level ‘ping’.
  5. The Storage Service using the C-STORE command – a DICOM Service that allows one AE to send a DICOM object to another AE
The C in C-ECHO and C-STORE commands stands for Composite. If you remember, in chapter 4 when discussing the DICOM Data Model, we said that DICOM applications exchange composite objects (the DICOM images that we already know) that are composites of modules from different IE's where IE's are the information entities of the Normalized DICOM data model.

Here's the story:
Complaint 20123

Burt Simpson from Springfield Memorial Hospital reports that he can’t send the screen capture to the PACS. He kept clicking the green “Send” button but he always gets the same error: “Operation Failed!”. The log file Burt copied from the system is attached.
You may ask yourself, what’s the point in analyzing a log of an application that we are never going to use? Well, the truth is that all DICOM logs look alike. Actually, most DICOM applications are quite similar because DICOM software implementations have common ancient ancestors. If it’s a C library it may be the DICOM test node, CTN. If it’s Java than it might be dcm4che. Even if it's PHP or other newer languages, the libraries were transcribed and ported from the old C implementations so all DICOM logs are similar.

Query/Retrieve part II - C-MOVE


In part I of this post, I was in a meeting with a customer reviewing their workstation code and while sitting there I was thinking to myself, why should my customers have to deal with so many details of the DICOM Q/R Service when all they really want is to retrieve a study just like they would have downloaded a zip file from a web site. And thus, later, back in my office I decided to extended the DICOM Toolkit API to include a C-MOVE method that will take care of everything including the incoming association. In today’s post I’m going to use the new MoveAndStore method to talk about the DICOM Query/Retrieve service. We’ll start at the end and then work our way backwards.

C-MOVE is a DICOM command that means this: The calling AE (we) ask the called AE (the PACS) to send all the DICOM Instances that match the identifier to the target AE. 

If you're looking for a High-Performance DICOM Server with Query/Retrieve SCP check HRZ's DICOM Server solution.

Here’s how you ask a PACS to send you the DICOM images with RZDCX (version 2.0.1.9).

        public void MoveAndStore()
        {
            // Create an object with the query matching criteria (Identifier)
            DCXOBJ query = new DCXOBJ();
            DCXELM e = new DCXELM();
            e.Init((int)DICOM_TAGS_ENUM.patientName);
            e.Value = DOE^JOHN";
            query.insertElement(e);
            e.Init((int)DICOM_TAGS_ENUM.patientID);
            e.Value = @"123456789";
query.insertElement(e);
            // Create an accepter to handle the incomming association
DCXACC accepter = new DCXACC();
            accepter.StoreDirectory = @".\MoveAndStore";
Directory.CreateDirectory(accepter.StoreDirectory);
            // Create a requester and run the query
DCXREQ requester = new DCXREQ();
            requester.MoveAndStore(
                MyAETitle, // The AE title that issue the C-MOVE
                IS_AE,     // The PACS AE title
                IS_Host,   // The PACS IP address
                IS_port,   // The PACS listener port
                MyAETitle, // The AE title to send the
                query,     // The matching criteria
                104,       // The port to receive the results
                accepter); // The accepter to handle the results
        }

Behind this rather short function hides a lot of DICOM networking and when it returns we should have all the matching objects stored in the directory “.\MoveAndStore”. Readers with some practical DICOM experience probably expect me to say that it can also fail. In that case MoveAndStore throws an exception with the error code and description. Sometimes you would have to set the detailed logging on and start reading logs like we did in chapter 5 of this tutorial on DICOM networking and in some later post we will look together at a DICOM log of a Q/R transaction.

The following diagram, taken from part 2 of the DICOM standard, is commonly seen in DICOM Conformance Statements as the Data Flow diagram of the Q/R Service. These diagrams and their notation are defined by the standard in part 2 that specify the DICOM Conformance Statement – a standard document that every application vendor should provide and that describes how they implemented the standard in their product. At some point we will get to how to read and write these documents.




The vertical dashed line represents the DICOM Protocol Interface between the two applications (it is usually a single dashed line but in this example it got a bit messed up). The arrows accros the interface represents DICOM associations. The arrow points from the application that initiates the association (the requester) to the application that responds to it (the responder or accepter). The upper part of the diagram shows the control chanel where the C-MOVE request is sent and statuses are reported back by the PACS. The lower part of the diagram shows the data chanel where the DICOM instances are sent to the client.

Modality Performed Procedure Step

Introduction


After the post on Modality Worklist, I felt that it wouldn’t be a complete without explanation on Modality Performed Procedure Step. MWL without MPPS is like a task list without checkboxes, and after all, striking a checkbox on a completed task is great fun. Talking of which, I once red this article about productivity and task lists and since then I’m using a circular checkbox on my paper to do notes because it’s 4 times faster. Instead of 4 lines you only need one. Think of it.

IHE Comes to Rescue


Though the DICOM standard states that it doesn’t go into the details of the implementation and what should be the implications of MPPS on workflow it is very clear from reading the details of the standard that an MPPS is the checkmark of MWL. The gap is closed by IHE radiology technical framework that does a great job and details exactly what should be the workflow and how the implementation should look like. If you are not familiar with IHE, I strongly recommend navigating to their web site and start digging. Getting familiar with the IHE Technical Frameworks can save a lot of expensive software architect hours and more important, save you from implementing things wrong. The IHE TF is high quality software specification document that you can use almost as is for your healthcare IT software projects.


Anyway, if you don’t have time to dig inside the long documents of IHE and DICOM and HL7, here’s a short data and program flow summary:

  1. The modality makes a MWL Query. Each result is a requested procedure object with one or more Scheduled Procedure Steps (SPS).
  2. The user picks one SPS to perform.  
  3. The modality creates a new Modality Performed Procedure Step (MPPS) that references the Study, the requested procedure, and the SPS.  This is done using the N-CREATE command. 
  4. There’s a state machine for MPPS with three states:
    1. In Progress (A dot at the center of the circular checkbox)
    2. Completed (A dash on the checkbox)
    3. Discontinued (Back to the beginning)
  5. After the images acquisition is done the modality sends an updated status for the MPPS using N-SET command. The N-SET must include a performed series sequence with at least one series in it, even if the procedure was aborted (in which case the series will have no images).
  6. At this point the Scheduler should dash the checkbox to mark the task as completed (or discontinued).
  7. Though usually you would have a 1-to-1 relationship between a scheduled procedure and a performed procedure, the DICOM data model has a n-to-m relationship between SPS and MPPS. The connection is made by the MPPS that references the SPS that it was performed for.

The DIMSE-N Protocol


Unlike all the other command that we’ve discussed so far in this tutorial namely C-ECHO, C-STORE, C-FIND and C-MOVE that are DIMSE-C commands, MPPS uses the normalized, DIMSE-N protocol commands N-CREATE and N-SET to create and update the Modality Performed Procedure Step normalized  information entity. We’ve discussed the normalized data model (aka DICOM Model of the Real World) briefly in chapter 4 when discussing DICOM Objects and stating that image objects are composites of modules from different information entities.
Like, in MWL before, here’s where MPPS fits into the DICOM Data Model:

Chapter 12: Pixel Data

Frame 0001
I guess that one can't escape talking about pixels when dealing with DICOM. After all, imaging is what DICOM is all about and digital images are built from pixels. So today, to celebrate release 2.0.2.6 (and the x64 version) of the DICOM Toolkit, I'm finally going to touch the heart of every DICOM Image, The Pixel Data.

For today's post I've prepared a little C++ test application that really does nothing much other then putting pixels into the pixel data of a DICOM file and save it. Well, not exactly nothing much, because it creates a huge DICOM file, more then 0.7 GB and compress it and never use more then 20 MB of memory. If you want to know how, read on.

DICOMDIR and Media Interchange

[update 24 March 2023: Latest releases of HRZ software can be found on HRZ website - www.hrzkit.com]

DICOMDIR, Have you heard this term? What does it mean? Do I need this in my system? Lots of questions. Let's try to answer some.

Here's a list with quick information about DICOMDIR:

  1. Standard DICOM CD/DVD should have a file named DICOMDIR in its root directory.
  2. The DICOMDIR file has in it records that hold paths to DICOM files on the media.
  3. DICOMDIR is a DICOM Object holding a sequence of DICOMDIR records nodes each having a type like PATIENT, STUDY, SERIES and IMAGE
  4. The DICOMDIR file include key attributes from the data on the media such as Patient Name, Patient ID, Study ID, Study Date.
  5. The file names of DICOM files on a standard DICOM CD/DVD should be capital alphanumeric up to 8 characters with no suffix.
  6. The CD/DVD may include other files that are not DICOM. The DICOMDIR file does not reference them.
  7. The mandatory elements of the DICOMDIR nodes are not 1-2-1 with the mandatory elements in the DICOM Objects. For example Study ID which is Type 2 in DICOM Image objects is Type 1 in DICOMDIR STUDY Record. So when creating your DICOM images if you intend to create DICOMDIR for them, add these elements too.
There are two ways DICOM application can collaborate with one another. They can communicate over TCP/IP network connection or they can exchange files over some physical media.

The first figure in the DIOM standard makes sense eventually
The picture above, which is by the way the first figure in the DICOM standard (page 10 of chapter 1), explains that very well although when I first looked at thirteen years ago it it didn't mean anything to me.
It is worth staying a bit longer on this figure because it has a lot of valuable information in it so lets work it top to bottom.

Converting Bitmap, JPEG and PDF to DICOM

Before we move any further, the examples in this post are included in HRZ's MODALIZER-SDK DICOM C# Examples package. Non programmers, can achieve the same results and much more using MODALIZER+ DICOM Wizard, HRZ's administrative PACS workstation. Let's start.

Imagine you're a dermatologist taking pictures of patients' skin for treatment tracking using a digital camera. The pictures are JPEG's and have no patient info in them. If you could convert them to DICOM and send them to the clinic PACS, that would be a great advancement.

Tuesday, January 5, 2016

DICOM Conformance Statement

[update 24 March 2023: latest HRZ softwarecan be found on HRZ website - www.hrzkit.com]

During the process of writing the DICOM Conformance Statement of DICOMIZER 5.0 I realized its been on my task list for more than two years! Its a complicated documented to write but two years ... that's a personal record.

So, what's the thing with this document, the DICOM Conformance Statement (aka DCS). Is it important? Is it mandatory to have one for your DICOM application? Why, When and How to read it? When to write one?

This is from the DICOM Standard:

"By comparing the Conformance Statements from two different implementations, a knowledgeable user should be able to determine whether and to what extent communications might be supported between the two implementations."
And of course the key here is "a knowledgeable user" ha ha!

DICOM Conformance Statement is a very technical document that describes (and some would even go further and say specifies) the DICOM capabilities of a product, a system, software or medical device.

There are two reasons to open the DCS:
1. To evaluate a product, before a purchase for example and,
2. When something goes wrong (maybe because you skipped #1 above).

There's a reason for this chapter position, very deep into the DICOM Tutorial. In order to be able to use the information in the DICOM Conformance Statement one has to have substantial experience and profound understanding of the DICOM standard and its fine details.

Lets take an example. You have a system that produces PDF reports and you want to attach them to the imaging studies in your PACS so when opening the study from the PACS workstation the images and the reports can be reviewed together. That's a nobel goal indeed.

Saturday, February 14, 2015

DICOM's role in the internet world and new release of RZDCX

There's an event held in Israel every year in Hadasa Ein-Karem hospital called IsraPACS. Diego Gicovate is doing a great job organizing it. This year I was invited to say couple of words and decided to ask the question "Where DICOM is going?" What it's role today with all the Internet and cloud technology.

Old lady knitting next to a Renault 4 car
Source: Unknown
(Please contact if you know this picture and or where it came from)

Usually, when I give presentations on DICOM, the introduction, the couple of slides in the beginning,  goes like this: "DICOM is very old, It's very big, It's a bit complicated, but hey, its working!" I have this slide (above) of an old lady sitting outside on a chair and knitting with a Renault 4 in the background. Then I review the parts of the standard, noting that, printed, it probably weighs something like 10 Kilo's and joking that I've read almost all of its 3 - 4 thousand pages. At the end  I show a slide with the poster of Monty Piton's film "The meaning of life" and replace it with the meaning of DICOM and then a slide saying, but hey, 1 standard, 1,000's of vendors 1,000,000's of patients, 1,000,000,000's of images, it can't be so bad, look, its working!

Saturday, September 27, 2014

Video to DICOM (and back)

This is a story of a lost battle. For many years I refused to add MPEG to DICOM functionality in my DICOM SDK. The explanation I gave to myself and to my customers was that storing video in PACS is a bad idea because video streams are usually very big and nobody ever watches them. From an engineering point of view, the size of the video is not so much a matter of disk space but rather a network headache. The way that the DICOM network protocol works, with all the different levels of timeouts and with no failover mechanisms for PDU’s may cause such huge objects to fail over and over when stored and restored. For the clinical point of view, I consulted with Radiologists friends from whom I learned that the driving force behind keeping most of this stuff is not clinical but rather medico legal. These excuses held for some time but eventually, because I’m an engineer but also a businessman, I changed my mind. After all, the customer is always right, and when more and more customers asked to convert video to DICOM, I realized that winning this battle means loosing customers and that’s not something a businessman should do.

Videos were added to DICOM through the mechanism of Transfer Syntax. All together there are currently four (4) video transfer syntaxes for different types of MPEG’s. Here's the list of these transfer syntaxes:
  • MPEG2 Main Profile @ Main Level : "1.2.840.10008.1.2.4.100"
  • MPEG2 Main Profile @ High Level : "1.2.840.10008.1.2.4.101"
  • MPEG-4 AVC/H.264 High Profile / Level 4.1 : "1.2.840.10008.1.2.4.102"
  • MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1 : "1.2.840.10008.1.2.4.103"


If I have to guess, there will probably be more added in the future as new formats of video gain take over. The embedded document option that was taken for PDF would probably be my choice but I admit that I didn’t investigate the reasons that led to the way the standard went and there may have

Wednesday, September 17, 2014

A short one on MPEG to DICOM

This is a quick post referencing our new release of RZDCX 2.0.4.2 that adds the option to convert MPEG to DICOM. I will post a longer article with all the information about MPEG and DICOM, video streams and audio hopefully by the end of this month. Meanwhile, check out this post on our web site and download the latest version of MODALIZER-SDK DICOM Toolkit.
Here's a short C++ code snippet that creates a DICOM encapsulated MPEG to start with:

static void CreateVideo(string filename)
{
    /// Create a DCXOBJ
    IDCXOBJPtr obj(__uuidof(DCXOBJ));

    /// Create an element pointer to place in the object for every tag
    IDCXELMPtr el(__uuidof(DCXELM));

IDCXUIDPtr id(__uuidof(DCXUID));

rzdcxLib::ENCAPSULATED_VIDEO_PROPS videoProps;
videoProps.width = 352;
videoProps.Height = 288;
videoProps.PixelAspectRatioX = 4;
videoProps.PixelAspectRatioY = 3;
videoProps.FrameDurationMiliSec; // 40 msec = 25 FPS
videoProps.NumberOfFrames = 1600; // 1600 frames
videoProps.VideoFormat = rzdcxLib::MPEG2_AT_MAIN_LEVEL;
obj->SetVideoStream(filename.c_str(), videoProps);


obj->TransferSyntax = rzdcxLib::TS_MPEG2_MAIN_PROFILE_AT_HIGH_LEVEL;
    /// You don't have to create an element every time, 
    /// just initialize it.
char pn[]="John^Doe";
    el->Init(rzdcxLib::PatientsName);
    el->PutCStringPtr((int)pn);
    obj->insertElement(el);

el->Init(rzdcxLib::patientID);
    el->Value = "123765";
    obj->insertElement(el);

el->Init(rzdcxLib::studyInstanceUID);
el->Value = id->CreateUID(UID_TYPE_STUDY);
obj->insertElement(el);

el->Init(rzdcxLib::seriesInstanceUID);
el->Value = id->CreateUID(UID_TYPE_SERIES);
obj->insertElement(el);
el->Init(rzdcxLib::sopInstanceUID);
el->Value = id->CreateUID(UID_TYPE_INSTANCE);
obj->insertElement(el);

el->Init(rzdcxLib::sopClassUid);
el->Value = "1.2.840.10008.5.1.4.1.1.77.1.4.1"; // Video Photographic Image Storage
obj->insertElement(el);

el->Init(rzdcxLib::NumberOfFrames);
el->Value = (short)1600;
obj->insertElement(el);

el->Init(rzdcxLib::FrameIncrementPointer);
el->Value = rzdcxLib::FrameTime;
obj->insertElement(el);

filename += ".dcm";
obj->saveFile(filename.c_str());

}

One last note: You should know your video properties because we don't open or validate the MPEG file. More on "why is it this way" in the longer post soon.

Saturday, October 19, 2013

Life beyond Visual

Qt Project Logo
[update 24 March 2023: latest HRZ software can be found on HRZ website - www.hrzkit.com]

The request to add Modality Worklist SCU to a product is common. This time, the product was already capable of exporting DICOM Images but didn't have any network capabilities. The guys from Marketing asked to send the DICOM files to a PACS and add Modality Worklist Query. Very reasonable and makes perfect sense. Only when I got the detailed system requirements did I realize that this project is going to be challenging after all but for different reasons.
Most of our custom software development projects at H.R.Z. are Windows Technology. We do some Java and iOS from time to time but that's not very common. This time we were asked to develop with Qt.

Qt is a cross-platform application framework. The programming language is C++ and there's a pre-processor called MOC on top of that and GUI framework which now, looking backwards, I can say that is actually very good. Originally developed by Trolltech and later acquired by Nokia, Qt offers a wide range of compilers for many target operating systems and hardware ranging from Handhelds and Cell Phones, embedded linux, Mac OS-X and of course Windows. Apparently Qt is more popular in Europe then in the United States, Maybe because of anti-corporate trends in the old continent or maybe simply because its free.

I wanted to take this project. It was an opportunity to see how our DICOM library, RZDCX, performs outside of its C#/.NET comfort zone. We already had at least two respectable customers utilizing RZDCX and Qt in their medical device products that have completed the development cycle and had thousands of units sold worldwide, so I knew it's possible, but while they were using Microsoft Compiler that offers the full comfort of ATL, this project required MinGW compiler which was new to us. Before I could say yes, I had to verify that Qt + MinGW can talk with our DICOM Toolkit so we had to do a little research and evaluation project and that's exactly what we did.

Qt and COM

Like many open-source projects, when it comes to documentation, Qt documentation is inferior to MSDN for example and even to Apple Developer Center. After digging deep into the internet and separating the wheat from the chaff we were able to compile a short cookbook on using COM in Qt. Qt framework includes a class called QAxObject that inherits from QAxBase. These two classes is enough but luckily there's a pre-processor tool called dumpcpp that makes things much easier. dumpcpp generates C++ wrapper classes for type libraries (typelib). With dumpcpp, using RZDCX becomes very easy. Here's our Cookbook.
Using COM Objects in Qt

Wednesday, July 10, 2013

Sneak Peek into DICOMIZER 2.0.5 DICOM Viewer

[update 24 March 2023: Latest releases of HRZ software can be found on HRZ website - www.hrzkit.com]

We are working hard on the upcoming release of DICOMIZER 2.0.5 with integrated DICOM Viewer. This project really shows how easy it is to build DICOM applications with RZDCX. The DICOMIZER and DICOM Viewer are written using C# and use RZDCX DICOM SDK for all the DICOM Services: Storage, Query/Retrieve, Modality Worklist Query, Reading DICOMDIR and Creating new DICOM Objects.
Actually it all started when I decided to gather all our code examples, test applications and code snippets and combine them all together into one big demo Application. We took the DICOMIZER and added to it The Modality Worklist SCU Example. It made sense so we've added the Query/Retrieve SCU Example too. Then, after releasing DCXIMG.GetBitmap, it became very clear that the best way to demonstrate it is by writing a little DICOM Viewer. And so, here we are drifting away into something I always avoided but now can't really remember why.

The main panel has now 7 buttons. You can see the version id as well. This helps.

DICOMIZER 2.0.5 Main Menu
When you drag a DICOM file or even an entire folder and drop them on the DICOMIZER window, the DICOM Viewer display them.

The DICOM Viewer showing a DICOM CT Study

You can drag DICOM files on the DICOMIZER Application or Shortcut icons and they will display.

At this point, we have three areas on the window:

  • The top panel shows the Patients and Studies.
  • The left panel shows Series thumbnails
  • The center main panel shows the current image.
Scroll through the series' images is done using the up and down arrows or using the toolbar.
That's all for now, the rest you case see (the toolbar icons are quite standard from the BIR document).
Make sure to like us on Facebook and get frequent updates or stay tuned here.


Wednesday, May 29, 2013

Using the DICOM File Meta Information to Identify a DICOM file

[update 24 March 2023: Latest releases of HRZ software can be found on HRZ website - www.hrzkit.com]

I know I shouldn't do this but I'll do it anyway and apologize for not posting as frequent as before. This is for very good reason that I'm very busy with everyday work. One little example is the new DICOMIZER 2.0 released just few days ago and this is just a tiny project that my involvement in was really limited to giving some guidelines to the team. Naturally, the new DICOMIZER uses RZDCX. It is written in C# and uses the new features of version 2.0.3.0 of the DICOM Toolkit that all of them were requested by readers of this blog and of course our loved customers. I hope to release some code snippets from the new release soon but in this post, just before getting to the main subject (identifying DICOM files), I want to describe the new GetBitmap call of DCXIMG that returns a bitmap in memory and is used in the new DICOMIZER when you drag a DICOM file on top of the application. Here's a screenshot.

The little code that do the trick follows.

Tuesday, December 18, 2012

DICOM Server and DICOM Toolkit new Release 2.0.2.8

The last couple of weeks were very busy with many installations of HRZ DICOM Server all over the world. It turned out to be a product that many people were waiting for and we've been busy with installations and support work. Naturally, many issues were found and fixed. These fixes and improvements were gathered into the last release that is now available online. It was great fun to see that people liked the idea of the server and modified and customized the database mappings to meat their own requirements. For me this was the best indication that the product concept is really working.

Release 2.0.2.8

A new release is ready on the DICOM downloads page. This release addresses couple of bug fixes and improvements to the DICOM Server and DICOM Toolkit. Many of these changes were initiated by customers requests and I would like to thank you for the feedback and bug reports.

Saturday, June 30, 2012

Convert DICOM to Bitmap in 3 lines of code

In an earlier post I covered how to convert JPEG to DICOM and also PDF and Bitmap to DICOM. In this very short post I'm going to show the opposite direction, which is much simpler,  converting DICOM to Bitmap.
With MODALIZER-SDK this is very simple. Here's the C# code:


            DCXIMG img = new DCXIMG();
            img.LoadFile(dcmfile.Text);
            img.SaveBitmap(0, bmpFile.Text);


dcmfile and bmpFile in this example are text boxes.
SaveBitmap first parameter is the frame number (0 based index) as a DICOM file may have many frames in it.
The DCXIMG class takes care of all conversions and decoding of the image if the pixel data in the DICOM file is compressed.
That's it on this subject. Comments and questions are most welcome.

Saturday, February 4, 2012

Documentation Update for version 2.0.1.9

The online documentation is now updated for version 2.0.1.9. In the new documentation there's new page with information for DICOM conformance that is useful for writing the DICOM Conformance Statement.

Wednesday, February 1, 2012

RZDCX 2.0.1.9

A new release of ZRDCX, 2.0.1.9, was released today. This release fixes the following issues:


#TypeStatusCreatedChangedVersionTitle 
Description
 
291codefixedJan 30Jan 30 DICOMDIR with strict = false fails on file names with .'sedit
Create filenames like 1.2.3.4.dcm ScanAndCreate(..., false) -> Exception Reported by SBX
 
290newfixedJan 19Jan 192.0.1.8MoveAndStore - Single threaded C-MOVE duplexing control and dataedit
Add a method MoveAndStore to DCXREQ to allow one command that performs both the C-MOVE and the C-STORE commands on separate but semi-synced associations.
 
287newfixedDec 12Dec 122.0.1.8Minor logging additions to RZDCXedit
Fix log messages when pres ctx id not found in store


Issue 291 addresses a very popular feature request to enable creation of DICOMDIR even when the filenames are not according to the standard. For example filenames with the instance uid like 1.2.3.4.5.6.dcm are not valid reference file id's according to the standard. Nevertheless, sometimes you would like to create a DICOMDIR file for other purposes other than exporting data on a CD. The ScanAndCreate method of DCXDICOMDIR takes a "strict" parameter that when set to false, will generate a DICOMDIR regardless of the validity of it's content (as long of course that the files are DICOM files).

Issue 290 is a new feature of RZDCX that enable to run a complete C-MOVE SCP with a single command including the incomming association. More about this feature in the upcoming chapter of the DICOM Tutorial.
Here's a short example


        public void MoveAndStore()
        {
            // Create an object with the query matching criteria (Identifier)
            DCXOBJ query = new DCXOBJ();
            DCXELM e = new DCXELM();
            e.Init((int)DICOM_TAGS_ENUM.patientName);
            e.Value = DOE^JOHN";
            query.insertElement(e);
            e.Init((int)DICOM_TAGS_ENUM.patientID);
            e.Value = @"123456789";
query.insertElement(e);
            // Create an accepter to handle the incomming association
DCXACC accepter = new DCXACC();
            accepter.StoreDirectory = @".\MoveAndStore";
Directory.CreateDirectory(accepter.StoreDirectory);
            // Create a requester and run the query
DCXREQ requester = new DCXREQ();
            requester.MoveAndStore(
                MyAETitle, // The AE title that issue the C-MOVE
                IS_AE,     // The PACS AE title
                IS_Host,   // The PACS IP address
                IS_port,   // The PACS listener port
                MyAETitle, // The AE title to send the
                query,     // The matching criteria
                104,       // The port to receive the results
                accepter); // The accepter to handle the results
        }

This single command takes care of all the details of a C-MOVE transaction. Instead of running an accepter on another thread to wait for the C-MOVE results, we pass the accepter as a parameter to the MoveAndStore method of the requester. Note that there's a new set property in DCXACC that enables setting the directory to store the incoming files. All the callbacks of DCXACC and DCXREQ can be used as well just as before.

Issue 287 is a small log enhancement that maxes it easier to to diagnose association problems. The log now shows very clearly when a presentation context for a command was not negotiated.

Monday, January 23, 2012

DICOM Query/Retrieve Part I


It all started when I was sitting in a cubicle with a customer, looking at the code of their workstation performing a Query/Retrieve cycle and though everything did look familiar and pretty much straight forward something bothered me.

Query/Retrieve, or Q/R for short, is the DICOM service for searching images on the PACS and getting a copy of them to the workstation where they can be displayed.

Q/R is a fundamental service and every workstation implements it. This sounds like a trivial task, just like downloading a zip file from a web site but there are a lot of details to take care of and while writing this post I realized that I will have to split it to a little sub-series. Today's post will be about the Query part and in the next post I'll get to the Retrieve.

To search the PACS we use the DICOM command C-FIND. This command takes as an argument a DICOM object that represent a query. The PACS transforms the object that we send to a query, probably to SQL, runs it and then transform every result record back into a DICOM object and send it back to us in a C-FIND response. The PACS sends one C-FIND response for every result record. While still running, the status field of the C-FIND response command is pending (0xFF00). The last response has a status success. It may of course fail and then RZDCX will throw an exception with the failure reason and status. It may also succeed but with no matches (empty results set).

Let's do some examples. This code constructs a query for searching patients:

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

            el.Init((int)DICOM_TAGS_ENUM.QueryRetrieveLevel);
            el.Value = "PATIENT";
            obj.insertElement(el);

            el.Init(0x00100010);
            el.Value = "R*";
            obj.insertElement(el);

            el.Init(0x00100020);
            obj.insertElement(el);

            el.Init((int)DICOM_TAGS_ENUM.PatientsSex);
            obj.insertElement(el);

            el.Init((int)DICOM_TAGS_ENUM.PatientsBirthDate);
            obj.insertElement(el);

Sunday, May 15, 2011

RZDCX DICOM Library Release 2.0.0.8

The new release of RZDCX - Fast Strike DICOM Toolkit addresses customers change requests and enhancements.
The change log is detailed in the following table.

#TypeStatusCreatedBySubsysChangedAssignedSvrPriTitle
253newfixedMar 23zroniRZDCXMar 23zroni53Limit log file sizeedit
254newfixedApr 20zroniRZDCX10:52zroni33Support Unicode filenamesedit











256newfixedMay 14zroniRZDCXMay 14zroni53Add Status Detail to Error Messageedit


All changes does not affect the default behavior of the DICOM Library.

Change #253 addresses the size of the log file. This change enables the user to set a size limit in terms of number of messages in the file. The change introduces new methods to the DCXAPP interface that control the log file size and filename. For more information please read the DICOM Library Documentation page dealing with DICOM Diagnostics and Logging.

Change #254 adds support for Unicode filenames. After this change, all method parameters that carry filenames (e.g. OnStoreSetup, OnStoreDone, SaveFile, openFile, Send, CommitFiles) may use Unicode filenames strings. For example, if your application requires to save DICOM files with names with Mandarin characters, this is now supported.

Change #256 adds more information to the error description that is provided when a DICOM command fails by dumping all optional command attributes that were provided by the peer application into the error description string. The status details attributes are optional elements that a SCP may provide when commands fail. These may be a list of offending elements or other information that can help diagnose the problem. See for example DICOM Stabdard part 7, Section 10.1.5.1.6 describing N-CREATE Status Detail.

Sunday, January 16, 2011

DICOM SR - Structured Reports Made Easy with RZDCX 2.0

A new year is the perfect time for a new product version.
2011 is the year for the new release of RDCX DICOM Toolkit version 2.0 with structured reporting.

The major feature of this release is the all new DCXSR interface for creating DICOM Structured Reports using the dynamic SR dictionary.

If you had the chance to play around with DICOM SR's, you'll probably agree with me about one thing: so many attributes for so little information, ha? Just look at all these nested sequences, oh my god!