Showing posts with label QIDO-RS. Show all posts
Showing posts with label QIDO-RS. Show all posts

Wednesday, April 22, 2015

QIDO-RS Capability Breakdown

Recently I created a github repository to track the available DICOMWeb implementations and their capabilities.  While a vendor may claim to support a given DICOMWeb API, the devil really is in the details.  These details are supposed to be described in the conformance statement but these are usually incomplete (or wrong).  This post attempts to break down QIDO-RS at a deeper level so we can more accurately assess how complete and compliant a given implementation is:


Feature Description
application/dicom+xml Can return responses with Content-Type: multipart/related; application/dicom+xml
application/json Can return responses with Content-Type: application/json
gzip Can return responses with Content-Encoding: gzip. Note that this is not mentioned in the standard and is therefore not required (but I feel should be supported and am therefore including it)
no-cache Supports the Cache-control: no-cache header which ensures the result is current and not cached on the client side. Note that this is not required by the standard (but I feel should be supported and am therefore including it)
group/element Supports specifying DICOM elements by group/element (e.g. 0020000D)
keyword Supports specifying DICOM elements by DICOM keyword (e.g. StudyInstanceUID)
sequences Supports specifying sequence elements (e.g. RequestAttributeSequence.RequestedProcedureID)
limit Supports the limit option for queries (limits the number of records returned)
offset Supports the offset option for queries (skips records in the response to support paging)
TimezoneOffsetFromUTC Supports specification of the timezone as part of date/time queries. Note that this is not required by the standard
QIDO-RS Studies Supports searching for studies via the /studies endpoint
QIDO-RS Studies response /studies response includes all required attributes
StudyDate - single Supports searching for studies by study date by single value match (e.g. exact match)
StudyDate - range Supports searching for studies by study date range
StudyTime - single Supports searching for studies by study time by single value match (e.g. exact match)
StudyTime - range Supports searching for studies by study time range
AccessionNumber - single Supports searching for studies by accession number by single value match (e.g. 1233456)
AccessionNumber - wildcard Supports searching for studies by accession number by wildcard (e.g. 1234*)
ModalitiesInStudy - single Supports searching for studies by modalities in study by single value match e.g. (CT)
ModalitiesInStudy - list Supports searching for studies by modalities in study by list of values (e.g. CT,MR,US)
ReferringPhysicianName - single Supports searching for studies by ReferringPhysicianName by single value match
ReferringPhysicianName - wildcard Supports searching for studies by ReferringPhysicianName by wildcard
PatientName - single Supports searching for studies by PatientName by single value match
PatientName - wildcard Supports searching for studies by PatientName by wildcard
PatientID - single Supports searching for studies by PatientID by single value match
PatientID - wildcard Supports searching for studies by PatientID by wildcard
PatientID - list Supports searching for studies by PatientID by list of values
StudyInstanceUID - single Supports searching for studies by StudyInstanceUID by single value match
StudyInstanceUID - list Supports searching for studies by StudyInstanceUID by list of values
StudyId - single Supports searching for studies by StudyId by single value match
StudyId - list Supports searching for studies by StudyId by list of values
StudyId - wildcard Supports searching for studies by StudyId by wildcard match
QIDO-RS Study Series Supports searching for series via the /studies/{StudyInstanceUID}/series endpoint
QIDO-RS Series Supports searching for series via the /series endpoint
QIDO-RS Series response Search for series response includes all required attributes
Modality - single Supports searching for series by Modality by single value match
Modality - list Supports searching for series by Modality by list of values
SeriesInstanceUID - single Supports searching for series by SeriesInstanceUID by single value match
SeriesInstanceUID - list Supports searching for series by SeriesInstanceUID by single value match
SeriesNumber - single Supports searching for series by SeriesNumber by single value match
SeriesNumber - range Supports searching for series by SeriesNumber by matching a range of values
SeriesNumber - list Supports searching for series by SeriesNumber by matching a list of values
PerformedProcedureStepStartDate - single Supports searching for series by PerformedProcedureStepStartDate by single value match
PerformedProcedureStepStartDate - range Supports searching for series by PerformedProcedureStepStartDate by matching a range of values
PerformedProcedureStepStartTime - single Supports searching for series by PerformedProcedureStepStartTime by single value match
PerformedProcedureStepStartTime - range Supports searching for series by PerformedProcedureStepStartTime by range of values match
ScheduledProcedureStepID - single Supports searching for series by RequestAttributeSequence.ScheduledProcedureStepID by single value match
RequestedProcedureID - single Supports searching for series by RequestAttributeSequence.RequestedProcedureID by single value match
QIDO-RS Series Instances Supports searching for instances in a series via the /studies/{StudyInstanceUID}/series/{SeriesInstanceUID}/instances endpoint
QIDO-RS Study Instances Supports searching for instances in a study via the /studies/{StudyInstanceUID}/instances endpoint
QIDO-RS Instances Supports searching for instances via the /instances endpoint
QIDO-RS Instance response Search for Instance response includes all required attributes
SOPClassUID - single Supports searching for instances by SOPClassUID by single value match
SOPClassUID - list Supports searching for instances by SOPClassUID by list of values
SOPInstanceUID - single Supports searching for instances by SOPInstanceUID by single value match
SOPInstanceUID - list Supports searching for instances by SOPInstanceUID by list of values
InstanceNumber - single Supports searching for instances by InstanceNumber by single value match
InstanceNumber - range Supports searching for instances by InstanceNumber by range of values
InstanceNumber - list Supports searching for instances by InstanceNumber by list of values


Vendors can go beyond this list of features by adding support for additional matching keys, including additional fields in the response, fuzzy matching and relational queries.  I didn't include these features as they are not required by the standard, not required by most use cases and rarely implemented.

