]> Creatis software - gdcm.git/blobdiff - vtk/vtkGdcm4DSplitter.cxx
Fix GetImageDataVector() vs GetImageData()
[gdcm.git] / vtk / vtkGdcm4DSplitter.cxx
index 378046f343523395130108927e8a2553288f5e1d..352b14705392ae82c338ba66a55d1cdbcc332926 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: vtkGdcm4DSplitter.cxx,v $
   Language:  C++
-  Date:      $Date: 2011/03/29 12:51:21 $
-  Version:   $Revision: 1.2 $
+  Date:      $Date: 2011/04/08 00:11:36 $
+  Version:   $Revision: 1.8 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -27,6 +27,88 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
     (ImageSeriesReader::GenerateData() line 393).
 */
 
+
+/* ====================================================================
+vtkGdcm4DSplitter
+
+3D, 2D+T, 3D+T, n*2D+T, 4D images are not always stored the same way :
+        a single 'Dicom Serie', 
+        several 'Dicom series' within a single directory
+        several 'Dicom series' within several directories
+A 'Dicom Serie' doesn't mean always the same thing :
+        a given Slice along the time
+        a given Volume at a given time
+Sometimes, an image within a serie is so artefacted than user decides to replace
+it by an other image.
+
+User needs to be aware, *only him* knows want he wants to do.
+vtkGdcm4DSplitter class does the job for hom
+(despite its name, it works on 3D or 2D+T images too)
+
+User will have to specify some points
+
+. Choose input data
+------------------- 
+
+- a single directory
+       bool setDirName(std::string &dirName);
+- a list of directories
+       bool setVectDirName(std::vector<std::string> &vectDirName);
+- a list of files       
+       bool setVectFileName(std::vector<std::string> &vectFileName);
+
+- Recursive directory exploration
+       void setRecursive(bool recursive);
+. Choose 'split' criterion :
+---------------------------
+
+ - ImagePositionPatient
+        void setSplitOnPosition();
+ - ImageOrientationPatient
+        void setSplitOnOrientation();
+ - User choosen tag
+        void setSplitOnTag(unsigned short splitGroup, unsigned short splitElem);
+        void setSplitConvertToFloat(bool conv);
+ - UserDefined Function
+        void setSortOnUserFunction (FoncComp f);
+ for 'true' 3D image sets :
+   - if you want to get a single 3D vtkImageData, use SplitOnOrientation -i.e. no split-
+   - if you want to get a vector of 2D vtkImageData, use SplitOnPosition  -i.e. one slice in each 'XCoherent filesite'-
+
+ for 'true' 4D multi-orientation image sets (i.e. a stack of axial + sagital + coronal images, at different instants ...)
+   --> this is 5D, right?
+   Nothing done, yet.
+
+. Choose 'sort' criterion :
+--------------------------
+
+ - ImagePositionPatient
+        void setSortOnPosition(); 
+ - ImageOrientationPatient
+       ==> Only in your dreams!
+       ==> or, please, write a IOP sorter ...
+ - UserDefined Function
+        void setSortOnUserFunction (FoncComp f);
+ - File name
+        void setSortOnFileName()
+  
+. Execute :
+-----------
+        bool Go();
+
+. Get the result
+----------------
+
+// -a single vtkImageData:
+//        vtkImageData *GetImageData();
+- a vector of vtkImageData
+        std::vector<vtkImageData*> *GetImageDataVector();
+
+  ===================================================================== */
+
 #include "gdcmSerieHelper.h"
 
 #include "vtkGdcmReader.h"
@@ -42,15 +124,16 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
                  SortOnPosition(false),  SortOnOrientation(false),  SortOnTag(false), 
                  SortGroup(0),  SortElem(0), SortConvertToFloat(false),
 
-                 Recursive(false), TypeDir(0), 
-                 verbose(true) 
+                 Recursive(false), TypeDir(0),
+                 verbose(false) 
  {
  
  }
 
  std::vector<vtkImageData*> * vtkGdcm4DSplitter::GetImageDataVector() 
- {
- if (verbose) std::cout << "TypeDir " << TypeDir << std::endl;
+ { 
+/*
+ if (verbose) std::cout << "GetImageDataVector : TypeResult " << TypeResult << std::endl;
     if (TypeResult == 2)
        return ImageDataVector;
     else
@@ -62,21 +145,26 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
       }
       else
          return (std::vector<vtkImageData*>*) NULL;
+*/
+     return ImageDataVector;
  }
  
  vtkImageData *vtkGdcm4DSplitter::GetImageData() 
  {
+ /*
+  if (verbose) std::cout << "GetImageData : TypeResult " << TypeResult << std::endl;
     if (TypeResult == 1)
        return ImageData;
     else
-      if (TypeResult == 1)
+      if (TypeResult == 2)
       {
          return (*ImageDataVector)[0];      
       }
       else
          return (vtkImageData*) NULL;
- }
-       
+*/
+   return (*ImageDataVector)[0]; 
+ }      
        
  bool vtkGdcm4DSplitter::setDirName(std::string &dirName) 
  {
@@ -121,18 +209,21 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
 
  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() << " : " 
+  /* 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());  
+*/
+//   return atof(file1->GetEntryString(vtkGdcm4DSplitter::SortGroup,vtkGdcm4DSplitter::SortElem).c_str()) < atof(file2->GetEntryString(vtkGdcm4DSplitter::SortGroup,vtkGdcm4DSplitter::SortElem).c_str()); 
+   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);  
+   return file1->GetEntryString(vtkGdcm4DSplitter::SortGroup,vtkGdcm4DSplitter::SortElem) < file2->GetEntryString(vtkGdcm4DSplitter::SortGroup,vtkGdcm4DSplitter::SortElem);  
  }
