[Insight-users] z-axis ImagePositionPatient information lost on DICOM series write
Alexandre GOUAILLARD
agouaillard at gmail.com
Tue Aug 9 07:23:01 EDT 2011
Dear edward,
this is a known bug you can follow here. It should be addressed within 10 days.
https://itk.icts.uiowa.edu/jira/browse/ITK-182
regards,
alex.
On Mon, Aug 8, 2011 at 10:42 AM, Somer, Edward <edward.somer at kcl.ac.uk> wrote:
> 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
>
> _____________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Kitware offers ITK Training Courses, for more information visit:
> http://www.kitware.com/products/protraining.html
>
> Please keep messages on-topic and check the ITK FAQ at:
> http://www.itk.org/Wiki/ITK_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.itk.org/mailman/listinfo/insight-users
>
More information about the Insight-users
mailing list