#ifndef __MDTOOLS_H #define __MDTOOLS_H #include "MdFile.h" #include "MdEvent.h" //#include "MdUtils.h" #include "IoSd.h" #include "HdTools.h" #include #include #include #include #include #include #include using namespace std; #define PRODVERSION "v1r0" /*Maximun filename size */ static const int MD_MAXFILENAMESIZE = 4096; /*Maximum and minimun time differences between T3s*/ static const int MD_MAXTIMEDIFF = 500; static const int MD_MINTIMEDIFF = 120; /* Root dir where files will be written */ static string MDMDIR("/srv/AMIGA/data/XProd/Mdm"); /* To control time */ volatile static bool keepTucking(true); class MdMergedEvent : public md::Event { public: MdMergedEvent(): fMerged( md::Event() ), fVerbose (0) {}; MdMergedEvent( const md::Event &evt, int v = 0 ) : fMerged( evt ), fVerbose ( v ) {}; //Operator ot merged events md::Event& operator+=( const md::Event & newEvt ){ md::ID id; md::Counter* newctr; md::Module * newmod; md::Event::ConstIterator ctrIt; md::Counter::ConstIterator modIt; md::Module::ConstRawIterator rawIt; ostringstream oss; //Loop over counters of the new event newEvt (to be added) ctrIt= newEvt.CountersBegin(); for( ; ctrIt != newEvt.CountersEnd(); ++ctrIt ){ oss.str(""); id = (*ctrIt)->GetId(); newctr = fMerged.HasCounter(id); //Check if the new event has counters not present in fMerged event //and if so, then create and add them. if ( !newctr ){ oss << "\nADDING COUNTER " << id << " AS NEW TO EVENT\n"; newctr = new md::Counter( **ctrIt ); fMerged.AddCounter( newctr ); } else { //if the counter is already present, then check if has same data oss << "\nCOUNTER " << id << " ALREADY PRESENT IN THIS EVENT\n"; //Loop on modules modIt = (*ctrIt)->ModulesBegin(); for ( ; modIt != (*ctrIt)->ModulesEnd(); ++modIt ){ id = (*modIt)->GetId(); newmod = newctr->HasModule( id ); if ( !newmod ) { oss << "ADDING MODULE " << id << " AS NEW TO COUNTER\n"; newmod = new md::Module( **modIt ); newctr->AddModule( *newmod ); } else { oss << "MODULE " << id << " ALREADY PRESENT IN THIS COUNTER\n"; oss << "CHECKING IF RAW DATA IS THE SAME\n"; rawIt = (*modIt)->RawSignalBegin();//signal of module in counter of the new event newEvt bool sameSignal = true; //For every time bin checks the sample of both events for ( ; rawIt != (*modIt)->RawSignalEnd(); ++rawIt ){ unsigned int time = (*rawIt)->GetTimeBin(); Long64_t s1 = (*rawIt)->GetSample();//retrieve sample of newEvt Long64_t s2 = newmod->GetSampleAt( time );//retrieve sample of fMerged /* oss << "timeBin " << time << " "; oss << "SampleNewEvt " << s1 << " "; oss << "SampleMerged " << s2 << " "; oss << endl; */ if( s1 != s2 ) sameSignal = false; }//end loop on raw data /* rawIt = newmod->RawSignalBegin();//signal of module in counter of the fMerged event for ( ; rawIt != newmod->RawSignalEnd(); ++rawIt ){ unsigned int time = (*rawIt)->GetTimeBin(); Long64_t s1 = (*rawIt)->GetSample();//retrieve sample of newEvt oss << "timeBin " << time << " "; oss << "SampleMerged " << s1 << " "; oss << endl; }//end loop on raw data */ if ( !sameSignal ){ // if not the same signal do something (keep the hottest one) oss << "NOT THE SAME SIGNAL BETWEEN MODULES!!\n"; size_t ss1 = (*modIt)->RawSamplesSize();//signal size of module in counter of the new event newEvt size_t ss2 = newmod ->RawSamplesSize();//signal size of module in counter of the fMerged event if ( ss1 > ss2 ){ oss << "ADDING RAW DATA OF HOTTEST MODULE\n"; //Clear colder data newmod->ClearRawSignal(); //Load hotter data rawIt = (*modIt)->RawSignalBegin();//signal of module in counter of the new event newEvt for ( ; rawIt != (*modIt)->RawSignalEnd(); ++rawIt ){ unsigned int time = (*rawIt)->GetTimeBin(); Long64_t s1 = (*rawIt)->GetSample();//retrieve sample of newEvt newmod->AddRawSample( time, s1 ); }//end for }//end if ss1 > ss2 } else { oss << "SAME SIGNAL BETWEEN MODULES... doing nothing\n"; } }//end if HasModule }//end loop on modules }//end if HasCounter if( fVerbose ) cout << oss.str(); }//end for counters loop return fMerged; }//end operator+= md::Event & GetMergedEvent() { return fMerged;} const md::Event & GetMergedEvent() const { return fMerged;} void LoadEvent( const md::Event &evt ) { fMerged = evt; } void SetVerbosity ( int v ) { fVerbose = v; } private: md::Event fMerged; int fVerbose; }; class MdT3 : public md::Trigger { public: //Ctors MdT3(): md::Trigger() { EvtId = 0; Id = 0; Date = ""; Time = 0; toMerge = 0; }; MdT3(const md::Trigger &trg, const md::ID evtId ) : md::Trigger( trg ) { EvtId = evtId; Id = trg.GetId(); Date = ""; Time = 0; toMerge = 0; }; /* MdT3& operator=( const MdT3 &right ) { EvtId = right.EvtId; Id = right.Id; Date = right.Date; Time = right.Time; toMerge = right.toMerge; }; */ bool operator <(const MdT3 &right) const { if (GetT3Sec() == right.GetT3Sec() && GetT3Mic() == right.GetT3Mic()) return (Id < right.Id); if(GetT3Sec() == right.GetT3Sec()) return (GetT3Mic() < right.GetT3Mic()); else return (GetT3Sec() < right.GetT3Sec()); }; bool operator >(const MdT3 &right) const { if(GetT3Sec() == right.GetT3Sec() && GetT3Mic() == right.GetT3Mic()) return (Id > right.Id); if(GetT3Sec() == right.GetT3Sec()) return (GetT3Mic() > right.GetT3Mic()); else return (GetT3Sec() > right.GetT3Sec()); }; bool operator <=(const MdT3 &right) const { if(GetT3Sec() == right.GetT3Sec()) return (GetT3Mic() <= right.GetT3Mic()); else return (GetT3Sec() <= right.GetT3Sec()); }; bool operator >=(const MdT3 &right) const { if(GetT3Sec() == right.GetT3Sec()) return (GetT3Mic() >= right.GetT3Mic()); else return (GetT3Sec() >= right.GetT3Sec()); }; bool Match(const IoSdT3Trigger &right) const { return ( (GetT3Sec() == right.Second) && (GetT3Mic() == right.MicroSecond) ); }; bool Match(const TEyeEventHeader &right) const { return ( (GetT3Sec() == right.GetT3TimeStamp()->GetSec()) && (GetT3Mic() == right.GetT3TimeStamp()->GetNanoSec()) ); }; void Dump (ostringstream& ostr) { ostr << GetT3Algorithm() << " T3 Time : "; ostr << fixed << setprecision(10) << GetT3Sec() << " (s) "; ostr << fixed << setprecision(10) << GetT3Mic() << " (us) "; ostr << " Id = " << Id; ostr << endl; } md::ID EvtId;///Id from Event (global among loaded files) md::ID Id;///T3 Id from Trigger std::string Date; time_t Time; int toMerge; }; class MdmT3 : public MdT3 { public: MdmT3(): MdT3() { toMatch = 0; }; MdmT3(const md::Trigger &trg, const md::ID evtId ) : MdT3( trg, evtId ) { toMatch = 0; }; /* MdmT3& operator=( const MdmT3 &right ) { toMatch = right.toMatch; }; */ void ToMatch () { toMatch++; } int Matched () {return toMatch;} private: int toMatch; }; /******************************************************/ /* Function declarations */ /******************************************************/ template inline void BuildT3List(md::File & input, std::vector &MdT3s, const int & verbose = 0); //Overload for Sd data void BuildT3List(IoSd & input, std::vector &SdT3s, const int & verbose = 0); template inline std::string SelectOutput(const T &T3, const int & verbose = 0, const std::string prefix = "mdm" ); void Dump( const md::Event & myEvt, ostringstream& ostr ); int CheckMdMismatched( std::vector MdT3s, std::string logFileName, int verbose ); void PrepareForMerge(std::vector &MdT3s, const int & verbose = 0); size_t Keep24Hours( std::vector &MdT3s, int day2merge ); bool FileExists(const std::string & fileName); void SetOut(std::string &fileName, const std::string &year, const std::string &month, const std::string &day, const int & verbose, const std::string prefix ); void _setFileName(string &res, const struct tm &ptms, const string & prefix = "" ); /******************************************************/ /* Template implementations shall be in headers files */ /******************************************************/ template inline void BuildT3List(md::File &input, std::vector &MdT3s, const int & verbose){ md::Event event; ostringstream oss; // prepare Md event list for time sort while ( input.ReadNext( event ) == md::File::eSuccess ) { if (event.GetTrigger().GetT3Sec() != 0) { oss.str(""); T t3(event.GetTrigger(), event.GetId() ); t3.Time = event.GetUTCtime(); t3.Date = event.GetUTCdate(); MdT3s.push_back( t3 ); oss << "cycle " << fixed << setprecision(6) << input.GetCycle() << " "; oss << "id " << fixed << setprecision(6) << event.GetId() << " "; t3.Dump( oss ); if ( verbose ) cout << oss.str(); } else { cerr << "***** Skipping event# "<< event.GetId() << " which is corrupted (gps=0)" << endl; } }//end while // sort Md event list in time sort(MdT3s.begin(), MdT3s.end()); return; } /** * Get correct time to create the file * @parm tm struct tm where the file-creation date is stored * @return unix timestamp of the date used to set the file name */ template inline void _getRotateTime(struct tm &tm, const T & T3, const int & verbose = 0){ time_t curTime = T3.Time; gmtime_r(&curTime, &tm); if ( verbose > 1 ) { cout << tm.tm_year+1900 << "/" ; cout << fixed << setprecision(2) << tm.tm_mon+1 << "/" ; cout << fixed << setprecision(2) << tm.tm_mday << " " ; cout << fixed << setprecision(2) << tm.tm_hour << ":" ; cout << fixed << setprecision(2) << tm.tm_min << ":" ; cout << fixed << setprecision(2) << tm.tm_sec << " " ; } if(tm.tm_hour < 12){ //Substracting 12 hours will always yield the previous day ;) curTime -= 12*3600; gmtime_r(&curTime, &tm); } tm.tm_hour = 12; tm.tm_min = 0; tm.tm_sec = 0; return; } template inline std::string SelectOutput(const T &T3, const int & verbose, const std::string prefix ){ //Think UTC setenv("TZ", "", 1); //Used to call _getRotateTime and _setFileName struct tm fileTime; string fileName; _getRotateTime(fileTime, T3, verbose ); _setFileName(fileName, fileTime, prefix ); if( verbose > 1 ) cout << fileName << endl; return fileName; } #endif