X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmSerieHeader.cxx;h=7158a0bf102548e83b3be1e27c59689d0f45ab98;hb=7350639601914cd8ab02bfb0d6668c5bf56ce2f4;hp=2bee2ffae739369ed6c40e325887fe01fd377410;hpb=c094e185dd6404df031524ccae8e1b51e3b84871;p=gdcm.git diff --git a/src/gdcmSerieHeader.cxx b/src/gdcmSerieHeader.cxx index 2bee2ffa..7158a0bf 100644 --- a/src/gdcmSerieHeader.cxx +++ b/src/gdcmSerieHeader.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSerieHeader.cxx,v $ Language: C++ - Date: $Date: 2005/01/21 11:40:55 $ - Version: $Revision: 1.12 $ + Date: $Date: 2005/02/01 11:02:27 $ + Version: $Revision: 1.20 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -27,35 +27,62 @@ namespace gdcm { - +typedef std::list GdcmFileList; typedef std::vector GdcmFileVector; + //----------------------------------------------------------------------------- // Constructor / Destructor +/** + * \brief Constructor from a given SerieHeader + */ SerieHeader::SerieHeader() { - CoherentGdcmFileList.clear(); - // Later will contain: 0020 000e UI REL Series Instance UID - CurrentSerieUID = ""; + // For all the File lists of the gdcm::Serie + GdcmFileList *l = GetFirstCoherentFileList(); + while (l) + { + // For all the files of a File list + for (GdcmFileList::iterator it = l->begin(); + it != l->end(); + ++it) + { + delete *it; + } + l->clear(); + delete l;; + l = GetNextCoherentFileList(); + } } +/** + * \brief Canonical destructor. + */ SerieHeader::~SerieHeader() { - /// \todo - for ( GdcmFileList::const_iterator it = CoherentGdcmFileList.begin(); - it != CoherentGdcmFileList.end(); ++it) - { - delete *it; + // For all the Coherent File lists of the gdcm::Serie + GdcmFileList *l = GetFirstCoherentFileList(); + while (l) + { + // For all the files of a Coherent File list + for (GdcmFileList::iterator it = l->begin(); + it != l->end(); + ++it) + { + delete *it; + } + l->clear(); + delete l; + l = GetNextCoherentFileList(); } - CoherentGdcmFileList.clear(); } //----------------------------------------------------------------------------- -// Print //----------------------------------------------------------------------------- + // Public /** - * \brief add a File to the list based on file name + * \brief add a gdcm::File to the list corresponding to its Serie UID * @param filename Name of the file to deal with */ void SerieHeader::AddFileName(std::string const &filename) @@ -65,23 +92,18 @@ void SerieHeader::AddFileName(std::string const &filename) if( header->IsReadable() ) { // 0020 000e UI REL Series Instance UID - std::string uid = header->GetEntry (0x0020, 0x000e); - // if uid == GDCM_UNFOUND then consistenly we should find GDCM_UNFOUND + std::string uid = header->GetEntryValue (0x0020, 0x000e); + // if uid == GDCM_UNFOUND then consistently we should find GDCM_UNFOUND // no need here to do anything special - if( CurrentSerieUID == "" ) - { - // Set the current one - CurrentSerieUID = uid; - } - if( CurrentSerieUID == uid ) - { - // Current Serie UID and DICOM header seems to match add the file: - CoherentGdcmFileList.push_back( header ); - } - else + + if ( CoherentGdcmFileListHT.count(uid) == 0 ) { - gdcmVerboseMacro("Wrong Serie Instance UID should be:" << CurrentSerieUID ); + gdcmVerboseMacro(" New Serie UID :[" << uid << "]"); + // create a std::list in 'uid' position + CoherentGdcmFileListHT[uid] = new GdcmFileList; } + // Current Serie UID and DICOM header seems to match add the file: + CoherentGdcmFileListHT[uid]->push_back( header ); } else { @@ -91,13 +113,13 @@ void SerieHeader::AddFileName(std::string const &filename) } /** - * \brief Sets the Directory + * \brief Sets the root Directory * @param dir Name of the directory to deal with + * @param recursive whether we want explore recursively the Directory */ -void SerieHeader::SetDirectory(std::string const &dir) +void SerieHeader::SetDirectory(std::string const &dir, bool recursive) { - CurrentSerieUID = ""; //Reset previous Serie Instance UID - DirList dirList(dir); //OS specific + DirList dirList(dir, recursive); // OS specific DirListType filenames_list = dirList.GetFilenames(); for( DirListType::const_iterator it = filenames_list.begin(); @@ -108,27 +130,68 @@ void SerieHeader::SetDirectory(std::string const &dir) } /** - * \brief Sorts the File List + * \brief Sorts the given File List * \warning This could be implemented in a 'Strategy Pattern' approach * But as I don't know how to do it, I leave it this way * BTW, this is also a Strategy, I don't know this is the best approach :) */ -void SerieHeader::OrderGdcmFileList() +void SerieHeader::OrderGdcmFileList(GdcmFileList *CoherentGdcmFileList) { - if( ImagePositionPatientOrdering() ) + if( ImagePositionPatientOrdering( CoherentGdcmFileList ) ) { return ; } - else if( ImageNumberOrdering() ) + else if( ImageNumberOrdering(CoherentGdcmFileList ) ) { return ; } else { - FileNameOrdering(); + FileNameOrdering(CoherentGdcmFileList ); } } +/** + * \brief Get the first List while visiting the CoherentFileListHT + * @return The first GdcmFileList if found, otherwhise NULL + */ + std::list *SerieHeader::GetFirstCoherentFileList() +// Why doesn't it compile ?!? +//GdcmFileList *SerieHeader::GetFirstCoherentFileList() +{ + ItListHt = CoherentGdcmFileListHT.begin(); + if( ItListHt != CoherentGdcmFileListHT.end() ) + return ItListHt->second; + return NULL; +} + +/** + * \brief Get the next List while visiting the CoherentFileListHT + * \note : meaningfull only if GetFirstCoherentFileList already called + * @return The next GdcmFileList if found, otherwhise NULL + */ +std::list *SerieHeader::GetNextCoherentFileList() +{ + gdcmAssertMacro (ItListHt != CoherentGdcmFileListHT.end()); + + ++ItListHt; + if ( ItListHt != CoherentGdcmFileListHT.end() ) + return ItListHt->second; + return NULL; +} + +/** + * \brief Get the Coherent Files list according to its Serie UID + * @param SerieUID SerieUID + * \return pointer to the Coherent Filseslist if found, otherwhise NULL + */ +GdcmFileList *SerieHeader::GetCoherentFileList(std::string SerieUID) +{ + if ( CoherentGdcmFileListHT.count(SerieUID) == 0 ) + return 0; + return CoherentGdcmFileListHT[SerieUID]; +} + //----------------------------------------------------------------------------- // Protected @@ -137,12 +200,14 @@ void SerieHeader::OrderGdcmFileList() /** * \brief sorts the images, according to their Patient Position * We may order, considering : - * -# Image Number * -# Image Position Patient - * -# More to come :) + * -# Image Number + * -# More to come :-) + * @param CoherentGdcmFileList Coherent File list (same Serie UID) to sort * @return false only if the header is bugged ! */ -bool SerieHeader::ImagePositionPatientOrdering() +bool SerieHeader::ImagePositionPatientOrdering( + GdcmFileList *CoherentGdcmFileList ) //based on Jolinda's algorithm { //iop is calculated based on the file file @@ -157,14 +222,14 @@ bool SerieHeader::ImagePositionPatientOrdering() //!\todo rewrite this for loop. for ( GdcmFileList::const_iterator - it = CoherentGdcmFileList.begin(); - it != CoherentGdcmFileList.end(); ++it ) + it = CoherentGdcmFileList->begin(); + it != CoherentGdcmFileList->end(); ++it ) { if( first ) { (*it)->GetImageOrientationPatient( cosines ); - //You only have to do this once for all slices in the volume. Next, + // You only have to do this once for all slices in the volume. Next, // for each slice, calculate the distance along the slice normal // using the IPP tag ("dist" is initialized to zero before reading // the first slice) : @@ -230,8 +295,8 @@ bool SerieHeader::ImagePositionPatientOrdering() n = 0; //VC++ don't understand what scope is !! it -> it2 - for (GdcmFileList::const_iterator it2 = CoherentGdcmFileList.begin(); - it2 != CoherentGdcmFileList.end(); ++it2, ++n) + for (GdcmFileList::const_iterator it2 = CoherentGdcmFileList->begin(); + it2 != CoherentGdcmFileList->end(); ++it2, ++n) { //2*n sort algo !! //Assumption: all files are present (no one missing) @@ -244,16 +309,19 @@ bool SerieHeader::ImagePositionPatientOrdering() if (CoherentGdcmFileVector[pos]==NULL) CoherentGdcmFileVector[pos] = *it2; else + { + gdcmVerboseMacro( "2 files same position"); return false; + } } - CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only + CoherentGdcmFileList->clear(); // doesn't delete list elements, only node //VC++ don't understand what scope is !! it -> it3 for (GdcmFileVector::const_iterator it3 = CoherentGdcmFileVector.begin(); it3 != CoherentGdcmFileVector.end(); ++it3) { - CoherentGdcmFileList.push_back( *it3 ); + CoherentGdcmFileList->push_back( *it3 ); } distlist.clear(); @@ -264,39 +332,40 @@ bool SerieHeader::ImagePositionPatientOrdering() /** * \brief sorts the images, according to their Image Number - * @return false only if the header is bugged ! + * \note Works only on bona fide files (i.e image number is a character string + * corresponding to an integer) + * within a bona fide serie (i.e image numbers are consecutive) + * @param CoherentGdcmFileList Coherent File list (same Serie UID) to sort + * @return false if non nona fide stuff encountered */ - -bool SerieHeader::ImageNumberOrdering() +bool SerieHeader::ImageNumberOrdering(GdcmFileList *CoherentGdcmFileList) { int min, max, pos; int n = 0;//CoherentGdcmFileList.size() is a O(N) operation unsigned char *partition; - GdcmFileList::const_iterator it = CoherentGdcmFileList.begin(); + GdcmFileList::const_iterator it = CoherentGdcmFileList->begin(); min = max = (*it)->GetImageNumber(); - for (; it != CoherentGdcmFileList.end(); ++it, ++n) + for (; it != CoherentGdcmFileList->end(); ++it, ++n) { pos = (*it)->GetImageNumber(); - - //else min = (min < pos) ? min : pos; max = (max > pos) ? max : pos; } - // Find out if sorting worked: - if( min == max || max == 0 || max > (n+min)) return false; + // Find out if image numbers are coherent (consecutive) + if( min == max || max == 0 || max >= (n+min)) + return false; - //bzeros(partition, n); //This function is deprecated, better use memset. partition = new unsigned char[n]; - memset(partition, 0, n); + memset(partition, 0, n); GdcmFileVector CoherentGdcmFileVector(n); - //VC++ don't understand what scope is !! it -> it2 - for (GdcmFileList::const_iterator it2 = CoherentGdcmFileList.begin(); - it2 != CoherentGdcmFileList.end(); ++it2) + //VC++ doesn't understand what scope is !! it -> it2 + for (GdcmFileList::const_iterator it2 = CoherentGdcmFileList->begin(); + it2 != CoherentGdcmFileList->end(); ++it2) { pos = (*it2)->GetImageNumber(); CoherentGdcmFileVector[pos - min] = *it2; @@ -309,31 +378,59 @@ bool SerieHeader::ImageNumberOrdering() mult *= partition[i]; } - //VC++ don't understand what scope is !! it -> it3 - CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only + //VC++ doesn't understand what scope is !! it -> it3 + CoherentGdcmFileList->clear(); // doesn't delete list elements, only nodes for ( GdcmFileVector::const_iterator it3 = CoherentGdcmFileVector.begin(); it3 != CoherentGdcmFileVector.end(); ++it3 ) { - CoherentGdcmFileList.push_back( *it3 ); + CoherentGdcmFileList->push_back( *it3 ); } - CoherentGdcmFileVector.clear(); - + CoherentGdcmFileVector.clear(); delete[] partition; return mult != 0; } - /** * \brief sorts the images, according to their File Name + * @param CoherentGdcmFileList Coherent File list (same Serie UID) to sort * @return false only if the header is bugged ! */ -bool SerieHeader::FileNameOrdering() +bool SerieHeader::FileNameOrdering(GdcmFileList *) { - //using the sort + //TODO using the sort //sort(CoherentGdcmFileList.begin(), CoherentGdcmFileList.end()); return true; } -} // end namespace gdcm //----------------------------------------------------------------------------- +// Print +/** + * \brief Canonical printer. + */ +void SerieHeader::Print() +{ + // For all the Coherent File lists of the gdcm::Serie + CoherentFileListmap::iterator itl = CoherentGdcmFileListHT.begin(); + if ( itl == CoherentGdcmFileListHT.end() ) + { + gdcmVerboseMacro( "No Coherent File list found" ); + return; + } + while (itl != CoherentGdcmFileListHT.end()) + { + std::cout << "Serie UID :[" << itl->first << "]" << std::endl; + + // For all the files of a Coherent File list + for (GdcmFileList::iterator it = (itl->second)->begin(); + it != (itl->second)->end(); + ++it) + { + std::cout << " --- " << (*it)->GetFileName() << std::endl; + } + ++itl; + } +} + +//----------------------------------------------------------------------------- +} // end namespace gdcm