Group Abstract Group Abstract

Message Boards Message Boards

Load DICOM with actual data values: Import/Export changes data

POSTED BY: Martijn Froeling
5 Replies
POSTED BY: Rafal Chojna

Awesome! Very helpful information!

I was not aware of the DICOMTools will dig a bit into that.

And indeed the 2005 tag is a vendor-specific one, if i remember correctly all odd first numbers are generally vendor-specific.

Thanks again for the information!

POSTED BY: Martijn Froeling

Hi Martijn,

I'm sorry to hear that you are having a hard time working with DICOM files in the Wolfram Language. As you correctly noticed, Import["f.dcm", "Image"] applies a number of transformations under the hood. We went for this design because otherwise a vast majority of DICOM files would return an all-black image by default, which wouldn't be very useful.

I admit that our documentation for DICOM could be improved to be more helpful for advanced users. The element you are looking for is called "RawPixelData" and for now remains undocumented.

In[41]:= rawData = Import["ExampleData/head.dcm.gz", "RawPixelData"]
Out[41]= NumericArray[Type: UnsignedInteger16 Dimensions: {512, 512}]

In[42]:= MinMax[Normal @ rawData]
Out[42]= {0, 1727}

It returns an array of 16-bit unsigned integers even when the actual bit depth of the values in the file is 12, but the values are not modified in any way.

When you Import the "Data" element, on the other hand, you get the fully processed data which corresponds to the pixel values of the "Image" element:

enter image description here

Now, with "DataTransformation" -> None you can import pixel data without any scaling or other transformations defined in the DICOM file, but it will still map the theoretical range of pixel values to the range of the NumericArray type. For instance, a 12-bit DICOM data will be returned in a NumericArray of type "UnsignedInteger16" (because we don't have a 12-bit wide in the system) and every value will be multiplied by 16 (which maps [0, 2^12) to [0, 2^16)):

In[78]:= dataNoTransform = Import["ExampleData/head.dcm.gz", "Data", "DataTransformation" -> None]
Out[78]= NumericArray[Type: UnsignedInteger16 Dimensions: {512, 512}]

In[79]:= MinMax[Normal @ dataNoTransform]
Out[79]= {0, 27632}

In[80]:= MinMax[Normal @ rawData]
Out[80]= {0, 1727}

In[81]:= Max[dataNoTransform] / Max[rawData]
Out[81]= 16

One last tip: every standard DICOM tag can be imported via the "MetaInformation" element, including pixel data:

In[85]:= pixData = First @ Import["ExampleData/head.dcm.gz", {"MetaInformation", "PixelData"}]
Out[85]= NumericArray[Type: UnsignedInteger16 Dimensions: {512, 512}]

In[86]:= pixData === rawData
Out[86]= True
POSTED BY: Rafal Chojna

Awesome, that was exactly what I was looking for!!!

Thanks for the explanations, always nice to learn a few new things, I was not aware that with {"MetaInformation", "xxx"} you can only import specific tags.

Two additional questions if i may:

  1. Is loading multiple tags in one go possible based on the help of Import this should work right? enter image description here

These examples do not work or am I again missing something.

    Import["data\\dcm\\001_v1\\01901_T1_enhanced_(3x8mm)\\00001.dcm", \
    {"MetaInformation", "2005_100e", "RescaleSlope", "RescaleIntercept"}]
    Import["data\\dcm\\001_v1\\01901_T1_enhanced_(3x8mm)\\00001.dcm", \
    {"dicom", "MetaInformation", "2005_100e", "RescaleSlope", 
      "RescaleIntercept"}]
  1. For known Dicom tags only the Name is exposed, but not the orriginal tag, is this correct? For exmaple Pixel Data has tag (7FE0,0010)

    (*works*)
    Import["data\\dcm\\001_v1\\01901_T1_enhanced_(3x8mm)\\00001.dcm", \
    {"MetaInformation", "PixelData"}]
    (*does not work*)
    Import["data\\dcm\\001_v1\\01901_T1_enhanced_(3x8mm)\\00001.dcm", \
    {"MetaInformation", "7FE0_0010"}]
    

Thanks again for the support!

Best Martijn

PS Dicom support came a long way, I remember using MathVisionTools for Dicom support back in my university days

POSTED BY: Martijn Froeling

I am coming upon this interesting thread years later. I want to comment on the sentence, "We went for this design because otherwise a vast majority of DICOM files would return an all-black image by default, which wouldn't be very useful." I think there's a hidden assumption about to whom the functionality is meant to be useful.

With automatic transformation and glossy images, Import[]'s DICOM handling is useful to non-professionals who want to quickly put an existing DICOM image in a format that is easy to qualitatively analyze. That may be useful to patients who are generating informed questions for their healthcare providers. It is also useful to people who are running demos of Wolfram's functionality to generate sales.

With automatic transformation and glossy images, Import[]'s DICOM handling is NOT useful to healthcare providers, because as the OP mentioned: "...based on what I see actual values of the data are changed by clipping the histogram, which for default handling of medical data is never OK!!" Conventions like this are very serious in medicine because doctors need images free of manipulations that could affect the interpretation of key features of the image. So anyone who wanted to build a medical image processing app in Mathematica that meets government standards would have to show they are explicitly working around this default behavior.

Without automatic transformation, Importing a DICOM indeed gets you mostly-black images initially, but it seems that is what's useful to researchers. The OP was a very polite way of saying that without the ability to extract the raw voxel values, Wolfram's exciting new Import functionality for DICOMs was effectively useless to researchers. And the solution was for researchers to use a then-undocumented "RawPixelData" tag. (There's a single line about it in this article https://reference.wolfram.com/language/ref/format/DICOM.html now... was that there 4 years ago?) But in research, reproducibility is paramount, and reproducibility is curtailed greatly by "black box" functionality in software.

I wonder if sometimes the community would be better served by more candor and clarity about which functionality is meant to be useful to which users. Right now the main documentation page for DICOM reads like it's geared toward people who have never heard of a DICOM image until that day, and it's very important to keep that language in place in order to continue facilitating learning. But the info a researcher needs to do even 1 micro-step of their work ("RawPixelData" --> "DICOM pixel data without scaling") is buried in the Import Elements section, and a person who doesn't read that far is making a rational choice since Wolfram documentation just doesn't always cover the relevant technical information. This post was a demonstration of someone having to figure out for themself what's happening "under the hood" in order to make the functionality useful for their application area.

A fix could possibly look like creating an "Application Areas" section on documentation pages. For the DICOM page (https://reference.wolfram.com/language/ref/format/DICOM.html) that section would be close to the top and it would say something right at the beginning like:

"Import[] by default scales pixel values by clipping the histogram to ensure that the first image generated from the data has visible features. Researchers who want to perform a quantitative analysis must Import the "RawPixelData" element or Import with "DataTransformation" -> None".

Doing this would potentially allow researchers to get to their real work faster, without compromising other people's learning.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard