[Insight-users] z-axis ImagePositionPatient information lost on DICOM series write

Somer, Edward edward.somer at kcl.ac.uk
Mon Aug 8 04:42:00 EDT 2011


Dear All,

I'm trying to write a DICOM series using ImageSeriesWriter. My code is 
based upon the resampleDICOM example but I have a problem with the 
ImagePositionPatient field. The contents of each slice's 
metaDataDictionary are correct when printed to the screen but when I 
save and retrieve the data the z-axis value is zero for all slices. 
Other values, such as slice location are stored correctly.

I hare ITK-3.20.0, GDCM-2.0.14, I build within the Qt development 
environment with min-gw on 64-bit Ubuntu.

I've been chewing it over for a week. Can anybody help?

The offending code is below.

Thanks,

Ed

Typedefs

     typedef signed short int OutputPixelType;
     typedef itk::Image<OutputPixelType, 3> OutputImageType;
     typedef itk::Image<OutputPixelType, 2> OutputImage2DType;
     typedef itk::ShiftScaleImageFilter<ImageType, OutputImageType> 
ShiftScaleFilterType;
     typedef itk::ImageSeriesWriter<OutputImageType, OutputImage2DType> 
WriterType;
     typedef itk::GDCMImageIO ImageIOType;
     typedef itk::MetaDataDictionary   DictionaryType;
     typedef itk::MetaDataObject<std::string> MetaDataStringType;
     typedef itk::NumericSeriesFileNames OutputNamesGeneratorType;

Some stuff to rescale the data and cast it to signed short then...

     OutputNamesGeneratorType::Pointer namesGenerator = 
OutputNamesGeneratorType::New();
     namesGenerator->SetSeriesFormat( format.c_str() );
     namesGenerator->SetStartIndex( 1 );
     namesGenerator->SetEndIndex( matrixSize[2] );
     namesGenerator->SetIncrementIndex( 1 );

     itksys_ios::ostringstream sValue;
     std::string tagkey;
     sValue.str("");

     WriterType::DictionaryArrayType dictArray;

     gdcm::UIDGenerator suid;
     std::string seriesUID = suid.Generate();
     gdcm::UIDGenerator fuid;
     std::string frameOfReferenceUID = fuid.Generate();

     std::string studyUID;
     std::string sopClassUID;
     itk::ExposeMetaData<std::string>(*(gis->metaDataDictionary()), 
"0020|000d", studyUID);
     itk::ExposeMetaData<std::string>(*(gis->metaDataDictionary()), 
"0008|0016", sopClassUID);

     // Create a dictionary for each slice
     for ( unsigned int slice=0; slice<  matrixSize[2]; slice++ ) {

         WriterType::DictionaryRawPointer sliceDict = new 
WriterType::DictionaryType;
         copyDictionary(*(gis->metaDataDictionary()), *sliceDict);

         // Set the UID's for the study, series, SOP  and frame of 
reference
         itk::EncapsulateMetaData<std::string>(*sliceDict,"0020|000d", 
studyUID);
         itk::EncapsulateMetaData<std::string>(*sliceDict,"0020|000e", 
seriesUID);
         itk::EncapsulateMetaData<std::string>(*sliceDict,"0020|0052", 
frameOfReferenceUID);

         gdcm::UIDGenerator sopuid;
         std::string sopInstanceUID = sopuid.Generate();
         itk::EncapsulateMetaData<std::string>(*sliceDict,"0008|0018", 
sopInstanceUID);
         itk::EncapsulateMetaData<std::string>(*sliceDict,"0002|0003", 
sopInstanceUID);

  //       tagkey = "0008|0008"; // Image Type
  //       value = "DERIVED";
  //       itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
value);

  //       tagkey = "0008|0016"; // SOP Class (.2 CT, .7 OT (secondary 
capture), .128 PT Image Storage)
  //       value = "1.2.840.10008.5.1.4.1.1.2";
  //       itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
value);

         tagkey = "0018|0050"; // Slice Thickness
         sValue.str("");
         sValue<<  pixelSize.GetElement(2);
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str());

         sValue.str("");
         tagkey = "0020|0013"; // Image Number
         sValue<<  (slice + 1);
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str() );

         tagkey = "0020|0032"; // Image Position Patient
         ImageType::IndexType index;
         ImageType::PointType position;
         index[0] = 0;
         index[1] = 0;
         index[2] = slice;
         gis->image()->TransformIndexToPhysicalPoint(index, position);
         sValue.str("");
         sValue<<  position[0]<<  "\\"<<  position[1]<<  "\\"<<  
position[2];
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str() );

         sValue.str("");
         tagkey = "0020|1041"; // Slice Location
         sValue<<  position[2];
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str() );

         //std::cerr<<  "Slice: "<<  slice + 1<<  " Image Position: "<<  
position<<  std::endl;

         sValue.str("");
         tagkey = "0028|1052"; // Rescale Intercept
         sValue<<  0;
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str());

         sValue.str("");
         tagkey = "0028|1053"; // Rescale Slope
         //sValue<<  1/dataTypeScale;
         sValue<<  1;
         itk::EncapsulateMetaData<std::string>(*sliceDict, tagkey, 
sValue.str());

         //sliceDict->Print(std::cerr);
         dictArray.push_back(sliceDict);
     }

     WriterType::Pointer writer = WriterType::New();
     writer->SetInput( shiftScaleFilter->GetOutput() );
     writer->SetFileNames( namesGenerator->GetFileNames() );

     ImageIOType::Pointer gdcmIO = ImageIOType::New();
     writer->SetImageIO( gdcmIO );

     writer->SetMetaDataDictionaryArray(&dictArray );

     try {
         writer->Update();
     }
     catch ( itk::ExceptionObject&ex ) {
         statusBar()->showMessage( QString(ex.GetDescription()) );
         return;
     }

     gdcmIO->Print(std::cerr);

After the writer->Update the imageIO and writer looke like this...

GDCMImageIO (0x1cc62a0)
   RTTI typeinfo:   itk::GDCMImageIO
   Reference Count: 1
   Modified Time: 8394
   Debug: Off
   Observers:
     none
   AbortGenerateData: Off
   Progress: 0
   FileName:
   FileType: Binary
   ByteOrder: LittleEndian
   IORegion:
     ImageIORegion (0x1cc6330)
       Dimension: 2
       Index: 0 0
       Size: 0 0
   Number of Components/Pixel: 1
   Pixel Type: scalar
   Component Type: unknown
   Dimensions: ( 0 0 0 )
   Origin: ( 0 0 0 )
   UseCompression: Off
   UseStreamedReading: Off
   UseStreamedWriting: Off
   Internal Component Type: unknown
   RescaleSlope: 1
   RescaleIntercept: 0
   MaxSizeLoadEntry: 4095
   KeepOriginalUID:Off
   UIDPrefix: 1.2.826.0.1.3680043.2.1125.1
   StudyInstanceUID:
   SeriesInstanceUID:
   FrameOfReferenceInstanceUID:
   LoadSequences:1
   LoadPrivateTags:1
   CompressionType:1
   Patient Name:
   Patient ID:
   Patient Sex:
   Patient Age:
   Study ID:
   Patient DOB:
   Study Description:
   Body Part:
   Number Of Series In Study:
   Number Of Study Related Series:
   Study Date:
   Modality:
   Manufacturer:
   Institution Name:
   Model:
   Scan Options:
ImageSeriesWriter (0x1b24240)
   RTTI typeinfo:   itk::ImageSeriesWriter<itk::Image<short, 3u>, 
itk::Image<short, 2u> >
   Reference Count: 1
   Modified Time: 8397
   Debug: Off
   Observers:
     none
   Number Of Required Inputs: 0
   Number Of Required Outputs: 0
   Number Of Threads: 8
WARNING: In 
/usr/local/InsightToolkit-3.20.0/Code/Common/itkProcessObject.cxx, line 518
ImageSeriesWriter (0x1b24240): Output doesn't exist!

   ReleaseDataFlag: Off
   ReleaseDataBeforeUpdateFlag: On
   Input 0: (0x1555020)
   No Output
   AbortGenerateData: Off
   Progress: 1
   Multithreader:
     RTTI typeinfo:   itk::MultiThreader
     Reference Count: 1
     Modified Time: 8380
     Debug: Off
     Observers:
       none
     Thread Count: 8
     Global Maximum Number Of Threads: 128
     Global Default Number Of Threads: 8
   Image IO: GDCMImageIO (0x1a759b0)
   RTTI typeinfo:   itk::GDCMImageIO
   Reference Count: 4
   Modified Time: 14913
   Debug: Off
   Observers:
     none
   AbortGenerateData: Off
   Progress: 0
   FileName: /home/eds/DICOM/image325.dcm
   FileType: Binary
   ByteOrder: LittleEndian
   IORegion:
     ImageIORegion (0x1a75a40)
       Dimension: 2
       Index: 0 0
       Size: 512 512
   Number of Components/Pixel: 1
   Pixel Type: scalar
   Component Type: short
   Dimensions: ( 512 512 )
   Origin: ( -349.316 -508.316 )
   UseCompression: Off
   UseStreamedReading: On
   UseStreamedWriting: Off
   Internal Component Type: unknown
   RescaleSlope: 1
   RescaleIntercept: 0
   MaxSizeLoadEntry: 4095
   KeepOriginalUID:Off
   UIDPrefix: 1.2.826.0.1.3680043.2.1125.1
   StudyInstanceUID: 
1.2.826.0.1.3680043.2.1125.1.51189139806629899025040847923657328
   SeriesInstanceUID: 
1.2.826.0.1.3680043.2.1125.1.59002386129002343896766337658152548
   FrameOfReferenceInstanceUID: 
1.2.826.0.1.3680043.2.1125.1.63454546757695454502945692527374226
   LoadSequences:1
   LoadPrivateTags:1
   CompressionType:1
   Patient Name:ANON218197005250
   Patient ID:ANON218197005250
   Patient Sex:M
   Patient Age:042Y
   Study ID:ANON218197005250
   Patient DOB:
   Study Description:PET-halvkropp
   Body Part:
   Number Of Series In Study:
   Number Of Study Related Series:
   Study Date:20100519
   Modality:CT
   Manufacturer:SIEMENS
   Institution Name:
   Model:HERMES Workstation
   Scan Options:
   StartIndex: 1
   IncrementIndex: 1
   SeriesFormat: %d
   MetaDataDictionaryArray: 0x7ffffd704010
   Compression: Off

-- 
Edward Somer, PhD.
Senior PET Methodologist
The PET Imaging Centre
St Thomas' Hospital
London, UK
SE1 7EH

work tel: +44 (0) 20 7188 1497
work fax: +44 (0) 20 7620 0790
e-mail: Edward.Somer at kcl.ac.uk / Edward.Somer at googlemail.com
  



More information about the Insight-users mailing list