Sorting dynamic studies in DICOM

I work with dynamic, or multi-frame, PET scans, so in essence 4-D datasets.  Nuclear medicine scans have frequently used file formats that are either proprietary or  used largely or wholly by NM scans.  These formats tend to support dynamic studies natively.  Newer PET scanners come with native DICOM capabilities, but older scanners and some research scanners use different file formats.  I’ve been trying to get everything into DICOM format, so it can all go into a PACS for storage and distribution.

One of the tricky steps is, getting your software to recognize the concept of a timeframe, or volume.  There are several DICOM header elements that could be used to group the slice files into frames, and different software interprets the headers differently.  I’m building DICOM headers from scratch for a scanner that creates ECAT format files, and this step is proving quite interesting, shall we say.

I started by looking at how a commercial system groups dynamic PET studies.  The example I’m using is a GE PET scanner which is acquiring 30 frames of 35 slices each, so it creates 1,050 DICOM files.  I notice that while Vinci shows the 30×35 arrangement, the Osirix viewer and DCM4CHEE PACS server both show the study as a single frame of 1050 files.

So how are they being grouped?  I have a small perl utility program I use to show differing fields between two DICOM files.  I rename the DICOM files when I receive them from the PACS, since we use a wide range of research software, very little of which is PACS- or even DICOM-aware.  So for much of our research needs, we just treat the DICOM files as image files, and number them from 1 to 1050.

First, I compare two adjacent slices from the same frame.

[widget dynamicpet] 115% 0001.dcm 0002.dcm | grep -v UID
0008 0013  InstanceCreationTime: 122044.000               122045.000
0020 0013           ImageNumber: 1                        2
0020 0032  ImagePositionPatient: 128128                1281284.25
0020 1041         SliceLocation: 0.00000000000000         4.25000000000000
0028 1053          RescaleSlope: 0.20659                  0.106116
0054 1330            ImageIndex: 1                        2
Nothing unexpected here, the image number and index are sequential and the image position increments by the thickness of one slice.  I do note though that InstanceCreationTime is the time of reconstruction, so is not going to be useful to tell one frame from another.  RescaleSlope differs from slice to slice – with the very wide range of values in a PET scan, it’s customary to scale each slice separately.

Next, I look at the difference between the same slice in two consecutive frames: files 001 and 036 hold slice 1 from frames 1 and 2.

