Tuesday, December 25, 2012

C# Tricks


I did some UI work in C# lately and discovered all kind of cool new stuff. So cool, I couldn't resist sharing it with the world.

Lets say we have a multi-threaded application that throws tasks (TPL) in the back-end.

The tasks report back and we want to reflect it in the UI but we should update UI always in the main thread. We use Invokefor and in many places in the code we have chunks of the kind:

void SomeFunction()
{
  if (this.InvokeRequired)
    this.Invoke(new MethodInvoker(SomeFunction)
  else
  {
     // Here goes some UI functionality
  }
}

this is the form we are working in for example.

With .NET 3.0 we have Action so we can write one function like this

        void DoUiStuff(Action a)
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(a));
            else
                a();

        }

Then whenever we want a UI action we write a lambda expression for example:

DoUiStuff(() => progressBar.Visible = true);

or even a code block like this:

DoUiStuff(() =>
            {
              progressBar.Visible = false;
MessageBox.Show("Done!");
});

Fun ...



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.

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.