Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

gdcmSerieHelper.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmSerieHelper.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2005/02/05 01:37:09 $
00007   Version:   $Revision: 1.4 $
00008                                                                                 
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012                                                                                 
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016                                                                                 
00017 =========================================================================*/
00018 
00019 #include "gdcmSerieHelper.h"
00020 #include "gdcmDirList.h"
00021 #include "gdcmFile.h"
00022 #include "gdcmDebug.h"
00023 
00024 #include <math.h>
00025 #include <vector>
00026 #include <algorithm>
00027 
00028 namespace gdcm 
00029 {
00030 
00031 //-----------------------------------------------------------------------------
00032 // Constructor / Destructor
00036 SerieHelper::SerieHelper()
00037 {
00038    // For all the File lists of the gdcm::Serie
00039    GdcmFileList *l = GetFirstCoherentFileList();
00040    while (l)
00041    { 
00042       // For all the files of a File list
00043       for (GdcmFileList::iterator it  = l->begin();
00044                                   it != l->end(); 
00045                                 ++it)
00046       {
00047          delete *it;
00048       }
00049       l->clear();
00050       delete l;;
00051       l = GetNextCoherentFileList();
00052    }
00053 }
00054 
00058 SerieHelper::~SerieHelper()
00059 {
00060    // For all the Coherent File lists of the gdcm::Serie
00061    GdcmFileList *l = GetFirstCoherentFileList();
00062    while (l)
00063    { 
00064       // For all the files of a Coherent File list
00065       for (GdcmFileList::iterator it  = l->begin();
00066                                   it != l->end(); 
00067                                 ++it)
00068       {
00069          delete *it;
00070       }
00071       l->clear();
00072       delete l;
00073       l = GetNextCoherentFileList();
00074    }
00075 }
00076 
00077 //-----------------------------------------------------------------------------
00078 
00079 //-----------------------------------------------------------------------------
00080 
00081 // Public
00086 void SerieHelper::AddFileName(std::string const &filename)
00087 {
00088    //directly use string and not const char*:
00089    File *header = new File( filename ); 
00090    if( header->IsReadable() )
00091    {
00092       // 0020 000e UI REL Series Instance UID
00093       std::string uid =  header->GetEntryValue (0x0020, 0x000e);
00094       // if uid == GDCM_UNFOUND then consistently we should find GDCM_UNFOUND
00095       // no need here to do anything special
00096 
00097       if ( CoherentGdcmFileListHT.count(uid) == 0 )
00098       {
00099          gdcmWarningMacro(" New Serie UID :[" << uid << "]");
00100          // create a std::list in 'uid' position
00101          CoherentGdcmFileListHT[uid] = new GdcmFileList;
00102       }
00103       // Current Serie UID and DICOM header seems to match add the file:
00104       CoherentGdcmFileListHT[uid]->push_back( header );
00105    }
00106    else
00107    {
00108       gdcmWarningMacro("Could not read file: " << filename );
00109       delete header;
00110    }
00111 }
00112 
00118 void SerieHelper::SetDirectory(std::string const &dir, bool recursive)
00119 {
00120    DirList dirList(dir, recursive); // OS specific
00121   
00122    DirListType filenames_list = dirList.GetFilenames();
00123    for( DirListType::const_iterator it = filenames_list.begin(); 
00124         it != filenames_list.end(); ++it)
00125    {
00126       AddFileName( *it );
00127    }
00128 }
00129 
00136 void SerieHelper::OrderGdcmFileList(GdcmFileList *CoherentGdcmFileList)
00137 {
00138    if( ImagePositionPatientOrdering( CoherentGdcmFileList ) )
00139    {
00140       return ;
00141    }
00142    else if( ImageNumberOrdering(CoherentGdcmFileList ) )
00143    {
00144       return ;
00145    }
00146    else  
00147    {
00148       FileNameOrdering(CoherentGdcmFileList );
00149    }
00150 }
00151 
00156 GdcmFileList *SerieHelper::GetFirstCoherentFileList()
00157 {
00158    ItListHt = CoherentGdcmFileListHT.begin();
00159    if( ItListHt != CoherentGdcmFileListHT.end() )
00160       return ItListHt->second;
00161    return NULL;
00162 }
00163 
00169 GdcmFileList *SerieHelper::GetNextCoherentFileList()
00170 {
00171    gdcmAssertMacro (ItListHt != CoherentGdcmFileListHT.end());
00172   
00173    ++ItListHt;
00174    if ( ItListHt != CoherentGdcmFileListHT.end() )
00175       return ItListHt->second;
00176    return NULL;
00177 }
00178 
00184 GdcmFileList *SerieHelper::GetCoherentFileList(std::string SerieUID)
00185 {
00186    if ( CoherentGdcmFileListHT.count(SerieUID) == 0 )
00187       return 0;     
00188    return CoherentGdcmFileListHT[SerieUID];
00189 }
00190 
00191 //-----------------------------------------------------------------------------
00192 // Protected
00193 
00194 //-----------------------------------------------------------------------------
00195 // Private
00205 bool SerieHelper::ImagePositionPatientOrdering( GdcmFileList *fileList )
00206 //based on Jolinda's algorithm
00207 {
00208    //iop is calculated based on the file file
00209    float cosines[6];
00210    float normal[3];
00211    float ipp[3];
00212    float dist;
00213    float min = 0, max = 0;
00214    bool first = true;
00215    int n=0;
00216    std::vector<float> distlist;
00217 
00219    for ( GdcmFileList::const_iterator 
00220          it = fileList->begin();
00221          it != fileList->end(); ++it )
00222    {
00223       if( first ) 
00224       {
00225          (*it)->GetImageOrientationPatient( cosines );
00226       
00227          // You only have to do this once for all slices in the volume. Next, 
00228          // for each slice, calculate the distance along the slice normal 
00229          // using the IPP tag ("dist" is initialized to zero before reading 
00230          // the first slice) :
00231          normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
00232          normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
00233          normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];
00234   
00235          ipp[0] = (*it)->GetXOrigin();
00236          ipp[1] = (*it)->GetYOrigin();
00237          ipp[2] = (*it)->GetZOrigin();
00238 
00239          dist = 0;
00240          for ( int i = 0; i < 3; ++i )
00241          {
00242             dist += normal[i]*ipp[i];
00243          }
00244     
00245          if( dist == 0 )
00246          {
00247             return false;
00248          }
00249 
00250          distlist.push_back( dist );
00251 
00252          max = min = dist;
00253          first = false;
00254       }
00255       else 
00256       {
00257          ipp[0] = (*it)->GetXOrigin();
00258          ipp[1] = (*it)->GetYOrigin();
00259          ipp[2] = (*it)->GetZOrigin();
00260   
00261          dist = 0;
00262          for ( int i = 0; i < 3; ++i )
00263          {
00264             dist += normal[i]*ipp[i];
00265          }
00266 
00267          if( dist == 0 )
00268          {
00269             return false;
00270          }
00271       
00272          distlist.push_back( dist );
00273 
00274          min = (min < dist) ? min : dist;
00275          max = (max > dist) ? max : dist;
00276       }
00277       ++n;
00278    }
00279 
00280    // Then I order the slices according to the value "dist". Finally, once
00281    // I've read in all the slices, I calculate the z-spacing as the difference
00282    // between the "dist" values for the first two slices.
00283    GdcmFileVector CoherentGdcmFileVector(n);
00284    // CoherentGdcmFileVector.reserve( n );
00285    CoherentGdcmFileVector.resize( n );
00286    // gdcmAssertMacro( CoherentGdcmFileVector.capacity() >= n );
00287 
00288    float step = (max - min)/(n - 1);
00289    int pos;
00290    n = 0;
00291     
00292    //VC++ don't understand what scope is !! it -> it2
00293    for (GdcmFileList::const_iterator it2  = fileList->begin();
00294         it2 != fileList->end(); ++it2, ++n)
00295    {
00296       //2*n sort algo !!
00297       //Assumption: all files are present (no one missing)
00298       pos = (int)( fabs( (distlist[n]-min)/step) + .5 );
00299 
00300       // a Dicom 'Serie' may contain scout views
00301       // and images may have differents directions
00302       // -> More than one may have the same 'pos'
00303       // Sorting has then NO meaning !
00304       if (CoherentGdcmFileVector[pos]==NULL)
00305          CoherentGdcmFileVector[pos] = *it2;
00306       else
00307       {
00308          gdcmWarningMacro( "2 files same position");
00309          return false;
00310       }
00311    }
00312 
00313    fileList->clear();  // doesn't delete list elements, only node
00314   
00315    //VC++ don't understand what scope is !! it -> it3
00316    for (GdcmFileVector::const_iterator it3  = CoherentGdcmFileVector.begin();
00317         it3 != CoherentGdcmFileVector.end(); ++it3)
00318    {
00319       fileList->push_back( *it3 );
00320    }
00321 
00322    distlist.clear();
00323    CoherentGdcmFileVector.clear();
00324 
00325    return true;
00326 }
00327 
00328 bool SerieHelper::ImageNumberLessThan(File *file1, File *file2)
00329 {
00330   return file1->GetImageNumber() < file2->GetImageNumber();
00331 }
00332 
00341 bool SerieHelper::ImageNumberOrdering(GdcmFileList *fileList) 
00342 {
00343    int min, max, pos;
00344    int n = fileList->size();
00345 
00346    GdcmFileList::const_iterator it = fileList->begin();
00347    min = max = (*it)->GetImageNumber();
00348 
00349    for (; it != fileList->end(); ++it, ++n)
00350    {
00351       pos = (*it)->GetImageNumber();
00352       min = (min < pos) ? min : pos;
00353       max = (max > pos) ? max : pos;
00354    }
00355 
00356    // Find out if image numbers are coherent (consecutive)
00357    if( min == max || max == 0 || max >= (n+min))
00358       return false;
00359 
00360    std::sort(fileList->begin(), fileList->end(), SerieHelper::ImageNumberLessThan );
00361 
00362    return true;
00363 }
00364 
00365 bool SerieHelper::FileNameLessThan(File *file1, File *file2)
00366 {
00367   return file1->GetFileName() < file2->GetFileName();
00368 }
00369 
00375 bool SerieHelper::FileNameOrdering(GdcmFileList *fileList)
00376 {
00377    std::sort(fileList->begin(), fileList->end(), SerieHelper::FileNameLessThan);
00378    return true;
00379 }
00380 
00381 //-----------------------------------------------------------------------------
00382 // Print
00386 void SerieHelper::Print(std::ostream &os, std::string const & indent)
00387 {
00388    // For all the Coherent File lists of the gdcm::Serie
00389    CoherentFileListmap::iterator itl = CoherentGdcmFileListHT.begin();
00390    if ( itl == CoherentGdcmFileListHT.end() )
00391    {
00392       gdcmWarningMacro( "No Coherent File list found" );
00393       return;
00394    }
00395    while (itl != CoherentGdcmFileListHT.end())
00396    { 
00397       os << "Serie UID :[" << itl->first << "]" << std::endl;
00398 
00399       // For all the files of a Coherent File list
00400       for (GdcmFileList::iterator it =  (itl->second)->begin();
00401                                   it != (itl->second)->end(); 
00402                                 ++it)
00403       {
00404          os << indent << " --- " << (*it)->GetFileName() << std::endl;
00405       }
00406       ++itl;
00407    }
00408 }
00409 
00410 //-----------------------------------------------------------------------------
00411 } // end namespace gdcm

Generated on Thu Feb 10 22:18:00 2005 for gdcm by doxygen 1.3.6