X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmSerieHelper.cxx;h=3761252f910ed4e0294ac29afa763463654249b9;hb=7e9cd288c8f2138a56699721b33e572a6422d128;hp=5adbd99b1ffb1c8bea84c73f573438d71cc06f62;hpb=6b4aa7387613d98b62ee41d18aba2dbe0306b4ba;p=gdcm.git diff --git a/src/gdcmSerieHelper.cxx b/src/gdcmSerieHelper.cxx index 5adbd99b..3761252f 100644 --- a/src/gdcmSerieHelper.cxx +++ b/src/gdcmSerieHelper.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSerieHelper.cxx,v $ Language: C++ - Date: $Date: 2005/11/25 13:56:32 $ - Version: $Revision: 1.36 $ + Date: $Date: 2006/01/18 15:25:07 $ + Version: $Revision: 1.42 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -209,11 +209,13 @@ void SerieHelper::AddGdcmFile(File *header) } /** - * \brief add a rules for restricting a DICOM file to be in the serie we are - * trying to find. For example you can select only the DICOM file from a + * \brief add a rule for restricting a DICOM file to be in the serie we are + * trying to find. For example you can select only the DICOM files from a * directory which would have a particular EchoTime==4.0. * This method is a user level, value is not required to be formatted as a DICOM * string + * \todo find a trick to allow user to say if he wants the Rectrictions + * to be *ored* (and not only *anded*) * @param key Target tag we want restrict on a given value * @param value value to be checked to exclude File * @param op operator we want to use to check @@ -229,6 +231,47 @@ void SerieHelper::AddRestriction(TagKey const &key, ExRestrictions.push_back( r ); } +/** + * \brief add a rule for restricting a DICOM file to be in the serie we are + * trying to find. For example you can select only the DICOM file from a + * directory which would have a particular EchoTime==4.0. + * This method is a user level, value is not required to be formatted as a DICOM + * string + * \todo find a trick to allow user if he wants the Rectrictions to be *ored* + * (and not only *anded*) + * @param group tag group number we want restrict on a given value + * @param elem tag element number we want restrict on a given value + * @param value value to be checked to exclude File + * @param op operator we want to use to check + */ +void SerieHelper::AddRestriction(uint16_t group, uint16_t elem, + std::string const &value, int op) +{ + ExRule r; + r.group = group; + r.elem = elem; + r.value = value; + r.op = op; + ExRestrictions.push_back( r ); +} + +/** + * \brief add an extra 'SerieDetail' for building a 'Serie Identifier' + * that ensures (hope so) File constistency (Series Instance UID doesn't. + * @param group tag group number we want restrict on a given value + * @param elem tag element number we want restrict on a given value + * @param convert wether we want 'convertion', to allow further ordering + * e.g : 100 would be *before* 20; 000020.00 vs 00100.00 : OK + */ +void SerieHelper::AddSeriesDetail(uint16_t group, uint16_t elem, bool convert) +{ + + ExDetail d; + d.group = group; + d.elem = elem; + d.convert = convert; + ExDetails.push_back( d ); +} /** * \brief Sets the root Directory * @param dir Name of the directory to deal with @@ -391,7 +434,7 @@ XCoherentFileSetmap SerieHelper::SplitOnOrientation(FileList *fileSet) int nb = fileSet->size(); if (nb == 0 ) return CoherentFileSet; - double iop[6]; + float iop[6]; std::string strOrient; std::ostringstream ossOrient; @@ -568,7 +611,7 @@ bool SerieHelper::ImagePositionPatientOrdering( FileList *fileList ) //based on Jolinda Smith's algorithm { //iop is calculated based on the file file - double cosines[6]; + float cosines[6]; double normal[3]; double ipp[3]; double dist; @@ -725,11 +768,13 @@ bool SerieHelper::ImageNumberOrdering(FileList *fileList) return false; } if (DirectOrder) - std::sort(fileList->begin(), fileList->end(), - SerieHelper::ImageNumberLessThan ); + Sort(fileList,SerieHelper::ImageNumberLessThan); +// std::sort(fileList->begin(), fileList->end(), +// SerieHelper::ImageNumberLessThan ); else - std::sort(fileList->begin(), fileList->end(), - SerieHelper::ImageNumberGreaterThan ); + Sort(fileList,SerieHelper::ImageNumberGreaterThan); +// std::sort(fileList->begin(), fileList->end(), +// SerieHelper::ImageNumberGreaterThan ); return true; } @@ -751,11 +796,13 @@ bool SerieHelper::FileNameGreaterThan(File *file1, File *file2) bool SerieHelper::FileNameOrdering(FileList *fileList) { if (DirectOrder) - std::sort(fileList->begin(), fileList->end(), - SerieHelper::FileNameLessThan); + Sort(fileList,SerieHelper::FileNameLessThan); +// std::sort(fileList->begin(), fileList->end(), +// SerieHelper::FileNameLessThan); else - std::sort(fileList->begin(), fileList->end(), - SerieHelper::FileNameGreaterThan); + Sort(fileList,SerieHelper::FileNameGreaterThan); +// std::sort(fileList->begin(), fileList->end(), +// SerieHelper::FileNameGreaterThan); return true; } @@ -767,8 +814,9 @@ bool SerieHelper::FileNameOrdering(FileList *fileList) */ bool SerieHelper::UserOrdering(FileList *fileList) { - std::sort(fileList->begin(), fileList->end(), - SerieHelper::UserLessThanFunction); + Sort(fileList,SerieHelper::UserLessThanFunction); +// std::sort(fileList->begin(), fileList->end(), +// SerieHelper::UserLessThanFunction); if (!DirectOrder) { std::reverse(fileList->begin(), fileList->end()); @@ -776,7 +824,20 @@ bool SerieHelper::UserOrdering(FileList *fileList) return true; } -std::string SerieHelper::CreateUniqueSeriesIdentifier( File * inFile ) +/** + * \brief Heuristics to *try* to build a Serie Identifier that would ensure + * all the images are coherent. + * + * By default, uses the SeriesUID. If UseSeriesDetails(true) has been called, + * then additional identifying information is used. + * We allow user to add his own critierions, using AddSeriesDetail + * (he knows more than we do about his images!) + * ex : in tagging series, the only pertnent tag is + * 0018|1312 [In-plane Phase Encoding Direction] value : ROW/COLUMN + * @param inFile gdcm::File we want to build a Serie Identifier for. + * @return the SeriesIdentifier + */ +std::string SerieHelper::CreateUniqueSeriesIdentifier( File *inFile ) { if( inFile->IsReadable() ) { @@ -805,6 +866,10 @@ std::string SerieHelper::CreateUniqueSeriesIdentifier( File * inFile ) { sName = ""; } + + // You can think on checking Image Orientation (0020,0037), as well. + + // 0018 0050 Slice Thickness // On some CT systems, scout scans and subsequence volume scans will // have the same SeriesUID and Series Number - YET the slice @@ -830,25 +895,41 @@ std::string SerieHelper::CreateUniqueSeriesIdentifier( File * inFile ) { sColumns = ""; } - + // Concat the new info std::string num = sNum.c_str(); num += sName.c_str(); num += sThick.c_str(); num += sRows.c_str(); num += sColumns.c_str(); + + // Add a loop, here, to deal with any extra user supplied tag. + // We allow user to add his own critierions + // (he knows more than we do about his images!) + // ex : in tagging series, the only pertinent tag is + // 0018|1312 [In-plane Phase Encoding Direction] values : ROW/COLUMN + + std::string s; + for(SeriesExDetails::iterator it2 = ExDetails.begin(); + it2 != ExDetails.end(); + ++it2) + { + const ExDetail &r = *it2; + s = inFile->GetEntryString( r.group, r.elem ); + num += s.c_str(); + } // Append the new info to the SeriesUID id += "."; id += num.c_str(); } - // Eliminate non-alnum characters, including whitespace... + // Eliminate non-alphanum characters, including whitespace... // that may have been introduced by concats. for(unsigned int i=0; i= 'a' && id[i] <= 'z') || (id[i] >= '0' && id[i] <= '9') || (id[i] >= 'A' && id[i] <= 'Z'))) @@ -866,7 +947,61 @@ std::string SerieHelper::CreateUniqueSeriesIdentifier( File * inFile ) } } - +/** + * \brief Allow user to build is own File Identifier (to be able to sort + * temporal series just as he wants) + * Criterions will be set with AddSeriesDetail. + * (Maybe the method should be moved elsewhere + * -File class? FileHelper class?- + * @return FileIdentifier (Tokenizable on '_') + */ +std::string SerieHelper::CreateUserDefinedFileIdentifier( File * inFile ) +{ + // Deal with all user supplied tags. + // (user knows more than we do about his images!) + + float converted; + std::string id; + std::string s; + char charConverted[17]; + + for(SeriesExDetails::iterator it2 = ExDetails.begin(); + it2 != ExDetails.end(); + ++it2) + { + const ExDetail &r = *it2; + s = inFile->GetEntryString( r.group, r.elem ); + + // User is allowed to ask 'convertion', to allow further ordering + // e.g : 100 would be *before* 20; 000020.00 vs 00100.00 : OK + if (it2->convert) + { + converted = atof(s.c_str()); + // probabely something much more complicated is possible, + // using C++ features + /// \todo check the behaviour when there are >0 and <0 numbers + sprintf(charConverted, "%016.6f",converted); + s = charConverted; + } + // Eliminate non-alphanum characters, including whitespace. + for(unsigned int i=0; i= 'a' && s[i] <= 'z') + || (s[i] >= '0' && s[i] <= '9') + || (s[i] >= 'A' && s[i] <= 'Z'))) + { + s.erase(i, 1); + } + } + + id += s.c_str(); + id += "_"; // make the FileIdentifier Tokenizable + } + + return id; +} //----------------------------------------------------------------------------- // Print /** @@ -896,5 +1031,15 @@ void SerieHelper::Print(std::ostream &os, std::string const &indent) } } +//----------------------------------------------------------------------------- +// Sort +/** + * \brief Sort FileList. + */ +void SerieHelper::Sort(FileList *fileList, bool (*pt2Func)( File *file1, File *file2) ) +{ + std::sort(fileList->begin(), fileList->end(), pt2Func ); +} + //----------------------------------------------------------------------------- } // end namespace gdcm