1 /*=========================================================================
4 Module: $RCSfile: vtkGdcm4DSplitter.cxx,v $
6 Date: $Date: 2011/03/29 12:49:27 $
7 Version: $Revision: 1.1 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 /* Raisons ne pas utiliser itkImageSeriesReader:
21 On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
23 I'm developing with ITK 3.20 + GDCM 2.0.17 + VTK 5.6 and I've noticed
24 itkImageSeriesReader is ~2x slower than vtkGDCMImageReader (from GDCM2).
25 I compared both codes and I think the difference is the extra copy which
26 itkImageSeriesReader makes from ImageFileReader's output to its own output
27 (ImageSeriesReader::GenerateData() line 393).
30 #include "gdcmSerieHelper.h"
32 #include "vtkGdcmReader.h"
33 #include "vtkGdcm4DSplitter.h"
35 #include "gdcmSerieHelper.h" // for ImagePositionPatientOrdering()
36 #include <stdlib.h> // for atof
38 vtkGdcm4DSplitter::vtkGdcm4DSplitter() :
39 SplitOnPosition(false), SplitOnOrientation(false), SplitOnTag(false),
40 SplitGroup(0), SplitElem(0),
42 SortOnPosition(false), SortOnOrientation(false), SortOnTag(false),
43 SortGroup(0), SortElem(0), SortConvertToFloat(false),
45 Recursive(false), TypeDir(0),
51 std::vector<vtkImageData*> * vtkGdcm4DSplitter::GetImageDataVector()
53 if (verbose) std::cout << "TypeDir " << TypeDir << std::endl;
55 return ImageDataVector;
59 std::vector<vtkImageData*> *t = new std::vector<vtkImageData*>;
60 t->push_back( ImageData );
64 return (std::vector<vtkImageData*>*) NULL;
67 vtkImageData *vtkGdcm4DSplitter::GetImageData()
74 return (*ImageDataVector)[0];
77 return (vtkImageData*) NULL;
81 bool vtkGdcm4DSplitter::setDirName(std::string &dirName)
83 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirName) )
85 std::cout << "[" << dirName << "] is NOT a directory" << std::endl;
93 bool vtkGdcm4DSplitter::setVectDirName(std::vector<std::string> &vectDirName)
95 int nbDir = vectDirName.size();
96 for (int iDir=0; iDir<nbDir; iDir++)
98 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(vectDirName[iDir]) )
100 std::cout << "[" << vectDirName[iDir] << "] is NOT a directory" << std::endl;
105 VectDirName = vectDirName;
110 bool vtkGdcm4DSplitter::setVectFileName(std::vector<std::string> &vectFileName)
112 if ( vectFileName.size() == 0)
114 std::cout << "[ vectFileName ] : empty list" << std::endl;
117 VectFileName = vectFileName;
122 bool vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2)
124 if (verbose) printf ("%04x %04x\n", this->SortGroup,this->SortElem);
125 if (verbose) std :: cout << file1->GetEntryString(SortGroup,SortElem).c_str() << " : "
126 << atof(file1->GetEntryString(SortGroup,SortElem).c_str())
128 return atof(file1->GetEntryString(SortGroup,SortElem).c_str()) < atof(file2->GetEntryString(SortGroup,SortElem).c_str());
131 bool vtkGdcm4DSplitter::CompareOnSortTag(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2)
133 return file1->GetEntryString(SortGroup,SortElem) < file2->GetEntryString(SortGroup,SortElem);
136 bool vtkGdcm4DSplitter::Go()
138 if (!SplitOnPosition && !SplitOnOrientation && !SplitOnTag )
140 ///\TODO (?) Throw an exception "Choose Splitting mode before!"
141 std::cout << "Choose Splitting mode before!" << std::endl;
147 entree nom de directory / Vecteur de noms?
149 recuperer la liste des gdcm::File*
150 passer a SerieHelper (pas de check du Serie UID)
153 trier chaque Coherent file set
154 passer chacun a un vtkGcdmReader
155 retourner le (vecteur de) vtkImageData
158 GDCM_NAME_SPACE::SerieHelper *s;
159 s = GDCM_NAME_SPACE::SerieHelper::New();
161 GDCM_NAME_SPACE::File *f;
162 GDCM_NAME_SPACE::DirListType fileNames;
166 ///\TODO (?) Throw an exception "Set input Directory name(s) / file names before!"
167 std::cout << "Set input Directory name(s) / file names before!" << std::endl;
170 else if (TypeDir == 1)
172 GDCM_NAME_SPACE::DirList dirlist(DirName, Recursive); // NO recursive exploration
173 fileNames = dirlist.GetFilenames(); // all the file names
176 else if (TypeDir == 2)
178 int nbDir = VectDirName.size();
179 GDCM_NAME_SPACE::DirListType tmpFileNames;
180 for (int iDir=0; iDir<nbDir; iDir++)
182 GDCM_NAME_SPACE::DirList dirlist(VectDirName[iDir], Recursive);
183 tmpFileNames = dirlist.GetFilenames();
184 // Concat two std::vector
185 //vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
186 fileNames.insert( fileNames.end(), tmpFileNames.begin(), tmpFileNames.end() );
189 else if (TypeDir == 3)
191 fileNames=VectFileName;
194 GDCM_NAME_SPACE::FileList *l = new GDCM_NAME_SPACE::FileList; // (set of gdcm::File)
195 double floatTagvalue;
196 // Loop on all the gdcm-readable files
197 for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();
198 it != fileNames.end();
201 int maxSize = 0x7fff; // load Elements of any length
202 f = GDCM_NAME_SPACE::File::New();
203 f->SetMaxSizeLoadEntry(maxSize);
204 f->SetFileName( *it );
208 std::cout << " Fail to load [" << *it << "]" << std::endl;
211 GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
213 if (SplitOnOrientation)
215 s->SetDropDuplicatePositions(false);
216 xcm = s->SplitOnOrientation(l);
218 else if (SplitOnPosition)
220 s->SetDropDuplicatePositions(true);
221 xcm = s->SplitOnPosition(l);
225 s->SetDropDuplicatePositions(false);
227 // Crashes if DataElement not found
228 //std:: cout << GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(groupelem[0],groupelem[1])->GetName() << std::endl;
229 if ( ! SplitConvertToFloat )
230 xcm = s->SplitOnTagValue(l, SplitGroup, SplitElem);
233 xcm = s->SplitOnTagValueConvertToFloat(l, SplitGroup, SplitElem);
239 if(verbose) std::cout << "Empty XCoherent File Set after 'split' ?!?" << std::endl;
242 else if (xcm.size() == 1)
247 ImageDataVector = new std::vector<vtkImageData*>;
248 vtkGdcmReader *reader = vtkGdcmReader::New();
249 for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin();
254 std::cout << "--- xCoherentName = [" << (*i).first << "]" << std::endl;
256 // XCoherentFileSetmap map < critère de split, FileList (= std::vector de gdcm::File*) >
258 for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin();
263 std::cout << "==========================================xCoherentName = [" << (*i).first << "]" << std::endl;
267 if (verbose) std::cout << "SortOnPosition" << std::endl;
268 // (will be IPPSorter, in GDCM2)
269 s->ImagePositionPatientOrdering((*i).second);
270 if (verbose) std::cout << "out of SortOnPosition" << std::endl
273 if (SortOnOrientation)
275 if (verbose) std::cout << "SortOnOrientation" << std::endl;
276 /// \TODO SortOnOrientation()
277 // Within a 'just to see' program,
278 // OrderFileList() causes trouble, since some files
279 // (eg:MIP views) don't have 'Position', now considered as mandatory
280 // --> Activated on user demand.
282 // Information is in :
283 // 0020,0032 : Image Position Patient
284 // 0020,0030 : Image Position (RET)
286 // we still miss an algo to sort an Orientation, given by 6 cosines!
287 // Anything like this, in GDCM2?
288 std::cout << "SortOnOrientation : not so easy - I(mage)O(rientation)P(atient)Sorter still missing! -" << std::endl;
289 // have a look at SerieHelper::SplitOnPosition() to have an idea of the mess!
291 //Better sort on the file name, right now...
292 s->FileNameOrdering((*i).second);
297 if (verbose) std::cout << "SortOnFileName" << std::endl;
298 if (verbose) std::cout << "taille " << ((*i).second)->size() << std::endl;
299 s->FileNameOrdering((*i).second);
300 if (verbose) std::cout << "Out of SortOnFileName" << std::endl;
305 if (verbose) std::cout << "SortOnTag" << std::endl;
306 printf ("--> %04x %04x\n", SortGroup,SortElem);
307 if ( SortConvertToFloat )
308 s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)>
309 ( &vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat));
311 s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)>
312 ( &vtkGdcm4DSplitter::CompareOnSortTag));
314 // Anything like this, in GDCM2?
315 s->UserOrdering((*i).second);
316 if (verbose) std::cout << "Out of SortOnTag" << std::endl;
319 reader->SetCoherentFileList((*i).second);
321 ImageDataVector->push_back(reader->GetOutput() );
323 std::cout << std::endl;