]> Creatis software - gdcm.git/blob - vtk/vtkGdcm4DSplitter.cxx
378046f343523395130108927e8a2553288f5e1d
[gdcm.git] / vtk / vtkGdcm4DSplitter.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: vtkGdcm4DSplitter.cxx,v $
5   Language:  C++
6   Date:      $Date: 2011/03/29 12:51:21 $
7   Version:   $Revision: 1.2 $
8                                                                                 
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.
12                                                                                 
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.
16                                                                                 
17 =========================================================================*/
18
19 /* Raisons ne pas utiliser itkImageSeriesReader:
20
21 On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
22     Hi,
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).
28 */
29
30 #include "gdcmSerieHelper.h"
31
32 #include "vtkGdcmReader.h"
33 #include "vtkGdcm4DSplitter.h"
34 #include <algorithm>
35 #include "gdcmSerieHelper.h" // for ImagePositionPatientOrdering()
36 #include <stdlib.h> // for atof
37
38  vtkGdcm4DSplitter::vtkGdcm4DSplitter() :
39                  SplitOnPosition(false), SplitOnOrientation(false), SplitOnTag(false),
40                  SplitGroup(0), SplitElem(0),
41
42                  SortOnPosition(false),  SortOnOrientation(false),  SortOnTag(false), 
43                  SortGroup(0),  SortElem(0), SortConvertToFloat(false),
44
45                  Recursive(false), TypeDir(0), 
46                  verbose(true) 
47  {
48  
49  }
50
51  std::vector<vtkImageData*> * vtkGdcm4DSplitter::GetImageDataVector() 
52  {
53  if (verbose) std::cout << "TypeDir " << TypeDir << std::endl;
54     if (TypeResult == 2)
55        return ImageDataVector;
56     else
57       if (TypeResult == 1)
58       {
59          std::vector<vtkImageData*> *t = new std::vector<vtkImageData*>; 
60          t->push_back( ImageData );
61          return t;            
62       }
63       else
64          return (std::vector<vtkImageData*>*) NULL;
65  }
66  
67  vtkImageData *vtkGdcm4DSplitter::GetImageData() 
68  {
69     if (TypeResult == 1)
70        return ImageData;
71     else
72       if (TypeResult == 1)
73       {
74          return (*ImageDataVector)[0];      
75       }
76       else
77          return (vtkImageData*) NULL;
78  }
79        
80        
81  bool vtkGdcm4DSplitter::setDirName(std::string &dirName) 
82  {
83     if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirName) ) 
84     {
85        std::cout << "[" << dirName << "] is NOT a directory" << std::endl;
86        return false;
87     }
88     DirName = dirName; 
89     TypeDir=1;
90     return true;
91  }
92  
93  bool vtkGdcm4DSplitter::setVectDirName(std::vector<std::string> &vectDirName) 
94  {
95     int nbDir = vectDirName.size();
96     for (int iDir=0; iDir<nbDir; iDir++)
97     {
98        if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(vectDirName[iDir]) ) 
99        {
100           std::cout << "[" << vectDirName[iDir] << "] is NOT a directory" << std::endl;
101           return false;
102        }
103     }   
104
105     VectDirName = vectDirName; 
106     TypeDir=2;
107     return true;
108  }
109  
110  bool vtkGdcm4DSplitter::setVectFileName(std::vector<std::string> &vectFileName)
111  {
112     if ( vectFileName.size() == 0)
113     {
114           std::cout << "[ vectFileName ] : empty list" << std::endl;
115           return false;
116     }
117     VectFileName = vectFileName;
118     TypeDir=3;
119     return true;
120  }      
121
122  bool vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2)
123  { 
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())
127                             << std::endl;
128    return atof(file1->GetEntryString(SortGroup,SortElem).c_str()) < atof(file2->GetEntryString(SortGroup,SortElem).c_str());  
129  } 
130
131  bool vtkGdcm4DSplitter::CompareOnSortTag(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2)
132  {
133    return file1->GetEntryString(SortGroup,SortElem) < file2->GetEntryString(SortGroup,SortElem);  
134  }
135    
136  bool vtkGdcm4DSplitter::Go()
137  {
138    if (!SplitOnPosition && !SplitOnOrientation && !SplitOnTag ) 
139    {
140        ///\TODO (?) Throw an exception "Choose Splitting mode before!"
141        std::cout << "Choose Splitting mode before!" << std::endl;
142        return false;
143    }
144
145    /// How To :
146    /*
147    entree nom de directory / Vecteur de noms?
148    recursif oui/non
149    recuperer la liste des gdcm::File*
150    passer a SerieHelper (pas de check du Serie UID)
151    set critere de split
152    
153    trier chaque Coherent file set
154    passer chacun a un vtkGcdmReader
155    retourner le (vecteur de) vtkImageData
156    */
157    
158    GDCM_NAME_SPACE::SerieHelper *s;  
159    s = GDCM_NAME_SPACE::SerieHelper::New();
160
161    GDCM_NAME_SPACE::File *f;
162    GDCM_NAME_SPACE::DirListType fileNames;
163    
164    if (TypeDir == 0 )
165    {
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;
168       return false;
169    }
170    else if (TypeDir == 1)
171    {
172       GDCM_NAME_SPACE::DirList dirlist(DirName, Recursive); // NO recursive exploration
173       fileNames = dirlist.GetFilenames(); // all the file names
174    }
175    
176    else if (TypeDir == 2)
177    {
178       int nbDir = VectDirName.size();
179       GDCM_NAME_SPACE::DirListType tmpFileNames;
180       for (int iDir=0; iDir<nbDir; iDir++)
181       {
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() );
187       }    
188    }
189    else if (TypeDir == 3)
190    {
191       fileNames=VectFileName;
192    }  
193
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();
199                                   ++it)
200    {
201       int maxSize  = 0x7fff;         // load Elements of any length
202       f = GDCM_NAME_SPACE::File::New();
203       f->SetMaxSizeLoadEntry(maxSize);
204       f->SetFileName( *it );
205       if (f->Load())
206          l->push_back(f);
207       else 
208          std::cout << " Fail to load [" <<  *it << "]" << std::endl;          
209    }   
210
211    GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
212
213    if (SplitOnOrientation) 
214    {
215             s->SetDropDuplicatePositions(false);
216             xcm = s->SplitOnOrientation(l);
217    }
218    else if (SplitOnPosition)
219    {
220             s->SetDropDuplicatePositions(true);
221             xcm = s->SplitOnPosition(l);
222    }
223    else if (SplitOnTag) 
224    {
225          s->SetDropDuplicatePositions(false);
226
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);
231             else 
232             {
233                 xcm = s->SplitOnTagValueConvertToFloat(l, SplitGroup, SplitElem);
234             }
235    }
236    
237    if (xcm.size() == 0)
238    {
239       if(verbose) std::cout << "Empty XCoherent File Set after 'split' ?!?" << std::endl;
240       return false;
241    }
242    else if (xcm.size() == 1)
243       TypeResult=1;
244    else
245       TypeResult=2;
246
247    ImageDataVector = new std::vector<vtkImageData*>;
248    vtkGdcmReader *reader = vtkGdcmReader::New();
249    for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); 
250                                                   i != xcm.end();
251                                                 ++i)
252    {
253            if (verbose)
254                std::cout << "--- xCoherentName = [" << (*i).first << "]" << std::endl;
255    }
256  // XCoherentFileSetmap map < critère de split, FileList (= std::vector de gdcm::File*) >
257
258    for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); 
259                                                   i != xcm.end();
260                                                 ++i)
261    {
262            if (verbose)
263                std::cout << "==========================================xCoherentName = [" << (*i).first << "]" << std::endl;
264
265            if (SortOnPosition)
266            {
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;     
271             }
272
273            if (SortOnOrientation)
274            {
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.
281    
282            // Information is in :      
283            // 0020,0032 : Image Position Patient
284            // 0020,0030 : Image Position (RET)
285       
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!
290
291       //Better sort on the file name, right now...
292       s->FileNameOrdering((*i).second);   
293    }
294
295    if (SortOnFileName)
296    {
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;
301    }
302
303    if (SortOnTag)
304    {  
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));     
310       else
311          s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)>
312                                                               ( &vtkGdcm4DSplitter::CompareOnSortTag)); 
313        
314       // Anything like this, in GDCM2? 
315       s->UserOrdering((*i).second);
316       if (verbose) std::cout << "Out of SortOnTag" << std::endl;
317    }
318
319     reader->SetCoherentFileList((*i).second);
320     reader->Update();
321             ImageDataVector->push_back(reader->GetOutput() );
322
323          std::cout << std::endl;
324    }
325
326    reader->Delete();
327    s->Delete(); 
328    f->Delete();
329    delete l;
330  }
331