From acd847ca23ec3c1213e9e97043d4f99445a25b6c Mon Sep 17 00:00:00 2001 From: srit Date: Wed, 8 Sep 2010 09:56:02 +0000 Subject: [PATCH] Converted plastimatch dicom RT dose reader in ITK IO format. --- common/CMakeLists.txt | 2 + common/clitkDicomRTDoseIO.cxx | 246 +++++++++++++++++++++++++++ common/clitkDicomRTDoseIO.h | 82 +++++++++ common/clitkDicomRTDoseIOFactory.cxx | 35 ++++ common/clitkDicomRTDoseIOFactory.h | 75 ++++++++ 5 files changed, 440 insertions(+) create mode 100644 common/clitkDicomRTDoseIO.cxx create mode 100644 common/clitkDicomRTDoseIO.h create mode 100644 common/clitkDicomRTDoseIOFactory.cxx create mode 100644 common/clitkDicomRTDoseIOFactory.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 74a5786..76e9179 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -24,6 +24,8 @@ SET(clitkCommon_SRC clitkXdrImageIOFactory.cxx clitkHndImageIO.cxx clitkHndImageIOFactory.cxx + clitkDicomRTDoseIO.cxx + clitkDicomRTDoseIOFactory.cxx clitkOrientation.cxx vvImage.cxx clitkImageToImageGenericFilterBase.cxx diff --git a/common/clitkDicomRTDoseIO.cxx b/common/clitkDicomRTDoseIO.cxx new file mode 100644 index 0000000..6e3eba0 --- /dev/null +++ b/common/clitkDicomRTDoseIO.cxx @@ -0,0 +1,246 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +======================================================================-====*/ + +// clitk include +#include "clitkDicomRTDoseIO.h" +#include "clitkCommon.h" + +// itk include +#include + +#define GFOV_SPACING_TOL (1e-1) + +//-------------------------------------------------------------------- +// Read Image Information +void clitk::DicomRTDoseIO::ReadImageInformation() +{ + if(m_GdcmFile) + delete m_GdcmFile; + m_GdcmFile = new gdcm::File; + + int i, rc; + std::string tmp; + float ipp[3]; + int dim[3]; + float spacing[3]; + float *gfov; /* gfov = GridFrameOffsetVector */ + int gfov_len; + const char *gfov_str; + + m_GdcmFile->SetMaxSizeLoadEntry (0xffff); + m_GdcmFile->SetFileName (m_FileName.c_str()); + m_GdcmFile->SetLoadMode (0); + m_GdcmFile->Load(); + + /* Modality -- better be RTSTRUCT */ + tmp = m_GdcmFile->GetEntryValue (0x0008, 0x0060); + if (strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) { + itkExceptionMacro(<< "Error. Input file not RTDOSE: " << m_FileName); + } + + /* ImagePositionPatient */ + tmp = m_GdcmFile->GetEntryValue (0x0020, 0x0032); + rc = sscanf (tmp.c_str(), "%f\\%f\\%f", &ipp[0], &ipp[1], &ipp[2]); + if (rc != 3) { + itkExceptionMacro(<< "Error parsing RTDOSE ipp."); + } + + /* Rows */ + tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0010); + rc = sscanf (tmp.c_str(), "%d", &dim[1]); + if (rc != 1) { + itkExceptionMacro(<< "Error parsing RTDOSE rows."); + } + + /* Columns */ + tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0011); + rc = sscanf (tmp.c_str(), "%d", &dim[0]); + if (rc != 1) { + itkExceptionMacro(<< "Error parsing RTDOSE columns."); + } + + /* PixelSpacing */ + tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0030); + rc = sscanf (tmp.c_str(), "%g\\%g", &spacing[0], &spacing[1]); + + if (rc != 2) { + itkExceptionMacro(<< "Error parsing RTDOSE pixel spacing."); + } + + /* GridFrameOffsetVector */ + tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000C); + gfov = 0; + gfov_len = 0; + gfov_str = tmp.c_str(); + while (1) { + int len; + gfov = (float*) realloc (gfov, (gfov_len + 1) * sizeof(float)); + rc = sscanf (gfov_str, "%g%n", &gfov[gfov_len], &len); + if (rc != 1) { + break; + } + gfov_len ++; + gfov_str += len; + if (gfov_str[0] == '\\') { + gfov_str ++; + } + } + dim[2] = gfov_len; + if (gfov_len == 0) { + itkExceptionMacro(<< "Error parsing RTDOSE gfov."); + } + + /* --- Analyze GridFrameOffsetVector --- */ + + /* (1) Make sure first element is 0. */ + if (gfov[0] != 0.) { + itkExceptionMacro(<< "Error RTDOSE gfov[0] is not 0."); + } + + /* (2) Handle case where gfov_len == 1 (only one slice). */ + if (gfov_len == 1) { + spacing[2] = spacing[0]; + } + + /* (3) Check to make sure spacing is regular. */ + for (i = 1; i < gfov_len; i++) { + if (i == 1) { + spacing[2] = gfov[1] - gfov[0]; + } else { + float sp = gfov[i] - gfov[i-1]; + if (fabs(sp - spacing[2]) > GFOV_SPACING_TOL) { + itkExceptionMacro(<< "Error RTDOSE grid has irregular spacing:" + << sp << " vs " << spacing[2]); + } + } + } + + free (gfov); + + /* DoseGridScaling */ + m_DoseScaling = 1.0; + tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000E); + rc = sscanf (tmp.c_str(), "%f", &m_DoseScaling); + /* If element doesn't exist, scaling is 1.0 */ + + // set dimension values + SetNumberOfDimensions(3); + for(int i=0; i<3; i++) { + SetDimensions(i, dim[i]); + SetSpacing(i, spacing[i]); + SetOrigin(i, ipp[i]); + } + + // set other information + SetByteOrderToLittleEndian(); + SetPixelType(itk::ImageIOBase::SCALAR); + SetNumberOfComponents(1); + SetComponentType(itk::ImageIOBase::FLOAT); +} + +//-------------------------------------------------------------------- +// Read Image Information +bool clitk::DicomRTDoseIO::CanReadFile(const char* FileNameToRead) +{ + // opening dicom input file + gdcm::File dcmFile; + dcmFile.SetFileName(FileNameToRead); + if (!dcmFile.OpenFile()) + return false; + + //Taken from plastimatch + dcmFile.SetMaxSizeLoadEntry (0xffff); + dcmFile.SetLoadMode (0); + dcmFile.Load(); + + /* Modality -- better be RTDOSE */ + std::string tmp = dcmFile.GetEntryValue (0x0008, 0x0060); + if (!strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) { + return true; + } + + return false; +} + +//-------------------------------------------------------------------- +template +void +clitk::DicomRTDoseIO::dose_copy_raw (float *img_out, T *img_in, int nvox, float scale) +{ + for (int i = 0; i < nvox; i++) { + img_out[i] = img_in[i] * scale; + } +} + +//-------------------------------------------------------------------- +// Read Image Content +void clitk::DicomRTDoseIO::Read(void * buffer) +{ + float *img = (float*) buffer; + + unsigned long npix = 1; + for(unsigned int i=0; iGetPixelType().c_str(), "16U")==0) { + unsigned short* image_data = (unsigned short*) m_GdcmFile_helper.GetImageData(); + dose_copy_raw (img, image_data, npix, m_DoseScaling); + } else if (strcmp(m_GdcmFile->GetPixelType().c_str(),"32U")==0) { + unsigned long* image_data = (unsigned long*) m_GdcmFile_helper.GetImageData (); + dose_copy_raw (img, image_data, npix, m_DoseScaling); + } else { + itkExceptionMacro(<< "Error RTDOSE not type 16U and 32U (type=" + << m_GdcmFile->GetPixelType().c_str() << ")"); + } + + /* GCS FIX: Do I need to do something about endian-ness? */ + + + + /* Copy data to volume */ +// float *img = (float*) vol->img; +// for (i = 0; i < vol->npix; i++) { + //img[i] = image_data[i] * m_DoseScaling; +// } + + delete m_GdcmFile; +} + +//-------------------------------------------------------------------- +// Write Image Information +void clitk::DicomRTDoseIO::WriteImageInformation(bool keepOfStream) +{ +} + +//-------------------------------------------------------------------- +// Write Image Information +bool clitk::DicomRTDoseIO::CanWriteFile(const char* FileNameToWrite) +{ + return false; +} + +//-------------------------------------------------------------------- +// Write Image +void clitk::DicomRTDoseIO::Write(const void * buffer) +{ +} + diff --git a/common/clitkDicomRTDoseIO.h b/common/clitkDicomRTDoseIO.h new file mode 100644 index 0000000..b5679aa --- /dev/null +++ b/common/clitkDicomRTDoseIO.h @@ -0,0 +1,82 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +======================================================================-====*/ +#ifndef clitkDicomRTDoseIO_h +#define clitkDicomRTDoseIO_h + +// clitk include +#include "clitkCommon.h" + +// itk include +#include +#include + +// std include +#include + +namespace clitk +{ + +//==================================================================== +// Class for reading Vox Image file format +class DicomRTDoseIO: public itk::ImageIOBase +{ +public: + /** Standard class typedefs. */ + typedef DicomRTDoseIO Self; + typedef itk::ImageIOBase Superclass; + typedef itk::SmartPointer Pointer; + typedef signed short int PixelType; + + DicomRTDoseIO():Superclass() { + mustWriteHeader = false; + m_GdcmFile=NULL; + } + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(DicomRTDoseIO, ImageIOBase); + + /*-------- This part of the interface deals with reading data. ------ */ + virtual void ReadImageInformation(); + virtual bool CanReadFile( const char* FileNameToRead ); + virtual void Read(void * buffer); + + /*-------- This part of the interfaces deals with writing data. ----- */ + virtual void WriteImageInformation(bool keepOfStream); + virtual void WriteImageInformation() { + WriteImageInformation(false); + } + virtual bool CanWriteFile(const char* filename); + virtual void Write(const void* buffer); + +protected: + template void dose_copy_raw (float *img_out, T *img_in, int nvox, float scale); + + bool mustWriteHeader; + int m_HeaderSize; + std::ofstream file; + gdcm::File *m_GdcmFile; + float m_DoseScaling; +}; // end class DicomRTDoseIO + +} // end namespace + +#endif /* end #define clitkDicomRTDoseIO_h */ + diff --git a/common/clitkDicomRTDoseIOFactory.cxx b/common/clitkDicomRTDoseIOFactory.cxx new file mode 100644 index 0000000..42e963a --- /dev/null +++ b/common/clitkDicomRTDoseIOFactory.cxx @@ -0,0 +1,35 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +======================================================================-====*/ +#ifndef clitkDicomRTDoseIOFactory_cxx +#define clitkDicomRTDoseIOFactory_cxx + +#include "clitkDicomRTDoseIOFactory.h" + +//==================================================================== +clitk::DicomRTDoseIOFactory::DicomRTDoseIOFactory() +{ + this->RegisterOverride("itkImageIOBase", + "DicomRTDoseIO", + "Dicom RT dose IO", + 1, + itk::CreateObjectFunction::New()); +} + + +#endif /* end #define clitkDicomRTDoseIOFactory_cxx */ + diff --git a/common/clitkDicomRTDoseIOFactory.h b/common/clitkDicomRTDoseIOFactory.h new file mode 100644 index 0000000..93f3da1 --- /dev/null +++ b/common/clitkDicomRTDoseIOFactory.h @@ -0,0 +1,75 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +======================================================================-====*/ +#ifndef clitkDicomRTDoseIOFactory_h +#define clitkDicomRTDoseIOFactory_h + +// clitk include +#include "clitkDicomRTDoseIO.h" + +// itk include +#include "itkImageIOBase.h" +#include "itkObjectFactoryBase.h" +#include "itkVersion.h" + +namespace clitk +{ + +//==================================================================== +// Factory for reading Dicom RT Dose file +class DicomRTDoseIOFactory: public itk::ObjectFactoryBase +{ +public: + /** Standard class typedefs. */ + typedef DicomRTDoseIOFactory Self; + typedef itk::ObjectFactoryBase Superclass; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + + /** Class methods used to interface with the registered factories. */ + const char* GetITKSourceVersion(void) const { + return ITK_SOURCE_VERSION; + } + + const char* GetDescription(void) const { + return "Dicom RT Dose IO factory"; + } + + /** Method for class instantiation. */ + itkFactorylessNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(DicomRTDoseIOFactory, ObjectFactoryBase); + + /** Register one factory of this type */ + static void RegisterOneFactory(void) { + ObjectFactoryBase::RegisterFactory( Self::New() ); + } + +protected: + DicomRTDoseIOFactory(); + ~DicomRTDoseIOFactory() {}; + +private: + DicomRTDoseIOFactory(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +} // end namespace + +#endif /* end #define clitkDicomRTDoseIOFactory_h */ + -- 2.45.1