From 9c2a69fd5efbcd96f0130811bc0043a0b5d69c92 Mon Sep 17 00:00:00 2001 From: jpr Date: Tue, 29 Mar 2011 12:49:27 +0000 Subject: [PATCH] Deal with 4D image sets --- vtk/vtkGdcm4DSplitter.cxx | 331 ++++++++++++++++++++++++++++++++++++++ vtk/vtkGdcm4DSplitter.h | 102 ++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 vtk/vtkGdcm4DSplitter.cxx create mode 100644 vtk/vtkGdcm4DSplitter.h diff --git a/vtk/vtkGdcm4DSplitter.cxx b/vtk/vtkGdcm4DSplitter.cxx new file mode 100644 index 00000000..6ab01f6a --- /dev/null +++ b/vtk/vtkGdcm4DSplitter.cxx @@ -0,0 +1,331 @@ +/*========================================================================= + + Program: gdcm + Module: $RCSfile: vtkGdcm4DSplitter.cxx,v $ + Language: C++ + Date: $Date: 2011/03/29 12:49:27 $ + Version: $Revision: 1.1 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +/* Raisons ne pas utiliser itkImageSeriesReader: + +On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas + Hi, + I'm developing with ITK 3.20 + GDCM 2.0.17 + VTK 5.6 and I've noticed + itkImageSeriesReader is ~2x slower than vtkGDCMImageReader (from GDCM2). + I compared both codes and I think the difference is the extra copy which + itkImageSeriesReader makes from ImageFileReader's output to its own output + (ImageSeriesReader::GenerateData() line 393). +*/ + +#include "gdcmSerieHelper.h" + +#include "vtkGdcmReader.h" +#include "vtkGdcm4DSplitter.h" +#include +#include "gdcmSerieHelper.h" // for ImagePositionPatientOrdering() +#include // for atof + + vtkGdcm4DSplitter::vtkGdcm4DSplitter() : + SplitOnPosition(false), SplitOnOrientation(false), SplitOnTag(false), + SplitGroup(0), SplitElem(0), + + SortOnPosition(false), SortOnOrientation(false), SortOnTag(false), + SortGroup(0), SortElem(0), SortConvertToFloat(false), + + Recursive(false), TypeDir(0), + verbose(true) + { + + } + + std::vector * vtkGdcm4DSplitter::GetImageDataVector() + { + if (verbose) std::cout << "TypeDir " << TypeDir << std::endl; + if (TypeResult == 2) + return ImageDataVector; + else + if (TypeResult == 1) + { + std::vector *t = new std::vector; + t->push_back( ImageData ); + return t; + } + else + return (std::vector*) NULL; + } + + vtkImageData *vtkGdcm4DSplitter::GetImageData() + { + if (TypeResult == 1) + return ImageData; + else + if (TypeResult == 1) + { + return (*ImageDataVector)[0]; + } + else + return (vtkImageData*) NULL; + } + + + bool vtkGdcm4DSplitter::setDirName(std::string &dirName) + { + if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirName) ) + { + std::cout << "[" << dirName << "] is NOT a directory" << std::endl; + return false; + } + DirName = dirName; + TypeDir=1; + return true; + } + + bool vtkGdcm4DSplitter::setVectDirName(std::vector &vectDirName) + { + int nbDir = vectDirName.size(); + for (int iDir=0; iDir &vectFileName) + { + if ( vectFileName.size() == 0) + { + std::cout << "[ vectFileName ] : empty list" << std::endl; + return false; + } + VectFileName = vectFileName; + TypeDir=3; + return true; + } + + bool vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2) + { + if (verbose) printf ("%04x %04x\n", this->SortGroup,this->SortElem); + if (verbose) std :: cout << file1->GetEntryString(SortGroup,SortElem).c_str() << " : " + << atof(file1->GetEntryString(SortGroup,SortElem).c_str()) + << std::endl; + return atof(file1->GetEntryString(SortGroup,SortElem).c_str()) < atof(file2->GetEntryString(SortGroup,SortElem).c_str()); + } + + bool vtkGdcm4DSplitter::CompareOnSortTag(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2) + { + return file1->GetEntryString(SortGroup,SortElem) < file2->GetEntryString(SortGroup,SortElem); + } + + bool vtkGdcm4DSplitter::Go() + { + if (!SplitOnPosition && !SplitOnOrientation && !SplitOnTag ) + { + ///\TODO (?) Throw an exception "Choose Splitting mode before!" + std::cout << "Choose Splitting mode before!" << std::endl; + return false; + } + + /// How To : + /* + entree nom de directory / Vecteur de noms? + recursif oui/non + recuperer la liste des gdcm::File* + passer a SerieHelper (pas de check du Serie UID) + set critere de split + + trier chaque Coherent file set + passer chacun a un vtkGcdmReader + retourner le (vecteur de) vtkImageData + */ + + GDCM_NAME_SPACE::SerieHelper *s; + s = GDCM_NAME_SPACE::SerieHelper::New(); + + GDCM_NAME_SPACE::File *f; + GDCM_NAME_SPACE::DirListType fileNames; + + if (TypeDir == 0 ) + { + ///\TODO (?) Throw an exception "Set input Directory name(s) / file names before!" + std::cout << "Set input Directory name(s) / file names before!" << std::endl; + return false; + } + else if (TypeDir == 1) + { + GDCM_NAME_SPACE::DirList dirlist(DirName, Recursive); // NO recursive exploration + fileNames = dirlist.GetFilenames(); // all the file names + } + + else if (TypeDir == 2) + { + int nbDir = VectDirName.size(); + GDCM_NAME_SPACE::DirListType tmpFileNames; + for (int iDir=0; iDirSetMaxSizeLoadEntry(maxSize); + f->SetFileName( *it ); + if (f->Load()) + l->push_back(f); + else + std::cout << " Fail to load [" << *it << "]" << std::endl; + } + + GDCM_NAME_SPACE::XCoherentFileSetmap xcm; + + if (SplitOnOrientation) + { + s->SetDropDuplicatePositions(false); + xcm = s->SplitOnOrientation(l); + } + else if (SplitOnPosition) + { + s->SetDropDuplicatePositions(true); + xcm = s->SplitOnPosition(l); + } + else if (SplitOnTag) + { + s->SetDropDuplicatePositions(false); + + // Crashes if DataElement not found + //std:: cout << GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(groupelem[0],groupelem[1])->GetName() << std::endl; + if ( ! SplitConvertToFloat ) + xcm = s->SplitOnTagValue(l, SplitGroup, SplitElem); + else + { + xcm = s->SplitOnTagValueConvertToFloat(l, SplitGroup, SplitElem); + } + } + + if (xcm.size() == 0) + { + if(verbose) std::cout << "Empty XCoherent File Set after 'split' ?!?" << std::endl; + return false; + } + else if (xcm.size() == 1) + TypeResult=1; + else + TypeResult=2; + + ImageDataVector = new std::vector; + vtkGdcmReader *reader = vtkGdcmReader::New(); + for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); + i != xcm.end(); + ++i) + { + if (verbose) + std::cout << "--- xCoherentName = [" << (*i).first << "]" << std::endl; + } + // XCoherentFileSetmap map < critère de split, FileList (= std::vector de gdcm::File*) > + + for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); + i != xcm.end(); + ++i) + { + if (verbose) + std::cout << "==========================================xCoherentName = [" << (*i).first << "]" << std::endl; + + if (SortOnPosition) + { + if (verbose) std::cout << "SortOnPosition" << std::endl; + // (will be IPPSorter, in GDCM2) + s->ImagePositionPatientOrdering((*i).second); + if (verbose) std::cout << "out of SortOnPosition" << std::endl + } + + if (SortOnOrientation) + { + if (verbose) std::cout << "SortOnOrientation" << std::endl; + /// \TODO SortOnOrientation() + // Within a 'just to see' program, + // OrderFileList() causes trouble, since some files + // (eg:MIP views) don't have 'Position', now considered as mandatory + // --> Activated on user demand. + + // Information is in : + // 0020,0032 : Image Position Patient + // 0020,0030 : Image Position (RET) + + // we still miss an algo to sort an Orientation, given by 6 cosines! + // Anything like this, in GDCM2? + std::cout << "SortOnOrientation : not so easy - I(mage)O(rientation)P(atient)Sorter still missing! -" << std::endl; + // have a look at SerieHelper::SplitOnPosition() to have an idea of the mess! + + //Better sort on the file name, right now... + s->FileNameOrdering((*i).second); + } + + if (SortOnFileName) + { + if (verbose) std::cout << "SortOnFileName" << std::endl; + if (verbose) std::cout << "taille " << ((*i).second)->size() << std::endl; + s->FileNameOrdering((*i).second); + if (verbose) std::cout << "Out of SortOnFileName" << std::endl; + } + + if (SortOnTag) + { + if (verbose) std::cout << "SortOnTag" << std::endl; + printf ("--> %04x %04x\n", SortGroup,SortElem); + if ( SortConvertToFloat ) + s->SetUserLessThanFunction( reinterpret_cast + ( &vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat)); + else + s->SetUserLessThanFunction( reinterpret_cast + ( &vtkGdcm4DSplitter::CompareOnSortTag)); + + // Anything like this, in GDCM2? + s->UserOrdering((*i).second); + if (verbose) std::cout << "Out of SortOnTag" << std::endl; + } + + reader->SetCoherentFileList((*i).second); + reader->Update(); + ImageDataVector->push_back(reader->GetOutput() ); + + std::cout << std::endl; + } + + reader->Delete(); + s->Delete(); + f->Delete(); + delete l; + } + diff --git a/vtk/vtkGdcm4DSplitter.h b/vtk/vtkGdcm4DSplitter.h new file mode 100644 index 00000000..04d8abbf --- /dev/null +++ b/vtk/vtkGdcm4DSplitter.h @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: gdcm + Module: $RCSfile: vtkGdcm4DSplitter.h,v $ + Language: C++ + Date: $Date: 2011/03/29 12:49:27 $ + Version: $Revision: 1.1 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef _VTKGDCM4DSPLITTER_H_ +#define _VTKGDCM4DSPLITTER_H_ + +#include +#include +#include "gdcmDirList.h" + +//namespace GDCM_NAME_SPACE +//{ + class vtkGdcm4DSplitter { + public: + + vtkGdcm4DSplitter(); + ~vtkGdcm4DSplitter(){}; + bool setDirName(std::string &dirName); + bool setVectDirName(std::vector &vectDirName); + bool setVectFileName(std::vector &vectFileName); + + inline void setSplitOnPosition() {SplitOnPosition=true; SplitOnOrientation=false; SplitOnTag=false;} + inline void setSplitOnOrientation(){SplitOnPosition=false; SplitOnOrientation=true; SplitOnTag=false;} + inline void setSplitOnTag(unsigned short int splitGroup, unsigned short int splitElem) + {SplitOnPosition=false; SplitOnOrientation=false; SplitOnTag=true; + SplitGroup=splitGroup; SplitElem=splitElem;} + inline void setSplitConvertToFloat(bool conv) {SplitConvertToFloat=conv;} + + inline void setSortOnPosition() {SortOnPosition=true; SortOnOrientation=false; SortOnTag=false; SortOnFileName=false;} + // SortOnOrientation : not yet made + //inline void setSortOnOrientation(){SortOnPosition=false; SortOnOrientation=true; SortOnTag=false; SortOnFileName=false;} + inline void setSortOnTag(unsigned short int sortGroup, unsigned short int sortElem) + {SortOnPosition=false; SortOnOrientation=false; SortOnTag=true; SortOnFileName=false; + SortGroup=sortGroup; SortElem=sortElem;} + inline void setSortConvertToFloat(bool conv) {SortConvertToFloat=conv;} + + inline void setSortOnFileName() {SortOnPosition=false; SortOnOrientation=false; SortOnTag=false; SortOnFileName=true;} + inline void setRecursive(bool recursive) { Recursive=recursive;} + + std::vector *GetImageDataVector(); + vtkImageData *GetImageData(); + + bool Go(); + + protected: + private: + bool CompareOnSortTag (GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2); + bool CompareOnSortTagConvertToFloat(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2); + + // Data + // ---- + public: + protected: + private: + std::string DirName; + std::vector VectDirName; + std::vector VectFileName; + + bool SplitOnPosition; + bool SplitOnOrientation; + bool SplitOnTag; + + unsigned short int SplitGroup; + unsigned short int SplitElem; + bool SplitConvertToFloat; + + bool SortOnPosition; + bool SortOnOrientation; + bool SortOnTag; + bool SortOnFileName; + + unsigned short int SortGroup; + unsigned short int SortElem; + bool SortConvertToFloat; + + bool Recursive; + int TypeDir; + int TypeResult; + bool verbose; + std::vector *ImageDataVector; + vtkImageData *ImageData; + }; + +//} // end namespace gdcm + +//----------------------------------------------------------------------------- +#endif -- 2.45.0