Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ENH: Add ITKv4 PETStandardUptakeValueComputation

Extracting DICOM header values needed updating
for compatibility with API in ITKv4

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21442 3bd1e089-480b-0410-8dfb-8563597acbee
  • Loading branch information...
commit 1ab763f08ef34c4d42010925fd70cbd4ed06dbf2 1 parent b9d4f46
hjohnson authored
View
10 Modules/CLI/CMakeLists.txt
@@ -49,9 +49,8 @@ set(cli_modules
)
if(Slicer_BUILD_DICOM_SUPPORT)
- list(APPEND cli_modules
- CreateDICOMSeries
- )
+ list(APPEND cli_modules CreateDICOMSeries)
+ list(APPEND cli_modules PETStandardUptakeValueComputation)
endif()
if(Slicer_BUILD_LEGACY_CLI)
@@ -83,7 +82,6 @@ endif()
if("${ITK_VERSION_MAJOR}" LESS 4)
if(Slicer_BUILD_DICOM_SUPPORT)
list(APPEND cli_modules DicomToNrrdConverter)
- list(APPEND cli_modules PETStandardUptakeValueComputation)
endif()
endif()
@@ -170,3 +168,7 @@ if(Slicer_BUILD_BRAINSTOOLS)
)
endif()
+if(Slicer_BUILD_DWIConvert)
+ message("DCMTK_DIR = ${DCMTK_DIR}")
+ add_subdirectory(${DWIConvert_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/DWIConvert)
+endif()
View
6 Modules/CLI/PETStandardUptakeValueComputation/CMakeLists.txt
@@ -1,3 +1,4 @@
+find_package(DCMTK REQUIRED)
#-----------------------------------------------------------------------------
set(MODULE_NAME PETStandardUptakeValueComputation) # Do not use 'project()'
@@ -5,9 +6,12 @@ set(MODULE_NAME PETStandardUptakeValueComputation) # Do not use 'project()'
#-----------------------------------------------------------------------------
SEMMacroBuildCLI(
NAME ${MODULE_NAME}
+ ADDITIONAL_SRCS itkDCMTKFileReader.cxx
LOGO_HEADER ${Slicer_SOURCE_DIR}/Resources/NAMICLogo.h
# LOGO_HEADER ${Slicer_SOURCE_DIR}/Resources/CTSCLogo.h
- TARGET_LIBRARIES vtkITK ModuleDescriptionParser MRMLCore SlicerBaseLogic SlicerBaseCLI ITKIO
+ TARGET_LIBRARIES vtkITK ModuleDescriptionParser
+ MRMLCore SlicerBaseLogic SlicerBaseCLI ${ITK_LIBRARIES}
+ ${DCMTK_LIBRARIES}
INCLUDE_DIRECTORIES
${vtkITK_INCLUDE_DIRS}
${MRMLCore_INCLUDE_DIRS}
View
700 Modules/CLI/PETStandardUptakeValueComputation/PETStandardUptakeValueComputation.cxx
@@ -24,16 +24,9 @@
#include <itkImageSeriesReader.h>
#include <itkMetaDataDictionary.h>
#include <itkNumericSeriesFileNames.h>
-#include <itkOrientedImage.h>
-// GDCM includes
-#include <gdcmBinEntry.h>
-#include <gdcmFile.h>
-#include <gdcmGlobal.h>
-#include <gdcmSeqEntry.h>
-#include <gdcmSQItem.h>
-#include <gdcmUtil.h>
-#include <gdcmValEntry.h>
+#undef HAVE_SSTREAM // stupid DCMTK Header issue
+#include "itkDCMTKFileReader.h"
// ...
// ...............................................................................................
@@ -806,7 +799,7 @@ int LoadImagesAndComputeSUV( parameters & list, T )
voifile = fopen(list.VOIVolumeName.c_str(), "r");
if( voifile == NULL )
{
- std::cerr << "ERROR: cannot open input volume file '" << list.VOIVolumeName.c_str() << "'" << endl;
+ std::cerr << "ERROR: cannot open ROI Volume file '" << list.VOIVolumeName.c_str() << "'" << endl;
return EXIT_FAILURE;
}
fclose(voifile);
@@ -862,9 +855,9 @@ int LoadImagesAndComputeSUV( parameters & list, T )
// read the DICOM dir to get the radiological data
typedef short PixelValueType;
- typedef itk::OrientedImage< PixelValueType, 3 > VolumeType;
+ typedef itk::Image< PixelValueType, 3 > VolumeType;
typedef itk::ImageSeriesReader< VolumeType > VolumeReaderType;
- typedef itk::OrientedImage< PixelValueType, 2 > SliceType;
+ typedef itk::Image< PixelValueType, 2 > SliceType;
typedef itk::ImageFileReader< SliceType > SliceReaderType;
typedef itk::GDCMImageIO ImageIOType;
typedef itk::GDCMSeriesFileNames InputNamesGeneratorType;
@@ -927,437 +920,398 @@ int LoadImagesAndComputeSUV( parameters & list, T )
0018,1076 Radionuclide Positron Fraction: 0
*/
int parsingDICOM = 0;
- gdcm::File *f = new gdcm::File();
- if ( f != NULL )
- {
- const char *fn = filenames[0].c_str();
- f->SetFileName( fn );
- //bool res = f->Load(); // FIXME: commented out for now to avoid compile warnings
- f->Load(); // FIXME: handle res
-
- gdcm::SeqEntry *seq = f->GetSeqEntry(0x0054,0x0016);
- if ( seq != NULL )
- {
- parsingDICOM = 1;
- gdcm::SQItem *sqItem = seq->GetFirstSQItem();
- while ( sqItem )
+ itk::DCMTKFileReader fileReader;
+ fileReader.SetFileName(filenames[0]);
+ fileReader.LoadFile();
+
+ itk::DCMTKSequence seq;
+ if(fileReader.GetElementSQ(0x0054,0x0016,seq,false) == EXIT_SUCCESS)
+ {
+ parsingDICOM = 1;
+// for(int i = 0; i < seq.card(); ++i)
+// {
+// itk::DCMTKSequence sqItem;
+// seq.GetSequence(i,sqItem);
+ //---
+ //--- Radiopharmaceutical Start Time
+// sqItem.GetElementTM(0x0018,0x1072,tag);
+ seq.GetElementTM(0x0018,0x1072,tag);
+ //--- expect A string of characters of the format hhmmss.frac;
+ //---where hh contains hours (range "00" - "23"), mm contains minutes
+ //---(range "00" - "59"), ss contains seconds (range "00" - "59"), and frac
+ //---contains a fractional part of a second as small as 1 millionth of a
+ //---second (range "000000" - "999999"). A 24 hour clock is assumed.
+ //---Midnight can be represented by only "0000" since "2400" would
+ //---violate the hour range. The string may be padded with trailing
+ //---spaces. Leading and embedded spaces are not allowed. One
+ //---or more of the components mm, ss, or frac may be unspecified
+ //---as long as every component to the right of an unspecified
+ //---component is also unspecified. If frac is unspecified the preceding "."
+ //---may not be included. Frac shall be held to six decimal places or
+ //---less to ensure its format conforms to the ANSI
+ //---Examples -
+ //---1. "070907.0705" represents a time of 7 hours, 9 minutes and 7.0705 seconds.
+ //---2. "1010" represents a time of 10 hours, and 10 minutes.
+ //---3. "021" is an invalid value.
+ if ( tag.c_str() == NULL || *(tag.c_str()) == '\0' )
{
- //---
- //--- Radiopharmaceutical Start Time
- tag.clear();
- tag = sqItem->GetEntryValue(0x0018,0x1072);
- //--- expect A string of characters of the format hhmmss.frac;
- //---where hh contains hours (range "00" - "23"), mm contains minutes
- //---(range "00" - "59"), ss contains seconds (range "00" - "59"), and frac
- //---contains a fractional part of a second as small as 1 millionth of a
- //---second (range "000000" - "999999"). A 24 hour clock is assumed.
- //---Midnight can be represented by only "0000" since "2400" would
- //---violate the hour range. The string may be padded with trailing
- //---spaces. Leading and embedded spaces are not allowed. One
- //---or more of the components mm, ss, or frac may be unspecified
- //---as long as every component to the right of an unspecified
- //---component is also unspecified. If frac is unspecified the preceding "."
- //---may not be included. Frac shall be held to six decimal places or
- //---less to ensure its format conforms to the ANSI
- //---Examples -
- //---1. "070907.0705" represents a time of 7 hours, 9 minutes and 7.0705 seconds.
- //---2. "1010" represents a time of 10 hours, and 10 minutes.
- //---3. "021" is an invalid value.
- if ( tag.c_str() == NULL || *(tag.c_str()) == '\0' )
+ list.injectionTime = "MODULE_INIT_NO_VALUE" ;
+ }
+ else
+ {
+ len = tag.length();
+ hourstr.clear();
+ minutestr.clear();
+ secondstr.clear();
+ if ( len >= 2 )
{
- list.injectionTime = "MODULE_INIT_NO_VALUE" ;
+ hourstr = tag.substr(0, 2);
}
else
{
- len = tag.length();
- hourstr.clear();
- minutestr.clear();
- secondstr.clear();
- if ( len >= 2 )
- {
- hourstr = tag.substr(0, 2);
- }
- else
- {
- hourstr = "00";
- }
- if ( len >= 4 )
- {
- minutestr = tag.substr(2, 2);
- }
- else
- {
- minutestr = "00";
- }
- if ( len >= 6 )
- {
- secondstr = tag.substr(4);
- }
- else
- {
- secondstr = "00";
- }
- tag.clear();
- tag = hourstr.c_str();
- tag += ":";
- tag += minutestr.c_str();
- tag += ":";
- tag += secondstr.c_str();
- list.injectionTime = tag.c_str();
+ hourstr = "00";
}
-
- //---
- //--- Radionuclide Total Dose
- tag.clear();
- tag = sqItem->GetEntryValue(0x0018,0x1074);
- if ( tag.c_str() == NULL || *(tag.c_str()) == '\0' )
+ if ( len >= 4 )
{
- list.injectedDose = 0.0;
+ minutestr = tag.substr(2, 2);
}
else
{
- list.injectedDose = atof ( tag.c_str() ) ;
+ minutestr = "00";
}
-
-
- //---
- //--- RadionuclideHalfLife
- tag.clear();
- tag = sqItem->GetEntryValue(0x0018,0x1075);
- //--- Expect a Decimal String
- //--- A string of characters representing either
- //--- a fixed point number or a floating point number.
- //--- A fixed point number shall contain only the characters 0-9
- //--- with an optional leading "+" or "-" and an optional "." to mark
- //--- the decimal point. A floating point number shall be conveyed
- //--- as defined in ANSI X3.9, with an "E" or "e" to indicate the start
- //--- of the exponent. Decimal Strings may be padded with leading
- //--- or trailing spaces. Embedded spaces are not allowed.
- if ( tag.c_str() == NULL || *(tag.c_str()) == '\0' )
+ if ( len >= 6 )
{
- list.radionuclideHalfLife = "MODULE_INIT_NO_VALUE" ;
+ secondstr = tag.substr(4);
}
else
{
- list.radionuclideHalfLife = tag.c_str() ;
+ secondstr = "00";
}
-
- //---
- //---Radionuclide Positron Fraction
tag.clear();
- tag = sqItem->GetEntryValue(0x0018,0x1076);
- //--- not currently using this one?
+ tag = hourstr.c_str();
+ tag += ":";
+ tag += minutestr.c_str();
+ tag += ":";
+ tag += secondstr.c_str();
+ list.injectionTime = tag.c_str();
+ }
- sqItem = seq->GetNextSQItem();
+ //---
+ //--- Radionuclide Total Dose
+// if(sqItem.GetElementDS(0x0018,0x1074,1,&list.injectedDose,false) != EXIT_SUCCESS)
+ if(seq.GetElementDS(0x0018,0x1074,1,&list.injectedDose,false) != EXIT_SUCCESS)
+ {
+ list.injectedDose = 0.0;
}
- //--
- //--- UNITS: something like BQML:
- //--- CNTS, NONE, CM2, PCNT, CPS, BQML,
- //--- MGMINML, UMOLMINML, MLMING, MLG,
- //--- 1CM, UMOLML, PROPCNTS, PROPCPS,
- //--- MLMINML, MLML, GML, STDDEV
//---
- tag.clear();
- tag = f->GetEntryValue (0x0054,0x1001);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ //--- RadionuclideHalfLife
+ //--- Expect a Decimal String
+ //--- A string of characters representing either
+ //--- a fixed point number or a floating point number.
+ //--- A fixed point number shall contain only the characters 0-9
+ //--- with an optional leading "+" or "-" and an optional "." to mark
+ //--- the decimal point. A floating point number shall be conveyed
+ //--- as defined in ANSI X3.9, with an "E" or "e" to indicate the start
+ //--- of the exponent. Decimal Strings may be padded with leading
+ //--- or trailing spaces. Embedded spaces are not allowed.
+// if(sqItem.GetElementCS(0x0018,0x1075,list.radionuclideHalfLife,false) != EXIT_SUCCESS)
+ if(seq.GetElementDS(0x0018,0x1075,list.radionuclideHalfLife,false) != EXIT_SUCCESS)
{
- //--- I think these are piled together. MBq ml... search for all.
- std::string units = tag.c_str();
- if ( ( units.find ("BQML") != std::string::npos) ||
- ( units.find ("BQML") != std::string::npos) )
- {
- list.radioactivityUnits= "Bq";
- list.tissueRadioactivityUnits = "Bq";
- }
- else if ( ( units.find ("MBq") != std::string::npos) ||
- ( units.find ("MBQ") != std::string::npos) )
- {
- list.radioactivityUnits = "MBq";
- list.tissueRadioactivityUnits = "MBq";
- }
- else if ( (units.find ("kBq") != std::string::npos) ||
- (units.find ("kBQ") != std::string::npos) ||
- (units.find ("KBQ") != std::string::npos) )
- {
- list.radioactivityUnits = "kBq";
- list.tissueRadioactivityUnits = "kBq";
- }
- else if ( (units.find ("mBq") != std::string::npos) ||
- (units.find ("mBQ") != std::string::npos) )
- {
- list.radioactivityUnits = "mBq";
- list.tissueRadioactivityUnits = "mBq";
- }
- else if ( (units.find ("uBq") != std::string::npos) ||
- (units.find ("uBQ") != std::string::npos) )
- {
- list.radioactivityUnits = "uBq";
- list.tissueRadioactivityUnits = "uBq";
- }
- else if ( (units.find ("Bq") != std::string::npos) ||
- (units.find ("BQ") != std::string::npos) )
- {
- list.radioactivityUnits = "Bq";
- list.tissueRadioactivityUnits = "Bq";
- }
- else if ( (units.find ("MCi") != std::string::npos) ||
- ( units.find ("MCI") != std::string::npos) )
- {
- list.radioactivityUnits = "MCi";
- list.tissueRadioactivityUnits = "MCi";
- }
- else if ( (units.find ("kCi") != std::string::npos) ||
- (units.find ("kCI") != std::string::npos) ||
- (units.find ("KCI") != std::string::npos) )
- {
- list.radioactivityUnits = "kCi";
- list.tissueRadioactivityUnits = "kCi";
- }
- else if ( (units.find ("mCi") != std::string::npos) ||
- (units.find ("mCI") != std::string::npos) )
- {
- list.radioactivityUnits = "mCi";
- list.tissueRadioactivityUnits = "mCi";
- }
- else if ( (units.find ("uCi") != std::string::npos) ||
- (units.find ("uCI") != std::string::npos) )
- {
- list.radioactivityUnits = "uCi";
- list.tissueRadioactivityUnits = "uCi";
- }
- else if ( (units.find ("Ci") != std::string::npos) ||
- (units.find ("CI") != std::string::npos) )
- {
- list.radioactivityUnits = "Ci";
- list.tissueRadioactivityUnits = "Ci";
- }
- list.volumeUnits = "ml";
+ list.radionuclideHalfLife = "MODULE_INIT_NO_VALUE";
}
- else
+ //---
+ //---Radionuclide Positron Fraction
+ //--- not currently using this one?
+ std::string radioNuclidePositronFraction;
+// if(sqItem.GetElementCS(0x0018,0x1075,radioNuclidePositronFraction,false) != EXIT_SUCCESS)
+ if(seq.GetElementDS(0x0018,0x1075,radioNuclidePositronFraction,false) != EXIT_SUCCESS)
{
- //--- default values.
- list.radioactivityUnits = "MBq";
- list.tissueRadioactivityUnits = "MBq";
- list.volumeUnits = "ml";
+ radioNuclidePositronFraction = "MODULE_INIT_NO_VALUE";
}
+// }
+ //--
+ //--- UNITS: something like BQML:
+ //--- CNTS, NONE, CM2, PCNT, CPS, BQML,
+ //--- MGMINML, UMOLMINML, MLMING, MLG,
+ //--- 1CM, UMOLML, PROPCNTS, PROPCPS,
+ //--- MLMINML, MLML, GML, STDDEV
+ //---
- //---
- //--- DecayCorrection
- //--- Possible values are:
- //--- NONE = no decay correction
- //--- START= acquisition start time
- //--- ADMIN = radiopharmaceutical administration time
- //--- Frame Reference Time is the time that the pixel values in the Image occurred.
- //--- It's defined as the time offset, in msec, from the Series Reference Time.
- //--- Series Reference Time is defined by the combination of:
- //--- Series Date (0008,0021) and
- //--- Series Time (0008,0031).
- //--- We don't pull these out now, but can if we have to.
- tag.clear();
- tag = f->GetEntryValue (0x0054,0x1102);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ if(fileReader.GetElementCS(0x0054,0x1001,tag,false) == EXIT_SUCCESS)
+ {
+ //--- I think these are piled together. MBq ml... search for all.
+ std::string units = tag.c_str();
+ if ( ( units.find ("BQML") != std::string::npos) ||
+ ( units.find ("BQML") != std::string::npos) )
{
- //---A string of characters with leading or trailing spaces (20H) being non-significant.
- list.decayCorrection = tag.c_str();
+ list.radioactivityUnits= "Bq";
+ list.tissueRadioactivityUnits = "Bq";
}
- else
+ else if ( ( units.find ("MBq") != std::string::npos) ||
+ ( units.find ("MBQ") != std::string::npos) )
{
- list.decayCorrection = "MODULE_INIT_NO_VALUE";
+ list.radioactivityUnits = "MBq";
+ list.tissueRadioactivityUnits = "MBq";
}
-
- //---
- //--- StudyDate
-// this->ClearStudyDate();
- tag.clear();
- tag = f->GetEntryValue (0x0008,0x0021);
- if ( tag.c_str() != NULL && strcmp (tag.c_str(), "" ) )
+ else if ( (units.find ("kBq") != std::string::npos) ||
+ (units.find ("kBQ") != std::string::npos) ||
+ (units.find ("KBQ") != std::string::npos) )
{
- //--- YYYYMMDD
- yearstr.clear();
- daystr.clear();
- monthstr.clear();
- len = tag.length();
- if ( len >= 4 )
- {
- yearstr = tag.substr(0, 4);
- // this->Year = atoi(yearstr.c_str() );
- }
- else
- {
- yearstr = "????";
- // this->Year = 0;
- }
- if ( len >= 6 )
- {
- monthstr = tag.substr(4, 2);
- // this->Month = atoi ( monthstr.c_str() );
- }
- else
- {
- monthstr = "??";
- // this->Month = 0;
- }
- if ( len >= 8 )
- {
- daystr = tag.substr (6, 2);
-// this->Day = atoi ( daystr.c_str() );
- }
- else
- {
- daystr = "??";
-// this->Day = 0;
- }
- tag.clear();
- tag = yearstr.c_str();
- tag += "/";
- tag += monthstr.c_str();
- tag += "/";
- tag += daystr.c_str();
- list.studyDate = tag.c_str();
+ list.radioactivityUnits = "kBq";
+ list.tissueRadioactivityUnits = "kBq";
}
- else
+ else if ( (units.find ("mBq") != std::string::npos) ||
+ (units.find ("mBQ") != std::string::npos) )
+ {
+ list.radioactivityUnits = "mBq";
+ list.tissueRadioactivityUnits = "mBq";
+ }
+ else if ( (units.find ("uBq") != std::string::npos) ||
+ (units.find ("uBQ") != std::string::npos) )
{
- list.studyDate = "MODULE_INIT_NO_VALUE";
+ list.radioactivityUnits = "uBq";
+ list.tissueRadioactivityUnits = "uBq";
}
+ else if ( (units.find ("Bq") != std::string::npos) ||
+ (units.find ("BQ") != std::string::npos) )
+ {
+ list.radioactivityUnits = "Bq";
+ list.tissueRadioactivityUnits = "Bq";
+ }
+ else if ( (units.find ("MCi") != std::string::npos) ||
+ ( units.find ("MCI") != std::string::npos) )
+ {
+ list.radioactivityUnits = "MCi";
+ list.tissueRadioactivityUnits = "MCi";
+ }
+ else if ( (units.find ("kCi") != std::string::npos) ||
+ (units.find ("kCI") != std::string::npos) ||
+ (units.find ("KCI") != std::string::npos) )
+ {
+ list.radioactivityUnits = "kCi";
+ list.tissueRadioactivityUnits = "kCi";
+ }
+ else if ( (units.find ("mCi") != std::string::npos) ||
+ (units.find ("mCI") != std::string::npos) )
+ {
+ list.radioactivityUnits = "mCi";
+ list.tissueRadioactivityUnits = "mCi";
+ }
+ else if ( (units.find ("uCi") != std::string::npos) ||
+ (units.find ("uCI") != std::string::npos) )
+ {
+ list.radioactivityUnits = "uCi";
+ list.tissueRadioactivityUnits = "uCi";
+ }
+ else if ( (units.find ("Ci") != std::string::npos) ||
+ (units.find ("CI") != std::string::npos) )
+ {
+ list.radioactivityUnits = "Ci";
+ list.tissueRadioactivityUnits = "Ci";
+ }
+ list.volumeUnits = "ml";
+ }
+ else
+ {
+ //--- default values.
+ list.radioactivityUnits = "MBq";
+ list.tissueRadioactivityUnits = "MBq";
+ list.volumeUnits = "ml";
+ }
- //---
- //--- PatientName
- tag.clear();
- tag = f->GetEntryValue (0x0010,0x0010);
- if ( tag.c_str() != NULL && strcmp (tag.c_str(), "" ) )
+
+ //---
+ //--- DecayCorrection
+ //--- Possible values are:
+ //--- NONE = no decay correction
+ //--- START= acquisition start time
+ //--- ADMIN = radiopharmaceutical administration time
+ //--- Frame Reference Time is the time that the pixel values in the Image occurred.
+ //--- It's defined as the time offset, in msec, from the Series Reference Time.
+ //--- Series Reference Time is defined by the combination of:
+ //--- Series Date (0008,0021) and
+ //--- Series Time (0008,0031).
+ //--- We don't pull these out now, but can if we have to.
+ if(fileReader.GetElementCS(0x0054,0x1102,tag,false) == EXIT_SUCCESS)
+ {
+ //---A string of characters with leading or trailing spaces (20H) being non-significant.
+ list.decayCorrection = tag.c_str();
+ }
+ else
+ {
+ list.decayCorrection = "MODULE_INIT_NO_VALUE";
+ }
+
+ //---
+ //--- StudyDate
+ if(fileReader.GetElementDA(0x0008,0x0021,tag,false) == EXIT_SUCCESS)
+ {
+ //--- YYYYMMDD
+ yearstr.clear();
+ daystr.clear();
+ monthstr.clear();
+ len = tag.length();
+ if ( len >= 4 )
{
- list.patientName = tag.c_str();
+ yearstr = tag.substr(0, 4);
+ // this->Year = atoi(yearstr.c_str() );
}
else
{
- list.patientName = "MODULE_INIT_NO_VALUE";
+ yearstr = "????";
+ // this->Year = 0;
}
-
- //---
- //--- DecayFactor
- tag.clear();
- tag = f->GetEntryValue (0x0054,0x1321);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ if ( len >= 6 )
{
- //--- have to parse this out. what we have is
- //---A string of characters representing either a fixed point number or a
- //--- floating point number. A fixed point number shall contain only the
- //---characters 0-9 with an optional leading "+" or "-" and an optional "."
- //---to mark the decimal point. A floating point number shall be conveyed
- //---as defined in ANSI X3.9, with an "E" or "e" to indicate the start of the
- //---exponent. Decimal Strings may be padded with leading or trailing spaces.
- //---Embedded spaces are not allowed. or maybe atof does it already...
- list.decayFactor = tag.c_str() ;
+ monthstr = tag.substr(4, 2);
+ // this->Month = atoi ( monthstr.c_str() );
}
else
{
- list.decayFactor = "MODULE_INIT_NO_VALUE" ;
+ monthstr = "??";
+ // this->Month = 0;
}
-
-
- //---
- //--- FrameReferenceTime
- tag.clear();
- tag = f->GetEntryValue (0x0054,0x1300);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ if ( len >= 8 )
{
- //--- The time that the pixel values in the image
- //--- occurred. Frame Reference Time is the
- //--- offset, in msec, from the Series reference
- //--- time.
- list.frameReferenceTime = tag.c_str();
+ daystr = tag.substr (6, 2);
+// this->Day = atoi ( daystr.c_str() );
}
else
{
- list.frameReferenceTime = "MODULE_INIT_NO_VALUE";
+ daystr = "??";
+// this->Day = 0;
}
+ tag.clear();
+ tag = yearstr.c_str();
+ tag += "/";
+ tag += monthstr.c_str();
+ tag += "/";
+ tag += daystr.c_str();
+ list.studyDate = tag.c_str();
+ }
+ else
+ {
+ list.studyDate = "MODULE_INIT_NO_VALUE";
+ }
+ //---
+ //--- PatientName
+ if(fileReader.GetElementPN(0x0010,0x0010,tag,false) == EXIT_SUCCESS)
+ {
+ list.patientName = tag.c_str();
+ }
+ else
+ {
+ list.patientName = "MODULE_INIT_NO_VALUE";
+ }
- //---
- //--- SeriesTime
- tag.clear();
- tag = f->GetEntryValue (0x0008,0x0031);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ //---
+ //--- DecayFactor
+ if(fileReader.GetElementDS(0x0054,0x1321,tag,false) == EXIT_SUCCESS)
+ {
+ //--- have to parse this out. what we have is
+ //---A string of characters representing either a fixed point number or a
+ //--- floating point number. A fixed point number shall contain only the
+ //---characters 0-9 with an optional leading "+" or "-" and an optional "."
+ //---to mark the decimal point. A floating point number shall be conveyed
+ //---as defined in ANSI X3.9, with an "E" or "e" to indicate the start of the
+ //---exponent. Decimal Strings may be padded with leading or trailing spaces.
+ //---Embedded spaces are not allowed. or maybe atof does it already...
+ list.decayFactor = tag.c_str() ;
+ }
+ else
+ {
+ list.decayFactor = "MODULE_INIT_NO_VALUE" ;
+ }
+
+
+ //---
+ //--- FrameReferenceTime
+ if(fileReader.GetElementDS(0x0054,0x1300,tag,false) == EXIT_SUCCESS)
+ {
+ //--- The time that the pixel values in the image
+ //--- occurred. Frame Reference Time is the
+ //--- offset, in msec, from the Series reference
+ //--- time.
+ list.frameReferenceTime = tag.c_str();
+ }
+ else
+ {
+ list.frameReferenceTime = "MODULE_INIT_NO_VALUE";
+ }
+
+
+ //---
+ //--- SeriesTime
+ if(fileReader.GetElementTM(0x0008,0x0031,tag,false) == EXIT_SUCCESS)
+ {
+ hourstr.clear();
+ minutestr.clear();
+ secondstr.clear();
+ len = tag.length();
+ if ( len >= 2 )
{
- hourstr.clear();
- minutestr.clear();
- secondstr.clear();
- len = tag.length();
- if ( len >= 2 )
- {
- hourstr = tag.substr(0, 2);
- }
- else
- {
- hourstr = "00";
- }
- if ( len >= 4 )
- {
- minutestr = tag.substr(2, 2);
- }
- else
- {
- minutestr = "00";
- }
- if ( len >= 6 )
- {
- secondstr = tag.substr(4);
- }
- else
- {
- secondstr = "00";
- }
- tag.clear();
- tag = hourstr.c_str();
- tag += ":";
- tag += minutestr.c_str();
- tag += ":";
- tag += secondstr.c_str();
- list.seriesReferenceTime = tag.c_str();
+ hourstr = tag.substr(0, 2);
}
else
{
- list.seriesReferenceTime = "MODULE_INIT_NO_VALUE";
+ hourstr = "00";
}
-
-
- //---
- //--- PatientWeight
- tag.clear();
- tag = f->GetEntryValue (0x0010,0x1030);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ if ( len >= 4 )
{
- //--- Expect same format as RadionuclideHalfLife
- list.patientWeight = atof ( tag.c_str() );
- list.weightUnits = "kg";
+ minutestr = tag.substr(2, 2);
}
else
{
- list.patientWeight = 0.0;
- list.weightUnits = "";
-
+ minutestr = "00";
}
-
-
- //---
- //--- CalibrationFactor
- tag.clear();
- tag = f->GetEntryValue (0x7053,0x1009);
- if ( tag.c_str() != NULL && strcmp(tag.c_str(), "" ) )
+ if ( len >= 6 )
{
- //--- converts counts to Bq/cc. If Units = BQML then CalibrationFactor =1
- //--- I think we expect the same format as RadiopharmaceuticalStartTime
- list.calibrationFactor = atof(tag.c_str());
+ secondstr = tag.substr(4);
}
else
{
- list.calibrationFactor = 0.0 ;
+ secondstr = "00";
}
+ tag.clear();
+ tag = hourstr.c_str();
+ tag += ":";
+ tag += minutestr.c_str();
+ tag += ":";
+ tag += secondstr.c_str();
+ list.seriesReferenceTime = tag.c_str();
+ }
+ else
+ {
+ list.seriesReferenceTime = "MODULE_INIT_NO_VALUE";
+ }
+
+
+ //---
+ //--- PatientWeight
+ if(fileReader.GetElementDS(0x0010,0x1030,1,&list.patientWeight,false) == EXIT_SUCCESS)
+ {
+ //--- Expect same format as RadionuclideHalfLife
+ list.weightUnits = "kg";
+ }
+ else
+ {
+ list.patientWeight = 0.0;
+ list.weightUnits = "";
+
+ }
+
+
+ //---
+ //--- CalibrationFactor
+ if(fileReader.GetElementDS(0x7053,0x1009,1,
+ &list.calibrationFactor,false) != EXIT_SUCCESS)
+ {
+ list.calibrationFactor = 0.0 ;
}
}
- delete f;
// check.... did we get all params we need for computation?
View
4 Modules/CLI/PETStandardUptakeValueComputation/Testing/CMakeLists.txt
@@ -3,13 +3,15 @@
set(CLP ${MODULE_NAME})
#-----------------------------------------------------------------------------
-add_executable(${CLP}Test ${CLP}Test.cxx)
+add_executable(${CLP}Test ${CLP}Test.cxx ../itkDCMTKFileReader.cxx )
add_dependencies(${CLP}Test ${CLP})
target_link_libraries(${CLP}Test
vtkITK
ModuleDescriptionParser
SlicerBaseCLI
MRMLCore
+ ${DCMTK_LIBRARIES}
+ ${ITK_LIBRARIES}
)
set_target_properties(${CLP}Test PROPERTIES LABELS ${CLP})
View
1,200 Modules/CLI/PETStandardUptakeValueComputation/itkDCMTKFileReader.cxx
@@ -0,0 +1,1200 @@
+/*=========================================================================
+ *
+ * Copyright Insight Software Consortium
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *=========================================================================*/
+
+#include "itkDCMTKFileReader.h"
+#undef HAVE_SSTREAM // 'twould be nice if people coded without using
+// incredibly generic macro names
+#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first
+
+#define INCLUDE_CSTDIO
+#define INCLUDE_CSTRING
+
+#include "dcdict.h" // For DcmDataDictionary
+#include "dcsequen.h" /* for DcmSequenceOfItems */
+#include "dcvrcs.h" /* for DcmCodeString */
+#include "dcvrfd.h" /* for DcmFloatingPointDouble */
+#include "dcvrfl.h" /* for DcmFloatingPointDouble */
+#include "dcvrus.h" /* for DcmUnsignedShort */
+#include "dcvris.h" /* for DcmIntegerString */
+#include "dcvrobow.h" /* for DcmOtherByteOtherWord */
+#include "dcvrui.h" /* for DcmUniqueIdentifier */
+#include "dcfilefo.h" /* for DcmFileFormat */
+#include "dcdeftag.h" /* for DCM_NumberOfFrames */
+#include "dcvrlo.h" /* for DcmLongString */
+#include "dcvrtm.h" /* for DCMTime */
+#include "dcvrda.h" /* for DcmDate */
+#include "dcvrpn.h" /* for DcmPersonName */
+// #include "diregist.h" /* include to support color images */
+#include "vnl/vnl_cross.h"
+
+
+namespace itk
+{
+
+void
+DCMTKSequence
+::SetDcmSequenceOfItems(DcmSequenceOfItems *seq)
+{
+ this->m_DcmSequenceOfItems = seq;
+}
+int
+DCMTKSequence
+::card()
+{
+ return this->m_DcmSequenceOfItems->card();
+}
+
+int
+DCMTKSequence
+::GetSequence(unsigned long index,
+ DCMTKSequence &target,
+ bool throwException)
+{
+ DcmItem *item = this->m_DcmSequenceOfItems->getItem(index);
+ DcmSequenceOfItems *sequence =
+ dynamic_cast<DcmSequenceOfItems *>(item);
+ if(sequence == 0)
+ {
+ DCMTKException(<< "Can't find DCMTKSequence at index " << index);
+ }
+ target.SetDcmSequenceOfItems(sequence);
+ return EXIT_SUCCESS;
+}
+int
+DCMTKSequence
+::GetStack(unsigned short group,
+ unsigned short element,
+ DcmStack *resultStack, bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ if(this->m_DcmSequenceOfItems->search(tagkey,*resultStack) != EC_Normal)
+ {
+ DCMTKException(<< "Can't find tag " << std::hex << group << " "
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence
+::GetElementCS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+ DcmCodeString *codeStringElement = dynamic_cast<DcmCodeString *>(resultStack.top());
+ if(codeStringElement == 0)
+ {
+ DCMTKException(<< "Can't get CodeString Element at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(codeStringElement->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get OFString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned j = 0; j < ofString.length(); ++j)
+ {
+ target += ofString[j];
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence::
+GetElementFD(unsigned short group,
+ unsigned short element,
+ double * &target,
+ bool throwException)
+{
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+ DcmFloatingPointDouble *fdItem = dynamic_cast<DcmFloatingPointDouble *>(resultStack.top());
+ if(fdItem == 0)
+ {
+ DCMTKException(<< "Can't get CodeString Element at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ if(fdItem->getFloat64Array(target) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get floatarray Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence
+::GetElementFD(unsigned short group,
+ unsigned short element,
+ double &target,
+ bool throwException)
+{
+ double *array;
+ this->GetElementFD(group,element,array,throwException);
+ target = array[0];
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence
+::GetElementDS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+ DcmDecimalString *decimalStringElement = dynamic_cast<DcmDecimalString *>(resultStack.top());
+ if(decimalStringElement == 0)
+ {
+ DCMTKException(<< "Can't get DecimalString Element at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(decimalStringElement->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get DecimalString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned j = 0; j < ofString.length(); ++j)
+ {
+ target += ofString[j];
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence
+::GetElementSQ(unsigned short group,
+ unsigned short element,
+ DCMTKSequence &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+
+ DcmSequenceOfItems *seqElement = dynamic_cast<DcmSequenceOfItems *>(resultStack.top());
+ if(seqElement == 0)
+ {
+ DCMTKException(<< "Can't get at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target.SetDcmSequenceOfItems(seqElement);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKSequence
+::GetElementTM(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+
+ DcmTime *dcmTime = dynamic_cast<DcmTime *>(resultStack.top());
+ if(dcmTime == 0)
+ {
+ DCMTKException(<< "Can't get at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ char *cs;
+ dcmTime->getString(cs);
+ target = cs;
+ return EXIT_SUCCESS;
+}
+
+DCMTKFileReader
+::~DCMTKFileReader()
+{
+
+ delete m_DFile;
+}
+
+void
+DCMTKFileReader
+::SetFileName(const std::string &fileName)
+{
+ this->m_FileName = fileName;
+}
+
+const std::string &
+DCMTKFileReader
+::GetFileName() const
+{
+ return this->m_FileName;
+}
+
+void
+DCMTKFileReader
+::LoadFile()
+{
+ if(this->m_FileName == "")
+ {
+ itkGenericExceptionMacro(<< "No filename given" );
+ }
+ if(this->m_DFile != 0)
+ {
+ delete this->m_DFile;
+ }
+ this->m_DFile = new DcmFileFormat();
+ OFCondition cond = this->m_DFile->loadFile(this->m_FileName.c_str());
+ // /* transfer syntax, autodetect */
+ // EXS_Unknown,
+ // /* group length */
+ // EGL_noChange,
+ // /* Max read length */
+ // 1024, // should be big
+ // // enough for
+ // // header stuff but
+ // // prevent reading
+ // // image data.
+ // /* file read mode */
+ // ERM_fileOnly);
+ if(cond != EC_Normal)
+ {
+ itkGenericExceptionMacro(<< cond.text() << ": reading file " << this->m_FileName);
+ }
+ this->m_Dataset = this->m_DFile->getDataset();
+ this->m_Xfer = this->m_Dataset->getOriginalXfer();
+ if(this->m_Dataset->findAndGetSint32(DCM_NumberOfFrames,this->m_FrameCount).bad())
+ {
+ this->m_FrameCount = 1;
+ }
+ int fnum;
+ this->GetElementIS(0x0020,0x0013,fnum);
+ this->m_FileNumber = fnum;
+}
+
+int
+DCMTKFileReader
+::GetElementLO(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmLongString *loItem = dynamic_cast<DcmLongString *>(el);
+ if(loItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(loItem->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Cant get string from element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned i = 0; i < ofString.size(); i++)
+ {
+ target += ofString[i];
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementLO(unsigned short group,
+ unsigned short element,
+ std::vector<std::string> &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmLongString *loItem = dynamic_cast<DcmLongString *>(el);
+ if(loItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ target.clear();
+ OFString ofString;
+ for(unsigned long i = 0; loItem->getOFString(ofString,i) == EC_Normal; ++i)
+ {
+ std::string targetStr = "";
+ for(unsigned j = 0; j < ofString.size(); j++)
+ {
+ targetStr += ofString[j];
+ }
+ target.push_back(targetStr);
+ }
+ return EXIT_SUCCESS;
+}
+
+/** Get a DecimalString Item as a single string
+ */
+int
+DCMTKFileReader
+::GetElementDS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmDecimalString *dsItem = dynamic_cast<DcmDecimalString *>(el);
+ if(dsItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(dsItem->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get DecimalString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned j = 0; j < ofString.length(); ++j)
+ {
+ target += ofString[j];
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementFD(unsigned short group,
+ unsigned short element,
+ double &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmFloatingPointDouble *fdItem = dynamic_cast<DcmFloatingPointDouble *>(el);
+ if(fdItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(fdItem->getFloat64(target) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+int
+DCMTKFileReader
+::GetElementFD(unsigned short group,
+ unsigned short element,
+ double * &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmFloatingPointDouble *fdItem = dynamic_cast<DcmFloatingPointDouble *>(el);
+ if(fdItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(fdItem->getFloat64Array(target) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+int
+DCMTKFileReader
+::GetElementFL(unsigned short group,
+ unsigned short element,
+ float &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmFloatingPointSingle *flItem = dynamic_cast<DcmFloatingPointSingle *>(el);
+ if(flItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(flItem->getFloat32(target) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+int
+DCMTKFileReader
+::GetElementFLorOB(unsigned short group,
+ unsigned short element,
+ float &target,
+ bool throwException)
+{
+ if(this->GetElementFL(group,element,target,false) == EXIT_SUCCESS)
+ {
+ return EXIT_SUCCESS;
+ }
+ std::string val;
+ if(this->GetElementOB(group,element,val) != EXIT_SUCCESS)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ const char *data = val.c_str();
+ const float *fptr = reinterpret_cast<const float *>(data);
+ target = *fptr;
+ switch(this->GetTransferSyntax())
+ {
+ case EXS_LittleEndianImplicit:
+ case EXS_LittleEndianExplicit:
+ itk::ByteSwapper<float>::SwapFromSystemToLittleEndian(&target);
+ break;
+ case EXS_BigEndianImplicit:
+ case EXS_BigEndianExplicit:
+ itk::ByteSwapper<float>::SwapFromSystemToBigEndian(&target);
+ break;
+ default:
+ break;
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementUS(unsigned short group,
+ unsigned short element,
+ unsigned short &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmUnsignedShort *usItem = dynamic_cast<DcmUnsignedShort *>(el);
+ if(usItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(usItem->getUint16(target) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+int
+DCMTKFileReader
+::GetElementUS(unsigned short group,
+ unsigned short element,
+ unsigned short *&target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmUnsignedShort *usItem = dynamic_cast<DcmUnsignedShort *>(el);
+ if(usItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(usItem->getUint16Array(target) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ return EXIT_SUCCESS;
+}
+/** Get a DecimalString Item as a single string
+ */
+int
+DCMTKFileReader
+::GetElementCS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmCodeString *csItem = dynamic_cast<DcmCodeString *>(el);
+ if(csItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(csItem->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get DecimalString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned j = 0; j < ofString.length(); ++j)
+ {
+ target += ofString[j];
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementPN(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmPersonName *pnItem = dynamic_cast<DcmPersonName *>(el);
+ if(pnItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(pnItem->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get DecimalString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = "";
+ for(unsigned j = 0; j < ofString.length(); ++j)
+ {
+ target += ofString[j];
+ }
+ return EXIT_SUCCESS;
+}
+
+/** get an IS (Integer String Item
+ */
+int
+DCMTKFileReader
+::GetElementIS(unsigned short group,
+ unsigned short element,
+ ::itk::int32_t &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmIntegerString *isItem = dynamic_cast<DcmIntegerString *>(el);
+ if(isItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ Sint32 _target; // MSVC seems to have type conversion problems with
+ // using int32_t as a an argument to getSint32
+ if(isItem->getSint32(_target) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get DecimalString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = static_cast< ::itk::int32_t>(_target);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementISorOB(unsigned short group,
+ unsigned short element,
+ ::itk::int32_t &target,
+ bool throwException)
+{
+ if(this->GetElementIS(group,element,target,false) == EXIT_SUCCESS)
+ {
+ return EXIT_SUCCESS;
+ }
+ std::string val;
+ if(this->GetElementOB(group,element,val,throwException) != EXIT_SUCCESS)
+ {
+ return EXIT_FAILURE;
+ }
+ const char *data = val.c_str();
+ const int *iptr = reinterpret_cast<const int *>(data);
+ target = *iptr;
+ switch(this->GetTransferSyntax())
+ {
+ case EXS_LittleEndianImplicit:
+ case EXS_LittleEndianExplicit:
+ itk::ByteSwapper<int>::SwapFromSystemToLittleEndian(&target);
+ break;
+ case EXS_BigEndianImplicit:
+ case EXS_BigEndianExplicit:
+ itk::ByteSwapper<int>::SwapFromSystemToBigEndian(&target);
+ break;
+ default: // no idea what to do
+ break;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/** get an OB OtherByte Item
+ */
+int
+DCMTKFileReader
+::GetElementOB(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmOtherByteOtherWord *obItem = dynamic_cast<DcmOtherByteOtherWord *>(el);
+ if(obItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFString ofString;
+ if(obItem->getOFStringArray(ofString) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get OFString Value at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ target = Self::ConvertFromOB(ofString);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementSQ(unsigned short group,
+ unsigned short entry,
+ DCMTKSequence &sequence,
+ bool throwException)
+{
+ DcmSequenceOfItems *seq;
+ DcmTagKey tagKey(group,entry);
+
+ if(this->m_Dataset->findAndGetSequence(tagKey,seq) != EC_Normal)
+ {
+ DCMTKException(<< "Can't find sequence "
+ << std::hex << group << " "
+ << std::hex << entry)
+ }
+ sequence.SetDcmSequenceOfItems(seq);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementUI(unsigned short group,
+ unsigned short entry,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagKey(group,entry);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagKey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << entry << std::dec);
+ }
+ DcmUniqueIdentifier *uiItem = dynamic_cast<DcmUniqueIdentifier *>(el);
+ if(uiItem == 0)
+ {
+ DCMTKException(<< "Can't convert data item " << group
+ << "," << entry);
+ }
+ OFString ofString;
+ if(uiItem->getOFStringArray(ofString,0) != EC_Normal)
+ {
+ DCMTKException(<< "Can't get UID Value at tag "
+ << std::hex << group << " " << std::hex
+ << entry << std::dec);
+ }
+ target = "";
+ for(unsigned int j = 0; j < ofString.length(); ++j)
+ {
+ target.push_back(ofString[j]);
+ }
+ return EXIT_SUCCESS;
+}
+
+int DCMTKFileReader::
+GetElementDA(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmDate *dcmDate = dynamic_cast<DcmDate *>(el);
+ if(dcmDate == 0)
+ {
+ DCMTKException(<< "Can't get at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ char *cs;
+ dcmDate->getString(cs);
+ target = cs;
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetElementTM(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException)
+{
+
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmTime *dcmTime = dynamic_cast<DcmTime *>(el);
+ if(dcmTime == 0)
+ {
+ DCMTKException(<< "Can't get at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+ char *cs;
+ dcmTime->getString(cs);
+ target = cs;
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetDirCosines(vnl_vector<double> &dir1,
+ vnl_vector<double> &dir2,
+ vnl_vector<double> &dir3)
+{
+ double dircos[6];
+ DCMTKSequence planeSeq;
+ if(this->GetElementDS(0x0020,0x0037,6,dircos,false) != EXIT_SUCCESS)
+ {
+ if(this->GetElementSQ(0x0020,0x9116,planeSeq,false) == EXIT_SUCCESS)
+ {
+ if(planeSeq.GetElementDS(0x0020,0x0037,6,dircos,false) != EXIT_SUCCESS)
+ {
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ dir1[0] = dircos[0]; dir1[1] = dircos[1]; dir1[2] = dircos[2];
+ dir2[0] = dircos[3]; dir2[1] = dircos[4]; dir2[2] = dircos[5];
+ dir3 = vnl_cross_3d(dir1,dir2);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetSlopeIntercept(double &slope, double &intercept)
+{
+ if(this->GetElementDS<double>(0x0028,1053,1,&slope,false) != EXIT_SUCCESS)
+ {
+ slope = 1.0;
+ }
+ if(this->GetElementDS<double>(0x0028,1052,1,&intercept,false) != EXIT_SUCCESS)
+ {
+ intercept = 0.0;
+ }
+ return EXIT_SUCCESS;
+}
+
+ImageIOBase::IOPixelType
+DCMTKFileReader
+::GetImagePixelType()
+{
+ unsigned short SamplesPerPixel;
+ if(this->GetElementUS(0x0028,0x0100,SamplesPerPixel,false) != EXIT_SUCCESS)
+ {
+ return ImageIOBase::UNKNOWNPIXELTYPE;
+ }
+ ImageIOBase::IOPixelType pixelType;
+ switch(SamplesPerPixel)
+ {
+ case 8:
+ case 16:
+ pixelType = ImageIOBase::SCALAR;
+ break;
+ case 24:
+ pixelType = ImageIOBase::RGB;
+ break;
+ default:
+ pixelType = ImageIOBase::VECTOR;
+ }
+ return pixelType;
+}
+
+ImageIOBase::IOComponentType
+DCMTKFileReader
+::GetImageDataType()
+{
+ unsigned short IsSigned;
+ unsigned short BitsAllocated;
+ unsigned short BitsStored;
+ unsigned short HighBit;
+ ImageIOBase::IOComponentType type =
+ ImageIOBase::UNKNOWNCOMPONENTTYPE;
+
+ if(this->GetElementUS(0x0028,0x0100,BitsAllocated,false) != EXIT_SUCCESS ||
+ this->GetElementUS(0x0028,0x0101,BitsStored,false) != EXIT_SUCCESS ||
+ this->GetElementUS(0x0028,0x0102,HighBit,false) != EXIT_SUCCESS ||
+ this->GetElementUS(0x0028,0x0103,IsSigned,false) != EXIT_SUCCESS)
+ {
+ return type;
+ }
+ double slope, intercept;
+ this->GetSlopeIntercept(slope,intercept);
+
+ switch( BitsAllocated )
+ {
+ case 1:
+ case 8:
+ case 24: // RGB?
+ if(IsSigned)
+ {
+ type = ImageIOBase::CHAR;
+ }
+ else
+ {
+ type = ImageIOBase::UCHAR;
+ }
+ break;
+ case 12:
+ case 16:
+ if(IsSigned)
+ {
+ type = ImageIOBase::SHORT;
+ }
+ else
+ {
+ type = ImageIOBase::USHORT;
+ }
+ break;
+ case 32:
+ case 64: // Don't know what this actually means
+ if(IsSigned)
+ {
+ type = ImageIOBase::LONG;
+ }
+ else
+ {
+ type = ImageIOBase::ULONG;
+ }
+ break;
+ case 0:
+ default:
+ break;
+ //assert(0);
+ }
+
+ return type;
+}
+
+
+int
+DCMTKFileReader
+::GetDimensions(unsigned short &rows, unsigned short &columns)
+{
+ if(this->GetElementUS(0x0028,0x0010,rows,false) != EXIT_SUCCESS ||
+ this->GetElementUS(0x0028,0x0011,columns,false) != EXIT_SUCCESS)
+ {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetSpacing(double *spacing)
+{
+ double _spacing[3];
+ //
+ // There are several tags that can have spacing, and we're going
+ // from most to least desirable, starting with PixelSpacing, which
+ // is guaranteed to be in patient space.
+ // Imager Pixel spacing is inter-pixel spacing at the sensor front plane
+ // Pixel spacing
+ if((this->GetElementDS<double>(0x0028,0x0030,2,_spacing,false) != EXIT_SUCCESS &&
+ // imager pixel spacing
+ this->GetElementDS<double>(0x0018, 0x1164, 2, &_spacing[0],false) != EXIT_SUCCESS &&
+ // Nominal Scanned PixelSpacing
+ this->GetElementDS<double>(0x0018, 0x2010, 2, &_spacing[0],false) != EXIT_SUCCESS) ||
+ // slice thickness
+ this->GetElementDS<double>(0x0018,0x0050,1,&_spacing[2],false) != EXIT_SUCCESS)
+ {
+ // that method failed, go looking for the spacing sequence
+ DCMTKSequence spacingSequence;
+ DCMTKSequence subSequence;
+ DCMTKSequence subsubSequence;
+ // first, shared function groups sequence, then
+ // per-frame groups sequence
+ if((this->GetElementSQ(0x5200,0x9229,spacingSequence,false) == EXIT_SUCCESS ||
+ this->GetElementSQ(0X5200,0X9230,spacingSequence,false) == EXIT_SUCCESS) &&
+ spacingSequence.GetSequence(0,subSequence,false) == EXIT_SUCCESS &&
+ subSequence.GetElementSQ(0x0028,0x9110,subsubSequence,false) == EXIT_SUCCESS)
+ {
+ if(subsubSequence.GetElementDS<double>(0x0028,0x0030,2,_spacing,false) != EXIT_SUCCESS)
+ {
+ // Pixel Spacing
+ _spacing[0] = _spacing[1] = 1.0;
+ }
+ if(subsubSequence.GetElementDS<double>(0x0018,0x0050,1,&_spacing[2],false) != EXIT_SUCCESS)
+ {
+ // Slice Thickness
+ _spacing[2] = 1.0;
+ }
+ }
+ else
+ {
+ // punt if no info found.
+ _spacing[0] = _spacing[1] = _spacing[2] = 1.0;
+ }
+ }
+ //
+ // spacing is row spacing\column spacing
+ // but a slice is width-first, i.e. columns increase fastest.
+ //
+ spacing[0] = _spacing[1];
+ spacing[1] = _spacing[0];
+ spacing[2] = _spacing[2];
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetOrigin(double *origin)
+{
+ DCMTKSequence originSequence;
+ DCMTKSequence subSequence;
+ DCMTKSequence subsubSequence;
+
+ if((this->GetElementSQ(0x5200,0x9229,originSequence,false) == EXIT_SUCCESS ||
+ this->GetElementSQ(0X5200,0X9239,originSequence,false) == EXIT_SUCCESS) &&
+ originSequence.GetSequence(0,subSequence,false) == EXIT_SUCCESS &&
+ subSequence.GetElementSQ(0x0028,0x9113,subsubSequence,false) == EXIT_SUCCESS)
+ {
+ subsubSequence.GetElementDS<double>(0x0020,0x0032,3,origin,true);
+ return EXIT_SUCCESS;
+ }
+ this->GetElementDS<double>(0x0020,0x0032,3,origin,true);
+ return EXIT_SUCCESS;
+}
+
+int
+DCMTKFileReader
+::GetFrameCount() const
+{
+ return this->m_FrameCount;
+}
+
+E_TransferSyntax
+DCMTKFileReader
+::GetTransferSyntax() const
+{
+ return m_Xfer;
+}
+
+long
+DCMTKFileReader
+::GetFileNumber() const
+{
+ return m_FileNumber;
+}
+
+void
+DCMTKFileReader
+::AddDictEntry(DcmDictEntry *entry)
+{
+ DcmDataDictionary &dict = dcmDataDict.wrlock();
+ dict.addEntry(entry);
+ dcmDataDict.unlock();
+}
+
+unsigned
+DCMTKFileReader
+::ascii2hex(char c)
+{
+ switch(c)
+ {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a':
+ case 'A': return 10;
+ case 'b':
+ case 'B': return 11;
+ case 'c':
+ case 'C': return 12;
+ case 'd':
+ case 'D': return 13;
+ case 'e':
+ case 'E': return 14;
+ case 'f':
+ case 'F': return 15;
+ }
+ return 255; // should never happen
+}
+
+std::string
+DCMTKFileReader
+::ConvertFromOB(OFString &toConvert)
+{
+ // string format is nn\nn\nn...
+ std::string rval;
+ for(size_t pos = 0; pos < toConvert.size(); pos += 3)
+ {
+ unsigned char convert[2];
+ convert[0] = Self::ascii2hex(toConvert[pos]);
+ convert[1] = Self::ascii2hex(toConvert[pos+1]);
+ unsigned char conv = convert[0] << 4;
+ conv += convert[1];
+ rval.push_back(static_cast<unsigned char>(conv));
+ }
+ return rval;
+}
+
+bool CompareDCMTKFileReaders(DCMTKFileReader *a, DCMTKFileReader *b)
+{
+ return a->GetFileNumber() < b->GetFileNumber();
+}
+
+}
View
371 Modules/CLI/PETStandardUptakeValueComputation/itkDCMTKFileReader.h
@@ -0,0 +1,371 @@
+/*=========================================================================
+ *
+ * Copyright Insight Software Consortium
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *=========================================================================*/
+#ifndef __itkDCMTKFileReader_h
+
+#define __itkDCMTKFileReader_h
+#include <stack>
+#include <vector>
+#include "itkByteSwapper.h"
+#include "itkIntTypes.h"
+#include "vnl/vnl_vector.h"
+#include "dcxfer.h"
+#include "dcvrds.h"
+#include "dcstack.h"
+#include "dcdatset.h"
+#include "itkMacro.h"
+#include "itkImageIOBase.h"
+
+class DcmSequenceOfItems;
+class DcmFileFormat;
+class DcmDictEntry;
+
+// Don't print error messages if you're not throwing
+// an exception
+// std::cerr body;
+#define DCMTKException(body) \
+ { \
+ if(throwException) \
+ { \
+ itkGenericExceptionMacro(body); \
+ } \
+ else \
+ { \
+ return EXIT_FAILURE; \
+ } \
+ }
+
+namespace itk
+{
+class DCMTKSequence
+{
+public:
+ DCMTKSequence() : m_DcmSequenceOfItems(0) {}
+ void SetDcmSequenceOfItems(DcmSequenceOfItems *seq);
+ int card();
+ int GetSequence(unsigned long index,
+ DCMTKSequence &target,bool throwException = true);
+ int GetStack(unsigned short group,
+ unsigned short element,
+ DcmStack *resultStack, bool throwException = true);
+ int GetElementCS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+ int GetElementFD(unsigned short group,
+ unsigned short element,
+ double * &target,
+ bool throwException = true);
+ int GetElementFD(unsigned short group,
+ unsigned short element,
+ double &target,
+ bool throwException = true);
+ int GetElementDS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+ int GetElementTM(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+ /** Get an array of data values, as contained in a DICOM
+ * DecimalString Item
+ */
+ template <typename TType>
+ int GetElementDS(unsigned short group,
+ unsigned short element,
+ unsigned short count,
+ TType *target,
+ bool throwException)
+ {
+ DcmStack resultStack;
+ this->GetStack(group,element,&resultStack);
+ DcmDecimalString *dsItem =
+ dynamic_cast<DcmDecimalString *>(resultStack.top());
+ if(dsItem == 0)
+ {
+ DCMTKException(<< "Can't get DecimalString Element at tag "
+ << std::hex << group << " "
+ << element << std::dec);
+ }
+
+ OFVector<Float64> doubleVals;
+ if(dsItem->getFloat64Vector(doubleVals) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(doubleVals.size() != count)
+ {
+ DCMTKException(<< "DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << " expected "
+ << count << "items, but found "
+ << doubleVals.size() << std::dec);
+
+ }
+ for(unsigned i = 0; i < count; i++)
+ {
+ target[i] = static_cast<TType>(doubleVals[i]);
+ }
+ return EXIT_SUCCESS;
+ }
+ int GetElementSQ(unsigned short group,
+ unsigned short element,
+ DCMTKSequence &target,
+ bool throwException = true);
+private:
+ DcmSequenceOfItems *m_DcmSequenceOfItems;
+};
+
+class DCMTKFileReader
+{
+public:
+ typedef DCMTKFileReader Self;
+
+ DCMTKFileReader() : m_DFile(0),
+ m_Dataset(0),
+ m_Xfer(EXS_Unknown),
+ m_FrameCount(0),
+ m_FileNumber(-1L)
+ {
+ }
+ ~DCMTKFileReader();
+
+ void SetFileName(const std::string &fileName);
+
+ const std::string &GetFileName() const;
+
+ void LoadFile();
+
+ int GetElementLO(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+ int GetElementLO(unsigned short group,
+ unsigned short element,
+ std::vector<std::string> &target,
+ bool throwException = true);
+
+ /** Get an array of data values, as contained in a DICOM
+ * DecimalString Item
+ */
+ template <typename TType>
+ int GetElementDS(unsigned short group,
+ unsigned short element,
+ unsigned short count,
+ TType *target,
+ bool throwException = true)
+ {
+ DcmTagKey tagkey(group,element);
+ DcmElement *el;
+ if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
+ {
+ DCMTKException(<< "Cant find tag " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ DcmDecimalString *dsItem = dynamic_cast<DcmDecimalString *>(el);
+ if(dsItem == 0)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ OFVector<Float64> doubleVals;
+ if(dsItem->getFloat64Vector(doubleVals) != EC_Normal)
+ {
+ DCMTKException(<< "Cant extract Array from DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ if(doubleVals.size() != count)
+ {
+ DCMTKException(<< "DecimalString " << std::hex
+ << group << " " << std::hex
+ << element << " expected "
+ << count << "items, but found "
+ << doubleVals.size() << std::dec);
+
+ }
+ for(unsigned i = 0; i < count; i++)
+ {
+ target[i] = static_cast<TType>(doubleVals[i]);
+ }
+ return EXIT_SUCCESS;
+ }
+
+ template <typename TType>
+ int GetElementDSorOB(unsigned short group,
+ unsigned short element,
+ TType &target,
+ bool throwException = true)
+ {
+ if(this->GetElementDS<TType>(group,element,1,&target,false) == EXIT_SUCCESS)
+ {
+ return EXIT_SUCCESS;
+ }
+ std::string val;
+ if(this->GetElementOB(group,element,val) != EXIT_SUCCESS)
+ {
+ DCMTKException(<< "Cant find DecimalString element " << std::hex
+ << group << " " << std::hex
+ << element << std::dec);
+ }
+ const char *data = val.c_str();
+ const TType *fptr = reinterpret_cast<const TType *>(data);
+ target = *fptr;
+ switch(this->GetTransferSyntax())
+ {
+ case EXS_LittleEndianImplicit:
+ case EXS_LittleEndianExplicit:
+ itk::ByteSwapper<TType>::SwapFromSystemToLittleEndian(&target);
+ break;
+ case EXS_BigEndianImplicit:
+ case EXS_BigEndianExplicit:
+ itk::ByteSwapper<TType>::SwapFromSystemToBigEndian(&target);
+ break;
+ default:
+ break;
+ }
+ return EXIT_SUCCESS;
+
+ }
+ /** Get a DecimalString Item as a single string
+ */
+ int GetElementDS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+ int GetElementFD(unsigned short group,
+ unsigned short element,
+ double &target,
+ bool throwException = true);
+ int GetElementFD(unsigned short group,
+ unsigned short element,
+ double * &target,
+ bool throwException = true);
+ int GetElementFL(unsigned short group,
+ unsigned short element,
+ float &target,
+ bool throwException = true);
+ int GetElementFLorOB(unsigned short group,
+ unsigned short element,
+ float &target,
+ bool throwException = true);
+
+ int GetElementUS(unsigned short group,
+ unsigned short element,
+ unsigned short &target,
+ bool throwException = true);
+ int GetElementUS(unsigned short group,
+ unsigned short element,
+ unsigned short *&target,
+ bool throwException = true);
+ /** Get a DecimalString Item as a single string
+ */
+ int GetElementCS(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+
+ /** Get a PersonName Item as a single string
+ */
+ int GetElementPN(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+
+ /** get an IS (Integer String Item
+ */
+ int GetElementIS(unsigned short group,
+ unsigned short element,
+ ::itk::int32_t &target,
+ bool throwException = true);
+
+ int GetElementISorOB(unsigned short group,
+ unsigned short element,
+ ::itk::int32_t &target,
+ bool throwException = true);
+ /** get an OB OtherByte Item
+ */
+ int GetElementOB(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+
+ int GetElementSQ(unsigned short group,
+ unsigned short entry,
+ DCMTKSequence &sequence,
+ bool throwException = true);
+
+ int GetElementUI(unsigned short group,
+ unsigned short entry,
+ std::string &target,
+ bool throwException = true);
+
+ int GetElementDA(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+
+ int GetElementTM(unsigned short group,
+ unsigned short element,
+ std::string &target,
+ bool throwException = true);
+
+ int GetDirCosines(vnl_vector<double> &dir1,
+ vnl_vector<double> &dir2,
+ vnl_vector<double> &dir3);
+
+ int GetFrameCount() const;
+
+ int GetSlopeIntercept(double &slope, double &intercept);
+
+ int GetDimensions(unsigned short &rows, unsigned short &columns);
+
+ ImageIOBase::IOComponentType GetImageDataType();
+ ImageIOBase::IOPixelType GetImagePixelType();
+
+ int GetSpacing(double *spacing);
+ int GetOrigin(double *origin);
+
+ E_TransferSyntax GetTransferSyntax() const;
+
+ long GetFileNumber() const;
+
+ static void
+ AddDictEntry(DcmDictEntry *entry);
+
+private:
+ static unsigned ascii2hex(char c);
+
+ static std::string ConvertFromOB(OFString &toConvert);
+
+ std::string m_FileName;
+ DcmFileFormat* m_DFile;
+ DcmDataset * m_Dataset;
+ E_TransferSyntax m_Xfer;
+ Sint32 m_FrameCount;
+ long m_FileNumber;
+};
+
+extern bool CompareDCMTKFileReaders(DCMTKFileReader *a, DCMTKFileReader *b);
+}
+
+#endif // __itkDCMTKFileReader_h
Please sign in to comment.
Something went wrong with that request. Please try again.