What are your thoughts on this list?  Should something be added or removed?

Sunday, April 12, 2015

The importance of WADO-RS Retrieve Metadata

One of the most exciting aspects of WADO-RS is the Retrieve Metadata call.  Retrieve Metadata enables access to all non pixel elements for all SOP Instances in a study with a single HTTP request.  This capability doesn't exist in DIMSE services requiring applications to design around what is available via CFIND/QIDO-RS (a small subset of tags) or prefetching the entire study via CMOVE/WADO-RS Retrieve Study (which includes pixel data) in advance.  

Designing around CFIND/QIDO-RS is a huge limitation as there are many elements not returned by CFIND that are required for viewers to properly display the right initial images to a user.  For diagnostic use cases, it is really important to display the right initial images to the radiologist as quickly as possible (less than one second from opening the study ideally).  Doing this is not easy because DICOM does not define what an initial view of a study should be.  This is entirely left up to the application designer and requires taking into account specifics of the procedure, capabilities of the acquisition modality, user preferences and overall application design.

Here are some examples of the additional attributes needed beyond what is provided by CFIND/QIDO-RS:
1. Some MRI Procedures produce multiple echos in the same series.  Most users prefer that each of these echos be displayed as a separate stack
2. Some CT procedures produce multiple phases in the same series (arterial and venus).  Most users prefer that each of these phases be displayed as a separate stack
3. Some procedures will include multiple images in the same series and users will want them displayed independently (not stacked).  Detecting this often requires looking at specific tags
4. Key objects, presentation states and structured reports will often impact which images are initially displayed as well.  Note that in some cases these instances alone can drive the initial image display (e.g. display the Key Objects to a clinician)

In addition to this, the sort criteria for a stack can also vary requiring additional data not returned by CFIND/QIDO-RS.

Given that CFIND/QIDO-RS do not provide enough data for a viewer to always select the initial images to display, we are forced to pull the entire study over using CMOVE or WADO-RS Retrieve Study before we can analyze it.  While one of the goals of WADO-RS Retrieve Study is rapid access,  it isn't clear how fast the various implementations actually will be (I haven't had a chance to test any real implementations myself yet).  While it might be technically possible to load a large study over a 10 GB/s network in under a second this is not easy to do and will likely not be seen in the real world for many years to come.

While prefetching studies in advance using CMOVE or WADO-RS Retrieve Study will work, there is no way to prevent the pixel data from being sent which can limit the number of priors pulled due to limitations of the archive and network.  The pixel data is often over 100x larger than the rest of the elements in each SOP Instance so prefetching is often limited by the raw throughput of the archive software, storage subsystem or network infrastructure.

WADO-RS Retrieve Metadata therefore solves a huge problem with respect to integrating third party viewers with an image archive.  It provides rapid access to all of the non pixel data in a single HTTP request.  This provides more data than QIDO-RS (and CFIND) and is faster than WADO-RS Retrieve Study (and CMOVE).




Sunday, May 25, 2014

Implementing a QIDO-RS Service

Having previously implemented a basic QIDO-RS worklist using JavaScript, I figured it would be useful to implement a QIDO-RS service to improve my understanding of the standard. For those unfamiliar with QIDO-RS, it allows web based queries for studies, series and instances - similar to C-FIND. This weekend I implemented a simple service implementation using C#, Visual Studio 2013 and ASP.NET MVC 5 WebApi. You can find the source code for this project on my github here.  

Overall I found the implementation to be fairly straightforward and it took me about 16 hours total. About 2/3 of this time was related to a) understanding the standard and b) working through various issues with Visual Studio 2013 and ASP.NET MVC 5 WebApi (neither of which I had used before).  

Here are some of my thoughts after getting this implemented:

1. I found several errors in the DICOM standard:

  • Modality has incorrect tag in Table 6.7.1-2a
  • Missing Study Description tag in Table 6.7.1-2
  • Misspelled StudyInstanceUid on line 641
  • JSON Example in F.2.1.1.2 is Invalid JSON (missing a comma between array entries)

2. The standard was difficult to understand

  • It makes several references to concepts documented elsewhere (e.g. fuzzymatching,)
  • It seems to be designed as a web wrapper around CFIND which therefore requires fully understanding CFIND

3. It isn't clear what functionality is required and what is optional. This may be due to it being designed as a wrapper around C-FIND and I don't have expert level knowledge of C-FIND.

4. The JSON mapping was not designed for ease of use by JavaScript developers.  From F.2 in the standard "The DICOM JSON Model follows the Native DICOM Model for XML very closely, so that systems can take 790 advantage of both formats without much retooling".  Here are some specific issues

  • The attribute tag (group/element) is used as the property name in the JSON object. JavaScript code cannot use dot notation to access these properties since it is not supported for property names that do not begin with a letter. This could have easily been solved by putting a letter like x in front of the group/element.
  • The inclusion of the VR field seems unnecessary since the native JavaScript type system is used.
  • Putting all values in an array is awkward. It would have been better to only use an array for attributes with multiplicity > 1
  • The use of Alphabetic, Ideographic and Phonetic in the PN mapping is unclear. I am sure these are documented somewhere else in the standard - but where? Having a PN value be an object instead of string is also a bit awkward.
  • The casing for property names is not consistent. vr starts with lowercase letter while the others start with an uppercase letter. The most common naming convention in JSON/JavaScript is the first letter lowercase.



Overall this is a positive step forward to bringing DICOM into the world of the web but more can be done to reduce the barriers to using DICOM by developers. The best way DICOM can reduce these barriers is to make web browser and JavaScript based consumption a top priority and make it as easy to use as possible in that environment. Efforts such as the dicomWeb online documentation are very helpful and so are open source implementations of the standard.