-   
  bool vtkGdcm4DSplitter::Go()
  {
    if (!SplitOnPosition && !SplitOnOrientation && !SplitOnTag ) 
@@ -245,7 +336,8 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
       TypeResult=2;
 
    ImageDataVector = new std::vector<vtkImageData*>;
-   vtkGdcmReader *reader = vtkGdcmReader::New();
+  // vtkGdcmReader *reader = vtkGdcmReader::New(); // move inside the loop, or be clever using vtk!
+   
    for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); 
                                                   i != xcm.end();
                                                 ++i)
@@ -259,73 +351,102 @@ On Wed, Feb 16, 2011 at 11:51 AM, Roger Bramon Feixas <rogerbramon@gmail.com>
                                                   i != xcm.end();
                                                 ++i)
    {
-           if (verbose)
+   
+      vtkGdcmReader *reader = vtkGdcmReader::New(); /// \FIXME : unable to delete!
+       
+      if (verbose)
                std::cout << "==========================================xCoherentName = [" << (*i).first << "]" << std::endl;
 
-           if (SortOnPosition)
-           {
+      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)
-           {
+      else 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)
+            /// \TODO SortOnOrientation()
       
             // 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!
+            //  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::SplitOnOrientation() to have an idea of the mess!
 
-      //Better sort on the file name, right now...
-      s->FileNameOrdering((*i).second);   
-   }
+            //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;
-   }
+      else if (SortOnFileName)
+      {
+         if (verbose) std::cout << "SortOnFileName" << std::endl;
+         if (verbose) std::cout << "taille " << ((*i).second)->size() << std::endl;
 
-   if (SortOnTag)
-   {  
-      if (verbose) std::cout << "SortOnTag" << std::endl;   
-      printf ("--> %04x %04x\n", SortGroup,SortElem);
-              if ( SortConvertToFloat )
-         s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)> 
-                                                              ( &vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat));     
-      else
-         s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)>
-                                                              ( &vtkGdcm4DSplitter::CompareOnSortTag)); 
+         s->FileNameOrdering((*i).second);
+         if (verbose) std::cout << "Out of SortOnFileName" << std::endl;
+      }
+
+      else if (SortOnTag)
+      {  
+         if (verbose) std::cout << "SortOnTag" << std::endl;   
+         printf ("--> %04x %04x\n", SortGroup,SortElem);
+         std::cout << "Sorry, troubles not solved yet; use SortOnUserFunction, right now!" << std::endl;
+        /*        ==> WARNING : This one has troubles; do NOT use it, right now!
+        // a pointer to fonction cannot be casted as a pointer to member function!
+        // Use SortOnUserFunction, instead!
+
+         if ( SortConvertToFloat )
+            s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)> 
+                                                                 ( &vtkGdcm4DSplitter::CompareOnSortTagConvertToFloat));     
+         else
+            s->SetUserLessThanFunction( reinterpret_cast<bool (*)(gdcm13::File*, gdcm13::File*)>
+                                                                 ( &vtkGdcm4DSplitter::CompareOnSortTag)); 
        
-      // Anything like this, in GDCM2? 
-      s->UserOrdering((*i).second);
-      if (verbose) std::cout << "Out of SortOnTag" << std::endl;
-   }
+         // Anything like this, in GDCM2? 
+         s->UserOrdering((*i).second);
+        */
 
-    reader->SetCoherentFileList((*i).second);
-    reader->Update();
-            ImageDataVector->push_back(reader->GetOutput() );
+         //if (verbose) std::cout << "Out of SortOnTag" << std::endl;
+         std::cout << "NO ordering performed  :-( " << std::endl;
+      }
+      
+      else if (SortOnUserFunction)
+      {   
+          if (verbose) std::cout << "SortOnUserFunction" << std::endl;
+          s->SetUserLessThanFunction( UserCompareFunction );
+         // Anything like this, in GDCM2? 
+         s->UserOrdering((*i).second);
+         if (verbose) std::cout << "Out of SortOnUserFunction" << std::endl;   
+      }
 
-         std::cout << std::endl;
+       reader->SetCoherentFileList((*i).second);
+       reader->Update();
+       
+       /// \TODO : remove the following
+       if (verbose) {
+          std::cout << "reader->GetOutput() :" << std::endl;
+          reader->GetOutput()->PrintSelf(std::cout, vtkIndent(2));
+       }
+       
+       ImageDataVector->push_back(reader->GetOutput() );
+       
+       std::vector<vtkImageData*>::iterator it; 
+       if (verbose)      
+       for(it=ImageDataVector->begin(); it!=ImageDataVector->end(); ++it) {
+         std::cout << "-in vtkGdcm4DSplitter--------------------------" << std::endl;
+         (*it)->PrintSelf(std::cout, vtkIndent(2));
+       }
+       std::cout << std::endl;
    }
 
-   reader->Delete();
+   //reader->Delete();  // \TODO : fix
    s->Delete(); 
    f->Delete();
    delete l;
+   
+   return true;
  }