Page MenuHomePhabricator

dicom_sorting.patch

Authored By
santos
Jan 17 2011, 10:48 AM
Size
31 KB
Referenced Files
None
Subscribers
None

dicom_sorting.patch

Index: mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp
===================================================================
--- mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp (revision 28789)
+++ mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp (working copy)
@@ -162,7 +162,7 @@
QmitkDICOMBrowserView::ProgressAux::m_LastProgress = 0u;
mitk::DicomSeriesReader::StringContainer names = mitk::DicomSeriesReader::GetSeries(dir.toStdString(), series_uid.toStdString());
- mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(names, QmitkDICOMBrowserView::ProgressAux::UpdateProgressBar);
+ mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(names, true, true, QmitkDICOMBrowserView::ProgressAux::UpdateProgressBar);
if (node.IsNull())
{
Index: mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp
===================================================================
--- mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp (revision 28789)
+++ mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp (working copy)
@@ -90,7 +90,6 @@
bool mitk::DataNodeFactory::m_TextureInterpolationActive = false; // default value for texture interpolation if nothing is defined in global options (see QmitkMainTemplate.ui.h)
mitk::DataNodeFactory::DataNodeFactory()
-: m_UseSeriesDetails(true)
{
m_Serie = false;
m_OldProgress = 0;
@@ -248,7 +247,7 @@
}
#endif
- DicomSeriesReader::UidFileNamesMap names_map = DicomSeriesReader::GetSeries(this->GetDirectory(), this->m_UseSeriesDetails, this->m_SeriesRestrictions);
+ DicomSeriesReader::UidFileNamesMap names_map = DicomSeriesReader::GetSeries(this->GetDirectory(), this->m_SeriesRestrictions);
const unsigned int size = names_map.size();
this->ResizeOutputs(size);
Index: mitk/Core/Code/Algorithms/mitkDataNodeFactory.h
===================================================================
--- mitk/Core/Code/Algorithms/mitkDataNodeFactory.h (revision 28789)
+++ mitk/Core/Code/Algorithms/mitkDataNodeFactory.h (working copy)
@@ -93,9 +93,6 @@
*/
void SetImageSerie(bool serie);
- itkGetMacro( UseSeriesDetails, bool );
- itkSetMacro( UseSeriesDetails, bool );
-
void AddSeriesRestriction(const std::string &tag)
{m_SeriesRestrictions.push_back(tag);}
@@ -176,7 +173,6 @@
virtual void ReadFileSeriesTypeITKImageSeriesReader();
- bool m_UseSeriesDetails;
std::vector<std::string> m_SeriesRestrictions;
int m_OldProgress;
};
Index: mitk/Core/Code/IO/mitkDicomSeriesReader.cpp
===================================================================
--- mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (revision 28789)
+++ mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (working copy)
@@ -30,11 +30,11 @@
typedef itk::GDCMSeriesFileNames DcmFileNamesGeneratorType;
-DataNode::Pointer DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, UpdateCallBackMethod callback)
+DataNode::Pointer DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, bool sort, bool check_4d, UpdateCallBackMethod callback)
{
DataNode::Pointer node = DataNode::New();
- if (DicomSeriesReader::LoadDicomSeries(filenames, *node, callback))
+ if (DicomSeriesReader::LoadDicomSeries(filenames, *node, sort, check_4d, callback))
{
return node;
}
@@ -44,7 +44,7 @@
}
}
-bool DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback)
+bool DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback)
{
if(filenames.size() == 0)
{
@@ -64,34 +64,34 @@
switch (io->GetComponentType())
{
case DcmIoType::UCHAR:
- DicomSeriesReader::LoadDicom<unsigned char>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<unsigned char>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::CHAR:
- DicomSeriesReader::LoadDicom<char>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<char>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::USHORT:
- DicomSeriesReader::LoadDicom<unsigned short>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<unsigned short>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::SHORT:
- DicomSeriesReader::LoadDicom<short>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<short>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::UINT:
- DicomSeriesReader::LoadDicom<unsigned int>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<unsigned int>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::INT:
- DicomSeriesReader::LoadDicom<int>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<int>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::ULONG:
- DicomSeriesReader::LoadDicom<long unsigned int>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<long unsigned int>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::LONG:
- DicomSeriesReader::LoadDicom<long int>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<long int>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::FLOAT:
- DicomSeriesReader::LoadDicom<float>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<float>(filenames, node, sort, check_4d, callback);
return true;
case DcmIoType::DOUBLE:
- DicomSeriesReader::LoadDicom<double>(filenames, node, callback);
+ DicomSeriesReader::LoadDicom<double>(filenames, node, sort, check_4d, callback);
return true;
default:
MITK_ERROR << "Unknown pixel type!";
@@ -126,7 +126,7 @@
if (io->CanReadFile(filename.c_str()))
{
//Look at header Tag 3001,0010 if it is "Philips3D"
- gdcm::PixmapReader reader;
+ gdcm::Reader reader;
reader.SetFileName(filename.c_str());
reader.Read();
gdcm::DataSet &data_set = reader.GetFile().GetDataSet();
@@ -144,7 +144,7 @@
bool DicomSeriesReader::ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image)
{
- // Now get PhilipsSpecific Tags
+ // Now get PhilipsSpecific Tags
gdcm::PixmapReader reader;
reader.SetFileName(filename.c_str());
@@ -164,7 +164,7 @@
gdcm::Attribute<0x0018,0x6026> physicalTagY;
gdcm::Attribute<0x3001,0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ; // (Philips specific)
- dimTagX.Set(data_set);
+ dimTagX.Set(data_set);
dimTagY.Set(data_set);
dimTagZ.Set(data_set);
dimTagT.Set(data_set);
@@ -229,26 +229,26 @@
myRegion.SetIndex( myIndex );
imageItk->SetSpacing(mySpacing);
imageItk->SetRegions( myRegion);
- imageItk->Allocate();
+ imageItk->Allocate();
imageItk->FillBuffer(0);
itk::ImageRegionIterator<ImageType> iterator(imageItk, imageItk->GetLargestPossibleRegion());
- iterator.GoToBegin();
+ iterator.GoToBegin();
unsigned long pixCount = 0;
unsigned long planeSize = dimX*dimY;
- unsigned long planeCount = 0;
- unsigned long timeCount = 0;
+ unsigned long planeCount = 0;
+ unsigned long timeCount = 0;
unsigned long numberOfSlices = dimZ;
while (!iterator.IsAtEnd())
- {
- unsigned long adressedPixel =
+ {
+ unsigned long adressedPixel =
pixCount
+ (numberOfSlices-1-planeCount)*planeSize // add offset to adress the first pixel of current plane
+ timeCount*numberOfSlices*planeSize; // add time offset
iterator.Set( new_pixels[ adressedPixel ] );
- pixCount++;
+ pixCount++;
++iterator;
if (pixCount == planeSize)
@@ -265,29 +265,43 @@
{
break;
}
- }
- mitk::CastToMitkImage(imageItk, output_image);
+ }
+ mitk::CastToMitkImage(imageItk, output_image);
/*
// this works as well, but then the picture is upside down.. transversal slice[max] should be transversal slice[0] and so on.
while (!iterator.IsAtEnd())
{
iterator.Set( new_pixels[pixCount] );
- pixCount++;
+ pixCount++;
iterator++;
- }
- mitk::CastToMitkImage(imageItk, image);
- */
+ }
+ mitk::CastToMitkImage(imageItk, image);
+ */
return true; // actually never returns false yet.. but exception possible
}
#endif
-DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, bool additional_criteria, const StringContainer &restrictions)
+DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, const StringContainer &restrictions)
{
DcmFileNamesGeneratorType::Pointer name_generator = DcmFileNamesGeneratorType::New();
- name_generator->SetUseSeriesDetails(additional_criteria);
- name_generator->SetDirectory(dir.c_str());
+ /**
+ assumption about this method:
+ returns a map of uid-like-key --> list(filename)
+ each entry should contain filenames that have images of same
+ - TODO study instance uid
+ - TODO series instance uid
+ - 0020,0037 image orientation (patient)
+ - 0028,0030 pixel spacing (x,y)
+ - 0018,0050 slice thickness
+
+ */
+
+ name_generator->SetUseSeriesDetails(true);
+ name_generator->AddSeriesRestriction("0020|0037"); // image orientation (patient)
+ name_generator->AddSeriesRestriction("0028|0030"); // pixel spacing (x,y)
+
const StringContainer::const_iterator restrictions_end = restrictions.end();
for(StringContainer::const_iterator it = restrictions.begin(); it != restrictions_end; ++it)
@@ -295,6 +309,8 @@
name_generator->AddSeriesRestriction(*it);
}
+ name_generator->SetDirectory(dir.c_str());
+
UidFileNamesMap map;
const StringContainer &series_uids = name_generator->GetSeriesUIDs();
const StringContainer::const_iterator series_end = series_uids.end();
@@ -309,13 +325,13 @@
return map;
}
-DicomSeriesReader::StringContainer DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, bool additional_criteria,
- const StringContainer &restrictions)
+DicomSeriesReader::StringContainer DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, const StringContainer &restrictions)
{
DcmFileNamesGeneratorType::Pointer name_generator = DcmFileNamesGeneratorType::New();
- name_generator->SetUseSeriesDetails(additional_criteria);
- name_generator->SetDirectory(dir.c_str());
+ name_generator->SetUseSeriesDetails(true);
+ name_generator->AddSeriesRestriction("0020|0037"); // image orientation (patient)
+ name_generator->AddSeriesRestriction("0028|0030"); // pixel spacing (x,y)
const StringContainer::const_iterator restrictions_end = restrictions.end();
@@ -324,27 +340,68 @@
name_generator->AddSeriesRestriction(*it);
}
+ name_generator->SetDirectory(dir.c_str());
+
return name_generator->GetFileNames(series_uid);
}
+DicomSeriesReader::StringContainer DicomSeriesReader::SortSeriesSlices(const StringContainer &unsortedFilenames)
+{
#if GDCM_MAJOR_VERSION >= 2
+ gdcm::Sorter sorter;
+
+ sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction);
+ sorter.Sort(unsortedFilenames);
+ return sorter.GetFilenames();
+#else
+ return unsortedFilenames;
+#endif
+}
+
+#if GDCM_MAJOR_VERSION >= 2
bool DicomSeriesReader::GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2)
{
gdcm::Attribute<0x0008,0x0032> acq_time1; // Acquisition time
gdcm::Attribute<0x0020,0x0032> image_pos1; // Image Position (Patient)
+ gdcm::Attribute<0x0020,0x0037> image_orientation1; // Image Orientation (Patient)
acq_time1.Set(ds1);
image_pos1.Set(ds1);
+ image_orientation1.Set(ds1);
gdcm::Attribute<0x0008,0x0032> acq_time2;
gdcm::Attribute<0x0020,0x0032> image_pos2;
+ gdcm::Attribute<0x0020,0x0037> image_orientation2;
acq_time2.Set(ds2);
image_pos2.Set(ds2);
+ image_orientation2.Set(ds2);
+ if (image_orientation1 != image_orientation2)
+ {
+ MITK_ERROR << "Dicom images have different orientations.";
+ throw std::logic_error("Dicom images have different orientations.");
+ }
+
if (acq_time1 == acq_time2)
{
- return image_pos1 < image_pos2;
+ double normal[3];
+
+ normal[0] = image_orientation1[1] * image_orientation1[5] - image_orientation1[2] * image_orientation1[4];
+ normal[1] = image_orientation1[2] * image_orientation1[3] - image_orientation1[0] * image_orientation1[5];
+ normal[2] = image_orientation1[0] * image_orientation1[4] - image_orientation1[1] * image_orientation1[3];
+
+ double
+ dist1 = 0.0,
+ dist2 = 0.0;
+
+ for (unsigned char i = 0u; i < 3u; ++i)
+ {
+ dist1 += normal[i] * image_pos1[i];
+ dist2 += normal[i] * image_pos2[i];
+ }
+
+ return dist1 < dist2;
}
return acq_time1 < acq_time2;
Index: mitk/Core/Code/IO/mitkDicomSeriesReader.h
===================================================================
--- mitk/Core/Code/IO/mitkDicomSeriesReader.h (revision 28789)
+++ mitk/Core/Code/IO/mitkDicomSeriesReader.h (working copy)
@@ -43,114 +43,140 @@
namespace mitk
{
+/**
+* Provides functions for loading DICOM series.
+* The series is specified through an enumeration of all files contained in it.
+* A method for the creation of file name enumerations of all series contained in
+* a particular directory is also provided.
+* After loading the series, the generated DataNode is not named. The caller is
+* responsible for given the node a name.
+*/
+class MITK_CORE_EXPORT DicomSeriesReader
+{
+public:
+ typedef std::vector<std::string> StringContainer;
+ typedef std::map<std::string, StringContainer> UidFileNamesMap;
+ typedef void (*UpdateCallBackMethod)(float);
+
/**
- * Provides functions for loading DICOM series.
- * The series is specified through an enumeration of all files contained in it.
- * A method for the creation of file name enumerations of all series contained in
- * a particular directory is also provided.
- * After loading the series, the generated DataNode is not named. The caller is
- * responsible for given the node a name.
+ * Loads a DICOM series composed by the file names enumerated in the file names container.
+ * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1].
*/
- class MITK_CORE_EXPORT DicomSeriesReader
- {
- public:
- typedef std::vector<std::string> StringContainer;
- typedef std::map<std::string, StringContainer> UidFileNamesMap;
- typedef void (*UpdateCallBackMethod)(float);
+ static DataNode::Pointer LoadDicomSeries(const StringContainer &filenames, bool sort = true, bool check_4d = true, UpdateCallBackMethod callback = 0);
- /**
- * Loads a DICOM series composed by the file names enumerated in the file names container.
- * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1].
- */
- static DataNode::Pointer LoadDicomSeries(const StringContainer &filenames, UpdateCallBackMethod callback = 0);
+ /**
+ * Loads a DICOM series composed by the file names enumerated in the file names container.
+ * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1].
+ */
+ static bool LoadDicomSeries(const StringContainer &filenames, DataNode &node, bool sort = true, bool check_4d = true, UpdateCallBackMethod callback = 0);
- /**
- * Loads a DICOM series composed by the file names enumerated in the file names container.
- * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1].
- */
- static bool LoadDicomSeries(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback = 0);
+ /**
+ * Checks if a specific file is a DICOM.
+ */
+ static bool IsDicom(const std::string &filename);
- /**
- * Checks if a specific file is a DICOM.
- */
- static bool IsDicom(const std::string &filename);
-
#if GDCM_MAJOR_VERSION >= 2
- /**
- * Checks if a specific file is a Philips3D Ultrasound DICOM file.
- */
- static bool IsPhilips3DDicom(const std::string &filename);
+ /**
+ * Checks if a specific file is a Philips3D Ultrasound DICOM file.
+ */
+ static bool IsPhilips3DDicom(const std::string &filename);
- /**
- * Read a Philips3D Ultrasound DICOM file and put into an mitk image
- */
- static bool ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image);
+ /**
+ * Read a Philips3D Ultrasound DICOM file and put into an mitk image
+ */
+ static bool ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image);
#endif
- /**
- * Find all series in a particular directory.
- * For each series, an enumeration of the files contained in it is created.
- * Optionally, more criteria can be used to distinguish between different series, and series
- * restrictions can be specified.
- */
- static UidFileNamesMap GetSeries(const std::string &dir, bool additional_criteria = false,
- const StringContainer &restrictions = StringContainer());
+ /**
+ * \brief Find all series (and sub-series -- see details) in a particular directory.
+ *
+ * For each series, an enumeration of the files contained in it is created.
+ *
+ * \return The resulting map will map SeriesInstanceUID to UNSORTED lists of file names.
+ *
+ * SeriesInstanceUID will be FORCED to be unique for each set of file names
+ * that should be loadable as a single mitk::Image. This implies that
+ * Image orientation, slice thickness, pixel spacing, rows, and columns
+ * must be the same for each file (i.e. the image slice contained in the file).
+ *
+ * If this separation logic requires that a SeriesInstanceUID must be made more specialized,
+ * it will follow the same logic as itk::GDCMSeriesFileNames to enhance the UID with
+ * more digits and dots.
+ *
+ * Optionally, more tags can be used to separate files into different logical series by setting
+ * the restrictions parameter.
+ */
+ static UidFileNamesMap GetSeries(const std::string &dir, const StringContainer &restrictions = StringContainer());
- /**
- * Find a particular series in a directory.
- * For each series, an enumeration of the files contained in it is created.
- * Optionally, more criteria can be used to distinguish between different series, and series
- * restrictions can be specified.
- */
- static StringContainer GetSeries(const std::string &dir, const std::string &series_uid,
- bool additional_criteria = false, const StringContainer &restrictions = StringContainer());
- protected:
- inline DicomSeriesReader()
- {}
+ /**
+ * Find a particular series in a directory.
+ * For each series, an enumeration of the files contained in it is created.
+ * Optionally, more criteria (restrictions) can be used to distinguish between different series, and series
+ * restrictions can be specified.
+ */
+ static StringContainer GetSeries(const std::string &dir, const std::string &series_uid,
+ const StringContainer &restrictions = StringContainer());
- inline ~DicomSeriesReader()
- {}
+ /**
+ * Sort a set of file names in an order that is meaningful for loading them into an mitk::Image.
+ *
+ * \warning This method assumes that input files are similar in basic properties such as slice thicknes, image orientation, pixel spacing, rows, columns.
+ *
+ * It should always be ok to put the result of a call to GetSeries(..) into this method.(..).
+ *
+ * Sorting order is determined by
+ *
+ * 1. TODO
+ * 2.
+ */
+ static StringContainer SortSeriesSlices(const StringContainer &unsortedFilenames);
+protected:
+ inline DicomSeriesReader()
+ {}
+ inline ~DicomSeriesReader()
+ {}
+
#ifdef MITK_USE_GDCMIO
- typedef itk::GDCMImageIO DcmIoType;
+ typedef itk::GDCMImageIO DcmIoType;
#else
- typedef itk::DICOMImageIO2 DcmIoType;
+ typedef itk::DICOMImageIO2 DcmIoType;
#endif
- class CallbackCommand : public itk::Command
+ class CallbackCommand : public itk::Command
+ {
+ public:
+ inline CallbackCommand(UpdateCallBackMethod callback)
+ : m_Callback(callback)
+ {}
+
+ inline void Execute(const itk::Object *caller, const itk::EventObject&)
{
- public:
- inline CallbackCommand(UpdateCallBackMethod callback)
- : m_Callback(callback)
- {}
+ (*this->m_Callback)(static_cast<const itk::ProcessObject*>(caller)->GetProgress());
+ }
- inline void Execute(const itk::Object *caller, const itk::EventObject&)
- {
- (*this->m_Callback)(static_cast<const itk::ProcessObject*>(caller)->GetProgress());
- }
+ inline void Execute(itk::Object *caller, const itk::EventObject&)
+ {
+ (*this->m_Callback)(static_cast<itk::ProcessObject*>(caller)->GetProgress());
+ }
+ protected:
+ UpdateCallBackMethod m_Callback;
+ };
- inline void Execute(itk::Object *caller, const itk::EventObject&)
- {
- (*this->m_Callback)(static_cast<itk::ProcessObject*>(caller)->GetProgress());
- }
- protected:
- UpdateCallBackMethod m_Callback;
- };
+ /**
+ * Performs the loading of a series and creates an image having the specified pixel type.
+ */
+ template <typename PixelType>
+ static void LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback);
- /**
- * Performs the loading of a series and creates an image having the specified pixel type.
- */
- template <typename PixelType>
- static void LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback);
-
#if GDCM_MAJOR_VERSION >= 2
- /*
- * Auxiliary sort function for Gdcm Dicom sorting. It is used for sorting
- * 4D Dicom data.
- */
- static bool GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2);
+ /*
+ * Auxiliary sort function for Gdcm Dicom sorting. It is used for sorting
+ * 4D Dicom data.
+ */
+ static bool GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2);
#endif
- };
+};
}
Index: mitk/Core/Code/IO/mitkDicomSeriesReader.txx
===================================================================
--- mitk/Core/Code/IO/mitkDicomSeriesReader.txx (revision 28789)
+++ mitk/Core/Code/IO/mitkDicomSeriesReader.txx (working copy)
@@ -21,117 +21,80 @@
#include <mitkDicomSeriesReader.h>
#include <itkImageSeriesReader.h>
-//#define GDCM_MAJOR_VERSION 3
-
namespace mitk
{
- template <typename PixelType>
- void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback)
+template <typename PixelType>
+void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback)
+{
+ const char* previousCLocale = setlocale(LC_NUMERIC, NULL);
+ setlocale(LC_NUMERIC, "C");
+ std::locale previousCppLocale( std::cin.getloc() );
+ std::locale l( "C" );
+ std::cin.imbue(l);
+
+ try
{
- const char* previousCLocale = setlocale(LC_NUMERIC, NULL);
- setlocale(LC_NUMERIC, "C");
- std::locale previousCppLocale( std::cin.getloc() );
- std::locale l( "C" );
- std::cin.imbue(l);
+ mitk::Image::Pointer image = mitk::Image::New();
+ CallbackCommand *command = callback ? new CallbackCommand(callback) : 0;
- try
- {
- mitk::Image::Pointer image = mitk::Image::New();
- CallbackCommand *command = callback ? new CallbackCommand(callback) : 0;
-
#if GDCM_MAJOR_VERSION >= 2
- /******** For Philips 3D+t images ********/
- if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) )
- {
- ReadPhilips3DDicom(filenames.front().c_str(), image);
- node.SetData(image);
- setlocale(LC_NUMERIC, previousCLocale);
- std::cin.imbue(previousCppLocale);
- return;
- }
+ /******** For Philips 3D+t images ********/
+ if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) )
+ {
+ ReadPhilips3DDicom(filenames.front().c_str(), image);
+ node.SetData(image);
+ setlocale(LC_NUMERIC, previousCLocale);
+ std::cin.imbue(previousCppLocale);
+ return;
+ }
- /******** For 4D data split in multiple files ***************/
- std::list<StringContainer> decomposed_filenames;
- unsigned int volume_count = 1u;
+ /******** For 4D data split in multiple files ***************/
+ std::list<StringContainer> decomposed_filenames;
+ unsigned int volume_count = 1u;
- gdcm::Sorter sorter;
-
- sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction);
- sorter.Sort(filenames);
-
- gdcm::Tag tag(0x0020,0x1041); //Slice location
+ StringContainer sorted_filenames = sort
+ ? DicomSeriesReader::SortSeriesSlices(filenames)
+ : filenames;
+ if (check_4d)
+ {
+ gdcm::Tag tag(0x0020,0x0032); //Image position (Patient)
gdcm::Scanner scanner;
scanner.AddTag(tag);
- scanner.Scan(sorter.GetFilenames());
+ scanner.Scan(sorted_filenames);
- const StringContainer::const_iterator f_end = sorter.GetFilenames().end();
- const char *act_value = scanner.GetValue(sorter.GetFilenames().front().c_str(), tag);
+ const StringContainer::const_iterator f_end = sorted_filenames.end();
+ const char *act_value = scanner.GetValue(sorted_filenames.front().c_str(), tag);
-
decomposed_filenames.push_back(StringContainer());
- decomposed_filenames.back().push_back(sorter.GetFilenames().front());
+ decomposed_filenames.back().push_back(sorted_filenames.front());
- for (StringContainer::const_iterator f_it = ++sorter.GetFilenames().begin(); f_it != f_end; ++f_it)
+ for (StringContainer::const_iterator f_it = ++sorted_filenames.begin(); f_it != f_end; ++f_it)
{
const char *value = scanner.GetValue(f_it->c_str(), tag);
if (!strcmp(act_value, value))
{
- act_value = value;
decomposed_filenames.push_back(StringContainer());
++volume_count;
}
decomposed_filenames.back().push_back(*f_it);
}
- if (volume_count > 1)
- {
- // It is 4D! Read it and store into mitk image
+ }
+ else
+ {
+ decomposed_filenames.push_back(sorted_filenames);
+ }
- typedef itk::Image<PixelType, 4> ImageType;
- typedef itk::ImageSeriesReader<ImageType> ReaderType;
+ if (volume_count > 1u)
+ {
+ // It is 4D! Read it and store into mitk image
- DcmIoType::Pointer io = DcmIoType::New();
- typename ReaderType::Pointer reader = ReaderType::New();
-
- reader->SetImageIO(io);
- reader->ReverseOrderOff();
-
- if (command)
- {
- reader->AddObserver(itk::ProgressEvent(), command);
- }
-
- const std::list<StringContainer>::const_iterator df_end = decomposed_filenames.end();
- unsigned int act_volume = 1u;
-
- reader->SetFileNames(decomposed_filenames.front());
- reader->Update();
- image->InitializeByItk(reader->GetOutput(), 1, volume_count);
- image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), 0u);
-
- MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << ", " << image->GetDimension(3) << "]";
- MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]";
-
- for (std::list<StringContainer>::iterator df_it = ++decomposed_filenames.begin(); df_it != df_end; ++df_it)
- {
- reader->SetFileNames(*df_it);
- reader->Update();
- image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), act_volume++);
- }
- node.SetData(image);
- setlocale(LC_NUMERIC, previousCLocale);
- std::cin.imbue(previousCppLocale);
- return; // finished
- }
-#endif
- /******** Normal Case, 3D (also for GDCM < 2 usable) ***************/
-
- typedef itk::Image<PixelType, 3> ImageType;
+ typedef itk::Image<PixelType, 4> ImageType;
typedef itk::ImageSeriesReader<ImageType> ReaderType;
DcmIoType::Pointer io = DcmIoType::New();
@@ -145,28 +108,67 @@
reader->AddObserver(itk::ProgressEvent(), command);
}
- reader->SetFileNames(filenames);
+ const std::list<StringContainer>::const_iterator df_end = decomposed_filenames.end();
+ unsigned int act_volume = 1u;
+
+ reader->SetFileNames(decomposed_filenames.front());
reader->Update();
- image->InitializeByItk(reader->GetOutput());
- image->SetImportVolume(reader->GetOutput()->GetBufferPointer());
+ image->InitializeByItk(reader->GetOutput(), 1, volume_count);
+ image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), 0u);
- MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << "]";
+ MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << ", " << image->GetDimension(3) << "]";
MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]";
+ for (std::list<StringContainer>::iterator df_it = ++decomposed_filenames.begin(); df_it != df_end; ++df_it)
+ {
+ reader->SetFileNames(*df_it);
+ reader->Update();
+ image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), act_volume++);
+ }
node.SetData(image);
setlocale(LC_NUMERIC, previousCLocale);
std::cin.imbue(previousCppLocale);
+ return; // finished
+ }
+#endif
+ /******** Normal Case, 3D (also for GDCM < 2 usable) ***************/
+ typedef itk::Image<PixelType, 3> ImageType;
+ typedef itk::ImageSeriesReader<ImageType> ReaderType;
+
+ DcmIoType::Pointer io = DcmIoType::New();
+ typename ReaderType::Pointer reader = ReaderType::New();
+
+ reader->SetImageIO(io);
+ reader->ReverseOrderOff();
+
+ if (command)
+ {
+ reader->AddObserver(itk::ProgressEvent(), command);
}
- catch (std::exception& e)
- {
- setlocale(LC_NUMERIC, previousCLocale);
- std::cin.imbue(previousCppLocale);
- throw e;
- }
+ reader->SetFileNames(filenames);
+ reader->Update();
+ image->InitializeByItk(reader->GetOutput());
+ image->SetImportVolume(reader->GetOutput()->GetBufferPointer());
+
+ MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << "]";
+ MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]";
+
+ node.SetData(image);
+ setlocale(LC_NUMERIC, previousCLocale);
+ std::cin.imbue(previousCppLocale);
+
}
+ catch (std::exception& e)
+ {
+ setlocale(LC_NUMERIC, previousCLocale);
+ std::cin.imbue(previousCppLocale);
+ throw e;
+ }
}
+}
+
#endif

File Metadata

Mime Type
text/plain
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
627
Default Alt Text
dicom_sorting.patch (31 KB)