Wednesday, December 5, 2012

Part 19 of the DICOM Standard

DICOM Plugin Model
While preparing for a meeting with a new customer I took some time to review part 19 of the DICOM standard that I haven't red yet. Actually I should have done it before even it went out but being busy with other issues, it got ever delayed. Part 19 of the DICOM standard carries a prominent name, "Application Hosting". For me, Application Hosting immediately associates with Amazon EC2, Google App Engine, Cloud Computing and Grid. You can imagine my disappointment when I found out that behind the cover page I couldn't find anything of that kind. Instead, part 19 is a very detailed software specification document of a plugin model for two applications collaborating with one another over SOAP. It includes WSDL's and call sequencing diagrams that explains how the host application can invoke (or connect to) the plugin and exchange Web Services URL's that each application can then work with to collaborate with one another. The model is well defined and when I got few days ago an email Ad from Aunt Minnie about the Philips IntelliSpace PACS API I immediately went to look if it uses the DICOM plugin API Model. The Ad went to Philips Medical web site and as far as I could figure out their API is not based on DICOM's Application Hosting part. As of this moment I don't know of any vendor that does implement DICOM Application Hosting and if one of the reader does know such vendor, please comment and share this info with me.

Friday, November 30, 2012

COM is not Dead

Once in a while I get questioned why am I still using COM when there's newer technology like .NET that dominates Windows development. When I started working with DICOM the latest technology was COM and frankly speaking COM gave me harder time then DICOM back then, but after accommodating to the principals, COM had proven itself as a great way for module segregation setting clear interfaces and concrete boundaries between software components. Even now, after almost thirteen years and after countless declarations from Microsoft that COM is no longer to be supported, COM is integral part of Windows OS and actually using COM in .NET (C# or VB.NET) is much simpler then before. Even the annoyance of registering COM objects with regsvr32 no longer exists with the so simple option of side by side assemblies in .NET projects.
Eliminating regsvr32 using Side by Side assemblies Isolated flag

The reason I'm telling you all this is a little project I've been working on lately. In this project there's a department scheduler that provide the worklist through a web service but the Modalities need a DICOM Modality Worklist So I've been asked to bridge between the two. My solution was to create a plugin for the HRZ DICOM Server that calls the web service whenever a Modality Worklist Query is received. So the Modalities talk DICOM to the DICOM Server that translates their query to a SOAP call and then translates back the response to DICOM.
Implementing a web service client is so simple in C# and the DICOM Server plugin model already provide the Modality Worklist frameworks so all that is left to be done is to call the C# Web Service client from a DICOM Server plugin which is native C++. Ouch! How to use managed DLL from native executable? Exactly! COM! With a single check-box and couple of attributes you can turn any .NET class into a COM object and then use it in your native code.
Turning a C# Class into a COM Object
All that is left to do is to set "Register for COM interop" check-box in the .NET Class Library project properties page.
Register for COM interop flag
And now we have a .NET library ready to be called from native C++ using COM. To complete the integration we use RegAsm to add the registry entries for the COM and that's about it.

In the C++ code the TLB is imported using #import Pre-Processor directive and the method is called just like any other COM API



      USES_CONVERSION;
      _HospPatientByIDPtr api(__uuidof(HospPatientByID));
      BSTR first_name(0);
      BSTR last_name(0);
      VARIANT_BOOL res = api->GetPatientInfoByID(
             A2W(pid.c_str()), &first_name, &last_name);

Thursday, October 25, 2012

Patches to the Modality Worklist Database

It turns out that the Modality Worklist Server draws a lot of attention and that there were couple of glitches in the last release. The main issue comes from date and time columns in the database (i.e. datetime sql type). Until this is fixed in the DICOM Database Plugin, here's a little patch that maps the database date and time fields to valid DICOM date and time formats.

The DICOM date format is YYYYMMDD and the DICOM time format is HHMMSS.TTT or HHMMSS

Another issue that is going to be solved in the next release is the case sensitive column names. This means that in order to add more fields to your MWL C-FIND Response, you should add the columns to the view exactly as they are named in the toolkit dictionary with the correct case. This problem was in the last build modality field that should have been Modality with a capital M.

Wednesday, July 18, 2012

OTech: Is your PACS ready for DICOM 4.0?

OTech: Is your PACS ready for DICOM 4.0?: Despite the title of this article, DICOM does not have any version indicator; as a matter of fact, the DICOM standardization committee, lo...

Wednesday, July 11, 2012

DSRSVC DICOM Modality Worklist Server - Update

I got a response that the Database plugin for the DICOM Server crashes. Where was a problem in DICOM Database Plugin that didn't export the configuration symbol and as a result the server didn't pick it up.
This problem is now fixed and the new build is available on the download page. If you've downloaded version 2.0.2.2, please download version 2.0.2.3 instead.
I would like to thank Igor that found this problem and reported it to me.

Sunday, July 8, 2012

DICOM Modality Worklist Server

HRZ DICOM Server is in use for many years in my custom software projects. It's a windows based service that is easily installed and configured. I've been using it since 2008 for various purposes and it is now a very stable and reliable software.
In this post I'm going to present its use as a Modality Worklist Server (or in short MWL SCP), explain how to install the software and how to configure the database to match your needs. Then, on the next post, I'm going to combine it together with processing HL7 order message to schedule a new work item. This will close the gap between HL7 and DICOM and we'll have most of the parts of IHE's radiology schedule workflow (SWF) integration profile.


What's the difference between a DICOM Server and a PACS?

Throughout the years, as PACS evolved, there were many debates about what is the feature set that makes a PACS? Does it have to have a Viewer? Does it have to provide all DICOM services? Should it have HL7? Many questions and even more answers. Calling it a DICOM Server is a laundry cleaning bypass of all that. It's a DICOM Server meaning it serves requests for DICOM Clients. What services does it provide? DSRSVC is a Storage SCP by default and you can add more services to it as you like using a plugin API. In the download page you'll find two plugins. The INI file plugin provides configuration for the storage service. The MS SQL Server DICOM Database Plugin adds:
  • Query/Retrieve SCP, 
  • Storage Commitment SCP and 
  • Modality Worklist SCP
Throughout the years it was used in all kind of applications, as an inbox for web viewer, as a CAD engine, as a departmental archive, as a proxy, as a bridge, and many more.

If you're looking to speed up development and use an off-the-shelf software product that you can easily extend, customize and integrate with your system, read on.

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.