ImageSeriesReader for dicom series and PixelIDValue of sitkFloat64

I have a strange question ( it may very well be from my lack of understanding) so thank you in advance
I am using SimpleITK-2.3.0-CSharp-win64-x64 to read and manipulate MR images .

I have an MR series with the following (relevant tags) :
SOP Class UID : 1.2.840.10008.

(0028,0002) Samples Per Pixel 1
(0028,0004) Photometric Interpretation MONOCHROME2
(0028,0010) Rows 704
(0028,0011) Columns 704
(0028,0030) Pixel Spacing 0.56390976905822\0.56390976905822
(0028,0100) Bits Allocated 16
(0028,0101) Bits Stored 12
(0028,0102) High Bit 11
(0028,0103) Pixel Representation 0
(0028,1050) Window Center 759
(0028,1051) Window Width 1320
(0028,1052) Rescale Intercept 0
(0028,1053) Rescale Slope 1.28620268620268
(0028,1054) Rescale Type normalized
(2050,0020) Presentation LUT Shape IDENTITY
(7FE0,0010) Pixel Data 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000…

and executing the following simple code
ImageSeriesReader imSerReader = new ImageSeriesReader();
VectorString dicomNames = ImageSeriesReader.GetGDCMSeriesFileNames(foldername);
MR_im = imSerReader.Execute();

My question is why does ImageSeriesReader assing a PixelDValue of 9 (sitkFloat64) to the resulting sITKImage ?

As far as I can ascertain bitsallocated in the dicom are 16 and pixelrepresentation is usigned int16.
Under normal circumstances I would not care all too much from the increased “precision” however when trying to recreate the dicom using fo-dicom and populating pixeldata adding a memorybytebuffer containing doubles results in dicom images not being read by any dicom reader

Any help or explanation would be greatly appreciated

Again thank you very much

Hello @Ervis,

The reason the pixel type is sitkFloat64 is because the actual intensity values depend on the bits allocated, bits used and additional information. The storage on disk, allocated and used, is combined with the values of the rescale slope and rescale intercept tags to obtain the actual intensity value. As the rescale slope in the image has a value of 1.286… the result is that the intensities are of type float64. For the detailed explanation see this kitware blog post. DICOM is a complex format, even things you think are trivial may not be so.

Note that Rescale Slope and Intercept are NOT expected to be present in MR images (unlike, say CT images, in which they are required), and are NOT expected to be applied before window values (for example) (even if you are not using them) and hence their presence cannot be considered a valid standard extended SOP class usage, so “cooking” these into the converted pixel values is a poor design IMHO (though it may be convenient for CT images), and should be left to the caller of the API to control, and perhaps an integer rather than float pixel data type should be returned by default. The presence of the rescale attributes in images is a long running controversy between one of the major MR vendors (which allows the scanners to be configured to insert these rescale values) and everyone else. PET is problematic too, as Matt mentions, and thought the rescale attributes are required by the standard for PET (just like CT), they are not expected (by convention, not standardization) to be applied before using the window values, so you may or may not want the rescale conversion to be applied for them either. FYI, that’s why in newer DICOM standard objects we separated the real-world value (rescaling) pipeline from the rendering (windowing) pipeline.

Thank you vey much @zivy and @dclunie for the explanation much appreciated, thank you.

So if I understood everything correctly (in my case) given a random pixel value of unsigned int16 (bitsallocated) of 10 the formula U = m*SV + b is applied ,using U=1.286 *10 + 0 resulting in an type float value.

If it is ok I would like to ask another follow-up question, now that I have an image buffer of foat64s, once I am done doing whatever I am doing in SITK to the image, and want to place this buffer back into a dicom file (for other reasons i have to use fo-dicom library for that) is there a method / mechanism or helper classes that would allow me to convert this float64 buffer (sitkImage) to uint16 without loosing accuracy ( with the assumption that the rescale intercept , slope, window values will also be placed in the resulting dicom file) ? I have seen tutorial examples online of using :
// Cast so we know the the pixel type
input = SimpleITK.Cast(input, PixelId.sitkFloat32);

I am unsure ( I am not familiar with the implementation of the Cast method) if there will be loss of accuracy?
Reason I am asking is because we do texture analysis on these images and it is paramount that I do maintain the accuracy of the original dataset.
I suppose I would always go and loop value by value on the image buffer , reverse the U = m*SV + b , and should in theory end up with uint16, but I am hoping someone may know a better way less error prone that would would speedup and allow for this process to be accurate

Again thank you very much for all your help

Hello @Ervis,

The cast filter will result in loss of accuracy if you are indeed working with float values (unless your floats are actually integer values stored in memory as float).

This SimpleITK example shows how to use the rescale slope and intercept values to save floating values, should work for what you are describing.

Note @dclunie’s comments on this usage being problematic in terms of the DICOM standard as specified for MR.