/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Santé) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ // // C++ Implementation: brukerdataset // // Description: // // // Author: , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #define DEBUG 0 #include "brukerdataset.h" BrukerDataSet::BrukerDataSet(){} BrukerDataSet::~BrukerDataSet(){} bool BrukerDataSet::LoadFile(std::string fileToRead) { //std::cout << //"------------- BrukerDataSet::LoadFile() Open : [" << fileToRead << "]" << std::endl; std::ifstream FID; char * buffer; FID.open(fileToRead.c_str(), std::ios::binary); if (FID.rdstate()==std::ios::failbit) { //std::cout << "BrukerDataSet::LoadFile() Cannot open : [" << fileToRead << "]" << std::endl; return false; } FID.seekg (0, std::ios::end); int length = FID.tellg(); FID.seekg (0, std::ios::beg); buffer = new char [length]; FID.read (buffer,length); FID.close(); BrukerDataSet::WholeHeader=buffer; delete [] buffer; return true; } std::string BrukerDataSet::SearchBufferForText(std::string& file, const boost::regex& RegExp) { boost::cmatch what; if (regex_search(file.c_str(), what, RegExp)) return what[1]; return ""; } /** * * @param file * @param RegExp * @return bool */ bool BrukerDataSet::BoolMatchBufferForText(std::string& file, const boost::regex& RegExp) { boost::cmatch what; if (regex_match(file.c_str(), what, RegExp)) return true; return false; } std::string BrukerDataSet::RemoveNewlines(std::string file) { boost::regex regexNewline; const char* pre_expression = "[[:cntrl:]]"; regexNewline.assign(pre_expression); const char* pre_format = ""; std::ostringstream t(std::ios::out | std::ios::binary); std::ostream_iterator oi(t); boost::regex_replace(oi, file.begin(), file.end(), regexNewline, pre_format, boost::match_default | boost::format_all); std::string s(t.str()); return s; } std::string BrukerDataSet::RemoveSpaces(std::string file) { boost::regex regexSpace; const char* pre_expression = "[[:space:]]"; regexSpace.assign(pre_expression); const char* pre_format = ""; std::ostringstream t(std::ios::out | std::ios::binary); std::ostream_iterator oi(t); boost::regex_replace(oi, file.begin(), file.end(), regexSpace, pre_format, boost::match_default | boost::format_all); std::string s(t.str()); return s; } std::string BrukerDataSet::MatchBufferForText(std::string& file,const boost::regex& RegExp) { boost::cmatch what; if (regex_match(file.c_str(), what, RegExp)) return what[1]; return ""; } std::string BrukerDataSet::GetKeyword(std::string& file) { return MatchBufferForText( file,KeyWord); } int BrukerDataSet::GetDimensionnality(std::string& file) { int iterator=0; std::string DimensionnalityBuffer=SearchBufferForText(file,Dimensionnality); if (DimensionnalityBuffer=="") return iterator; boost::match_results what; boost::match_flag_type flags= boost::match_default; std::string::const_iterator start,end; start=DimensionnalityBuffer.begin(); end=DimensionnalityBuffer.end(); while (regex_search(start, end, what, UnsignedInteger)) { iterator++; start=what[0].second; flags |= boost::match_prev_avail; flags |= boost::match_not_bob; } return iterator; } int BrukerDataSet::GetIntValueOfDimN(std::string& file, int N) { int iterator=0; std::string DimensionnalityBuffer=SearchBufferForText(file,Dimensionnality); if (N < 1 || DimensionnalityBuffer=="") return 0; //std::cout << DimensionnalityBuffer << std::endl; boost::match_results what; boost::match_flag_type flags= boost::match_default; std::string::const_iterator start,end; start=DimensionnalityBuffer.begin(); end=DimensionnalityBuffer.end(); for (int i=1;i<=N;i++) { regex_search(start,end, what, UnsignedInteger); iterator++; start=what[0].second; flags |= boost::match_prev_avail; flags |= boost::match_not_bob; } return atoi(std::string(what[1].first,what[1].second).c_str()); } std::string BrukerDataSet::GetValuesPart(std::string& file) { std::string Result; Result=MatchBufferForText(file,BufferNValues); if (Result !="") return RemoveNewlines(Result); return MatchBufferForText(file,Buffer1Value); } std::string BrukerDataSet::GetContentType(std::string& file) { std::string ValuesPart; boost::match_flag_type flags = boost::match_default; std::string::const_iterator start, end; ValuesPart=GetValuesPart(file); start=ValuesPart.begin(); end=ValuesPart.end(); // boost regexp_match can not handle well what we want // so instead of looking for a match we will seek proof of a non int serie // i.e. check if we can find something else than than -0-9 boost::regex isNotIntSerie("[^ \\-0-9]"); boost::match_results whatInt; if (!regex_search(start,end, whatInt, isNotIntSerie,flags)) return "int"; // if not int serie check if it's not a floats serie !!! boost::regex isNotFloatSerie("[^ \\-\\+\\.eE0-9]"); boost::match_results whatFloat; if (!regex_search(start,end, whatFloat, isNotFloatSerie,flags)) return "float"; // if not a float serie neither, it's a string !!! return "string"; } int BrukerDataSet::GetIntValueN(std::string& file,int N) { std::string ValuesPart=GetValuesPart(file); int iterator=0; if (N < 1 || ValuesPart=="") return -32767; boost::match_results what; boost::match_flag_type flags= boost::match_default; std::string::const_iterator start,end; start=ValuesPart.begin(); end=ValuesPart.end(); while (iterator != N) { regex_search(start,end, what, SignedInteger); iterator++; start=what[0].second; flags |= boost::match_prev_avail; flags |= boost::match_not_bob; } return (atoi((std::string(what[1].first,what[1].second)).c_str())); } double BrukerDataSet::GetDoubleValueN(std::string& file, int N) { std::string ValuesPart=GetValuesPart(file); int iterator=0; if (N < 1 || ValuesPart=="") return 0; boost::match_results what; boost::match_flag_type flags= boost::match_default; std::string::const_iterator start,end; start=ValuesPart.begin(); end=ValuesPart.end(); while (iterator != N) { regex_search(start,end, what, IntOrFloat); iterator++; start=what[0].second; flags |= boost::match_prev_avail; flags |= boost::match_not_bob; } return (atof((std::string(what[1].first,what[1].second)).c_str())); } std::string BrukerDataSet::GetTextValueN(std::string& file, int N) { return GetValuesPart(file); } int BrukerDataSet::GetKeywordNumberOfElements(std::string& file) { int NumberOfElements=1; for (int i=1;i<=GetDimensionnality(file);i++) NumberOfElements*=GetIntValueOfDimN(file, i); return NumberOfElements; } /** * @fn bool BrukerDataSet::FillMap() @brief This method fills the Bruker headermap with everything contained in the acqp file The map is made of BrukerFieldData containing the keywords: Datatype (string, int, double) DimensionNumber: The number of Dimensions of the keyword-> 0 scalar, 1-> 1D-vector, 2-> 2D-Matrix, 3->3D-Matrix, ... DimensionNumberValue: Gives the size of each dimension DoubleValue: return a vector of values if they are of type double IntValue: return a vector of values if they are of type int StringValue: return a string if the values where not identified as a serie of numbers NumberOfElements: Number of elements corresponding to the keyword given * @return bool */ bool BrukerDataSet::FillMap() { std::string ValuesBuffer, Keyword,TempString, Substring; int i; int KeywordNumber=0; int PositionDebut=WholeHeader.find("##"); int PositionFin=PositionDebut+2; int PosRel; BrukerFieldData data; if (PositionFin>=WholeHeader.length()) return false; while(PositionDebut!=std::string::npos) { PositionFin=WholeHeader.find("##",PositionDebut+2); if (-1 == PositionFin) break ; Substring=WholeHeader.substr (PositionDebut,PositionFin-PositionDebut-1); PosRel=Substring.find("$$",0); if (-1 != PosRel) Substring=Substring.substr (0,PosRel-1); if (DEBUG) std::cout<<"Substring=[" << Substring << "]" < BrukerDataSet::GetLoopStructure() const { return LoopStructure; } /** @fn bool BrukerDataSet::SetLoopStructure (const std::vector & theValue ) * @brief this methods provide a way to inject a userdefined loop structure, be very aware that this method is not foolproof * @param theValue * @return bool */ bool BrukerDataSet::SetLoopStructure ( const std::vector & theValue ) { LoopStructure = theValue; return true; } /** @fn bool BrukerDataSet::SetLoopStructureOld ( ) * @brief method to set the default Bruker loopstructure (not yet able to deal with EPI, SPIRAL or spectroscopic experiments * @return bool * @todo implement multicoil version */ bool BrukerDataSet::SetLoopStructureOld () { LoopStructure.clear(); /* \file brukerdataset.cpp \fn bool BrukerDataSet::setGenericLoopStructure ( ) \brief sets the loop structure of a standard Bruker experiment NR (Nbre de repetitions) NILoop (Boucle eventuelle extra (Diffusion par exemple) si NI<>(NSLICES x NECHOES) cette boucle est a� NI/(NSLICES x NECHOES) (Attention NILoop peut masquer plusieurs boucles imbriquees !!!!!) ACQ_size[1..M] (Codage suivant les autres dimensions) NSLICES (Nombre de tranches) ACQ_phase_factor (Facteur turbo de la sequence) ACQ_ns_list_size (Nombre d'echos) ACQ_size[0] (Ligne acq reelle) */ std::string NRStr("NR"); std::string NIStr("NI"); std::string ACQ_sizeStr("ACQ_size"); std::string ACQ_phase_factorStr("ACQ_phase_factor"); std::string ACQ_ns_listStr("ACQ_ns_list"); std::string ACQ_ns_list_sizeStr("ACQ_ns_list_size"); std::string NSLICESStr("NSLICES"); int i, temp; std::vector TempIntVect; TempIntVect.clear(); if (! CheckExistKeyword(NRStr)) return false; if (! CheckExistKeyword(NIStr)) return false; if (! CheckExistKeyword(ACQ_sizeStr)) return false; if (! CheckExistKeyword(ACQ_phase_factorStr))return false; if (! CheckExistKeyword(ACQ_ns_list_sizeStr))return false; if (! CheckExistKeyword(NSLICESStr)) return false; TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[0]); TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_ns_list_size"].IntValue[0]); TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "NSLICES"].IntValue[0]); if (1<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ){ TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[1]/BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); if (2<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ) { for(i=2;i<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber;i++) { TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[i]); } } } // Ici, boucles additionnelles si elles existent regroupees en une seule //temp=GetIntValueN(NIStr,1)/(GetIntValueN(NSLICESStr,1)*GetIntValueN(NECHOESStr,1)); temp=BrukerDataSet::BrukerHeaderMap[ (std::string) "NI" ].IntValue[0]/(BrukerDataSet::BrukerHeaderMap[ (std::string) "NSLICES" ].IntValue[0]*BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_ns_list_size" ].IntValue[0]); if (1 < temp) TempIntVect.push_back(temp); // fin des boucles cachees TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "NR" ].IntValue[0]); LoopStructure=TempIntVect; return true; } /** @fn bool BrukerDataSet::SetLoopStructure ( ) * @brief method to set the default Bruker loopstructure (not yet able to deal with EPI, SPIRAL or spectroscopic experiments * @return bool @todo implement multicoil version */ bool BrukerDataSet::SetLoopStructure (int dimension) { if (! SetInnerObjectLoopStructure(dimension)) return false; if (! SetOuterObjectLoopStructure(dimension)) return false; std::vector Inner=GetInnerObjectLoopStructure(); std::vector Outer=GetOuterObjectLoopStructure(); std::vector TmpVect; TmpVect=Inner; TmpVect.insert(TmpVect.end(),Outer.begin(),Outer.end()); LoopStructure=TmpVect; return true; } std::vector< std :: vector < int > > BrukerDataSet::GetBrukerObjectsLineList() const { return BrukerObjectsLineList; } bool BrukerDataSet::SetBrukerObjectsLineList () { std::vector Loop =GetLoopStructure(); int NumberOfLines, i,j; NumberOfLines=1; i=1; while (i TempVect (Loop.size()-1,0); std::vector k (Loop.size()-1,0); std::vector > TempLineList (NumberOfLines,TempVect); for (i=0;i= Loop[j]) { k[j-1]=0; k[j]++; } } for (j=1;j<=Loop.size()-1;j++) TempLineList[i][j-1]=k[j-1]; k[0]++; } BrukerObjectsLineList=TempLineList; return true; } std::vector< std::vector < int > > BrukerDataSet::GetBrukerImageList() const { return BrukerImageList; } bool BrukerDataSet::SetBrukerImageList () { if (LoopStructure.size()==0) SetImageLoopStructure(); std::vector Loop =GetImageLoopStructure(); int NumberOfLines, i,j; NumberOfLines=1; i=1; while (i TempVect (Loop.size()-1,0); std::vector k (Loop.size()-1,0); std::vector > TempLineList (NumberOfLines,TempVect); for (i=0;i= Loop[j]) { k[j-1]=0; k[j]++; } } for (j=1;j<=Loop.size()-1;j++) TempLineList[i][j-1]=k[j-1]; k[0]++; } BrukerImageList=TempLineList; return true; } std::map BrukerDataSet::GetBrukerHeaderMap() const { return BrukerHeaderMap; } //std::map BrukerDataSet::GetBrukerHeaderMap() const //{ // return BrukerHeaderMap; //} bool BrukerDataSet::SetInnerObjectLoopStructure(int dimension) { /* * * * ACQ_size[1..M] (Codage suivant les autres dimensions) NSLICES (Nombre de tranches) ACQ_phase_factor (Facteur turbo de la sequence) ACQ_ns_list_size (Nombre d'echos) ACQ_size[0] (Ligne acq reelle) */ int i, temp; std::vector TempIntVect; TempIntVect.clear(); if (! CheckExistKeyword("ACQ_size")) return false; if (! CheckExistKeyword("ACQ_phase_factor"))return false; if (! CheckExistKeyword("ACQ_ns_list_size"))return false; if (! CheckExistKeyword("NSLICES")) return false; //std::cout<< "BrukerDataSet::BrukerHeaderMap[ (std::string) ACQ_size ].IntValue[0]" < 1) TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "NSLICES"].IntValue[0]); //std::cout << "BrukerDataSet::BrukerHeaderMap[(std::string) NSLICES].IntValue[0]" << BrukerDataSet::BrukerHeaderMap[(std::string) "NSLICES"].IntValue[0] << std::endl; if (1<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ) { if(dimension == 1) TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[0]/BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); else TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[1]/BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); //std::cout << "BrukerDataSet::BrukerHeaderMap[ (std::string) ACQ_size ].IntValue[1]/BrukerDataSet::BrukerHeaderMap[(std::string) ACQ_phase_factor].IntValue[0]" << BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" //].IntValue[1]/BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0] << std::endl; if (2<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ) { for(i=2;i<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber;i++) { TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[i]); } } } InnerObjectLoopStructure=TempIntVect; return true; } std::vector< int > BrukerDataSet::GetInnerObjectLoopStructure() const { return InnerObjectLoopStructure; } std::vector< int > BrukerDataSet::GetOuterObjectLoopStructure() const { return OuterObjectLoopStructure; } bool BrukerDataSet::SetOuterObjectLoopStructure (int dimension) { OuterObjectLoopStructure.clear(); /* NR (Nbre de repetitions) NILoop (Boucle eventuelle extra (Diffusion par exemple) si NI<>(NSLICES x NECHOES) cette boucle est a� NI/(NSLICES x NECHOES) (Attention NILoop peut masquer plusieurs boucles imbriquees !!!!!) */ int temp; std::vector TempIntVect; TempIntVect.clear(); if (! CheckExistKeyword("NR")) return false; if (! CheckExistKeyword("NI")) return false; // Ici, boucles additionnelles si elles existent regroupees en une seule //temp=GetIntValueN(NIStr,1)/(GetIntValueN(NSLICESStr,1)*GetIntValueN(NECHOESStr,1)); if(dimension ==1) temp=BrukerDataSet::BrukerHeaderMap[ (std::string) "NI" ].IntValue[0]/(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_ns_list_size" ].IntValue[0]); else temp=BrukerDataSet::BrukerHeaderMap[ (std::string) "NI" ].IntValue[0]/(BrukerDataSet::BrukerHeaderMap[ (std::string) "NSLICES" ].IntValue[0]*BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_ns_list_size" ].IntValue[0]); if (1 < temp) TempIntVect.push_back(temp); // fin des boucles cachees TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "NR" ].IntValue[0]); OuterObjectLoopStructure=TempIntVect; return true; } std::vector< int > BrukerDataSet::GetImageLoopStructure() const { return ImageLoopStructure; } bool BrukerDataSet::SetImageLoopStructure ( ) { ImageLoopStructure.clear(); std::vector TempIntVect1=GetInnerObjectLoopStructure(); std::vector TempIntVect2=GetOuterObjectLoopStructure(); std::vector TempIntVect3(TempIntVect1.size(),1); std::vector TempIntVect4; TempIntVect3[1]=TempIntVect1[1]; TempIntVect3[3]=TempIntVect1[3]; TempIntVect4=TempIntVect3; TempIntVect4.insert(TempIntVect4.end(),TempIntVect2.begin(),TempIntVect2.end()); ImageLoopStructure = TempIntVect4; return true; }