[Note: I'm numbering the frames and slices from 1.  My background is CS so all experience and intuition says I should count from 0, and some software does just this, but I find that counting from 1 confuses fewer people than counting from 0.]

[widget dynamicpet] 117% 0001.dcm 0036.dcm | grep -v UID
0008 0013  InstanceCreationTime: 122044.000          122059.000
0008 0033             ImageTime: 110638.00           110419.00
0020 0013           ImageNumber: 1                   36
0028 1053          RescaleSlope: 0.20659             1.62858
0054 1300    FrameReferenceTime: 0                   15000
0054 1321           DecayFactor: 1.00427             1.01288
0054 1324        DeadTimeFactor: 1.61667             2.54626
0054 1330            ImageIndex: 1                   36

Well we have another time field differing, ImageTime, but it’s not related to the frame time because this scan started at 08:34.  ImageNumber and ImageIndex both are counting the file number rather than slice number.  The key field that differs here is (0054,1300) FrameReferenceTime, which is listing the frame start offset in milliseconds.  This field is part of the NM multi-frame module so is present only in NM scans.

Microsoft IIS 7

IIS 7 is Microsoft’s latest web server, if such a complex and comprehensive package can be reduced to two words.  I’ve been working with IIS for the first time, and it sure as heck isn’t Apache.

The ClearCanvas PACS installation has been about getting three items installed and communicating – ClearCanvas itself, IIS, and SQL Server. I found a very good resource for debugging IIS 7 errors: Mark Volodarsky’s Troubleshoot IIS Errors Like A Pro.    

I followed his instructions for turning on Failed Request Tracing Rules.  This does largely what it says, building a log file of failed requests.  This in turn led me to another error 500.19 Internal Server Error: “This configuration section cannot be used at this path” in my web.config file located within the ClearCanvas Server web directory.

Pressing on…I’m out of my depth here.  I followed these instructions regarding editing my applicationHost.config file located in Windowssystem32inetsrv.  Hey I’ve come this far, why not start messing with system files I don’t understand.  I turned on overrideModeDefault to “allow” for several modules.  While I was at it, I went back to the IIS settings in the Windows Features, and checked pretty much every feature I could find for IIS.  I’m going to need about a terabyte of RAM to run all this.

I’m not sure if I’ve made progress.  Now when I try to access the local CC Server web site I get a Server Error stating, amongst other things, “WRN: Assembly binding logging is turned OFF.  To enable assembly bind failure logging, set the registry value [HKLMSoftwareMicrosoftFusion!EnableLog] (DWORD) to 1.”.   Into the Registry Editor I go, what the heck.  I discover there is no key called Fusion!EnableLog…and I’m out of ideas.  I’m not going to start hacking the registry blind.


Installing ClearCanvas Server

I’ve written previously about installing Microsoft SQL Server 2008 Express to support ClearCanvas Server.  Once I got it running, I moved on to the server itself.  I’m making things a little hard for myself by running Vista, with IIS 7 and SQL Server 2008, instead of the example configuration of XP with IIS 6 and SQL Server 2005.

The first hurdle was getting SQL Server authentication, which is a step in the ClearCanvas Server installation program.  There are a few permutations of username and database server formats that I experimented with until I got a connection to succeed.  The CC installer just gave a ‘pass/fail’ message, but I checked in the SQL server log for a descriptive messages.  My problem was that I’d been using an SQL login that I’d created, rather than the ‘SA’ login that the CC Server installation process had created.  Note that you do have to go in and activate the SA account, it’s disabled by default. The installation process does not halt if a successful connection is established, but to the wrong account. So I got pretty good at uninstalling and reinstalling, going by either the install log file or the lack of a database named ‘ImageServer’ in SQL Server.

Most of my other knowledge was gained by not reading the manual, and trying to install the packages myself. So the best advice I can give is, follow the instructions closely, particularly the section about SQL Server Express.

The first thing I did wrong was to have SQL Server set up to use Windows authentication only.  The CC Server install guide clearly states I have to have SQL Server authentication mode enabled, whereas I, not having RTM, had the default which was to have Windows authentication mode only.  This is a setup option in SQL Server but thankfully can also be changed in the SQL Server Management Studio under ‘Security’ in the server properties.  This is something else I learned from belatedly reading the CC install manual.
Some more of learning from my mistakes.  I initially tried a Username of the form ‘andypc2ahc’ which is the domain-style name format (I’m running Vista, which uses Windows Server-style accounts).  I created this account in SQL Server Management Console and the domain (machine name) is prefixed upon clicking ‘Check Names’.  Perhaps this is from the habit of using Windows domain-style logins.  It caused a problem here though, for one thing the backslash was being escaped Unix-style and I was getting SQL error messages about an account ‘andypc2ahc’ not being found.  I tried the Unix solution of ‘andypc2\ahc’ but didn’t hold much hope of success, and I wasn’t (or was) disappointed.  Finally I created an account under SQL Server with just my login ‘ahc’ and no machine/domain name prefix.  This is what led me to believe I had an SQL connection, but in fact it was to the wrong account (not SA).

Here’s what the CC Server install log file showed when I was not using the SA account:

The other sticking point (also my mistake) was the ‘DB Server’ field.  The SQL Server Management Console refers to the server entity as ‘andypc2SQLEXPRESS’ and this was ultimately worked.  Entering either ‘SQLEXPRESS’ or ’’ lead to no messages in the error log, meaning that the database was not found at all.  This was because I’d failed to follow instructions and allow TCP connections to SQL Server Express…

Once I had that sorted, things were easier.  I accepted the default settings for the database name (‘ImageServer’) and the CC Server Filesystem.  This defaulted to C:FS, and I don’t like to fill up my C: drive top level with directories, but during the first install of programs I tend to accept the defaults until I understand the program.  For the same reason, I accepted SQL Server installing its database files under ‘C:Program FilesMicrosoft SQL Server’ whereas I’d prefer these potentially very large directories to be somewhere other than my C drive and certainly not mixed in with my program files.  In my next install, I’ll move both these directories off to another drive and in a directory I know to contain only data.

Next, I changed the Partition AE Title to ‘CCSERVER’, and the port number from the default of 104 to an arbitrary port of 11100.  I test and run multiple PACS servers, and I can’t have them fighting over port 104 (currently I have K-PACS using that port).  On this machine I’m also running the DCM4CHEE PACS server which defaults to port 11112 (the ‘second-choice’ PACS port after 104), so I chose something close to it. This keeps them grouped in the list of exempted ports in Windows Firewall.

Clicking ‘Next’ and off we go.  These Microsoft installs are so complex that I just hope they work – there is no source-code hacking or library-linking here. 

I did have to make one change, due to running IIS 7 (I have Vista SP1 installed).  The installation stopped with the error message “Error 424 trying to create IIS virtual directory”.  I eventually found from this site that I had to enable “IIS 6 Management Compatibility” under “Windows Features” in the Programs and Features control panel.  This message came right at the end so I had to uninstall CC Server, enable the IIS feature, and reinstall.  This process doesn’t take very long.