diff --git a/fles/mcbm2018/CMakeLists.txt b/fles/mcbm2018/CMakeLists.txt index 5bdf6aca6523d969415c01d6a73d71bb97b36bff..5a975a8e91ddf7d125fe57dd6656720c27ff678b 100644 --- a/fles/mcbm2018/CMakeLists.txt +++ b/fles/mcbm2018/CMakeLists.txt @@ -130,6 +130,9 @@ Set(SRCS tasks/CbmMcbmCheckTimingAlgo.cxx tasks/CbmMcbmCheckTimingTask.cxx + + tasks/CbmMcbmSpillFindAlgo.cxx + tasks/CbmMcbmSpillFindTask.cxx ) If(_UINT8_T_EXIST) diff --git a/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h b/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h index c19aaf4e36d19a6f48d9eb5c3c9d915406fee443..f4570ee2e4ebcbf358d397228b897b9610758711 100644 --- a/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h +++ b/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h @@ -77,4 +77,7 @@ #pragma link C++ class CbmMcbmCheckTimingAlgo + ; #pragma link C++ class CbmMcbmCheckTimingTask + ; +#pragma link C++ class CbmMcbmSpillFindAlgo + ; +#pragma link C++ class CbmMcbmSpillFindTask + ; + #endif diff --git a/fles/mcbm2018/CbmMcbm2018Source.cxx b/fles/mcbm2018/CbmMcbm2018Source.cxx index 0db535ca17644197346095a646ebb37164b7605d..d7619d28b56c16149f036a1a379d4eabd80ef707 100644 --- a/fles/mcbm2018/CbmMcbm2018Source.cxx +++ b/fles/mcbm2018/CbmMcbm2018Source.cxx @@ -117,6 +117,76 @@ Bool_t CbmMcbm2018Source::Init() { fTimeSliceMetaDataArray, fbWriteOutput); + /// Single spill unpacking + if (0 <= fiUnpSpillIdxStart) + { + switch( fuFlagSpillStart ) + { + case 0: + { + /// 0 = Break begin + if( fvuSpillBreakBegTs.size() - 1 <= fiUnpSpillIdxStop ) + { + LOG(warning) << "Chosen last spill index larger than spills contained in chosen spill start vector: " + << fiUnpSpillIdxStop << " VS " << fvuSpillBreakBegTs.size() - 1; + if( fiUnpSpillIdxStart < fvuSpillBreakBegTs.size() - 1 ) + { + fiUnpSpillIdxStop = fvuSpillBreakBegTs.size() - 2; + LOG(warning) << "Using last possible spill instead as final one"; + } // if( fiUnpSpillIdxStart < fvuSpillBreakBegTs.size() - 1 ) + else LOG(fatal) << "Start index also too large, exiting"; + } // if( fvuSpillBreakBegTs.size() - 1 <= fiUnpSpillIdxStop ) + + fuSpillBegTs = fvuSpillBreakBegTs[ fiUnpSpillIdxStart ]; //! + fuSpillEndTs = fvuSpillBreakBegTs[ fiUnpSpillIdxStop + 1 ]; //! + break; + } + case 1: + { + /// 1 = Break middle + if( fvuSpillBreakMidTs.size() - 1 <= fiUnpSpillIdxStop ) + { + LOG(warning) << "Chosen last spill index larger than spills contained in chosen spill start vector: " + << fiUnpSpillIdxStop << " VS " << fvuSpillBreakMidTs.size() - 1; + if( fiUnpSpillIdxStart < fvuSpillBreakMidTs.size() - 1 ) + { + fiUnpSpillIdxStop = fvuSpillBreakMidTs.size() - 2; + LOG(warning) << "Using last possible spill instead as final one"; + } // if( fiUnpSpillIdxStart < fvuSpillBreakMidTs.size() - 1 ) + else LOG(fatal) << "Start index also too large, exiting"; + } // if( fvuSpillBreakMidTs.size() - 1 <= fiUnpSpillIdxStop ) + + fuSpillBegTs = fvuSpillBreakMidTs[ fiUnpSpillIdxStart ]; //! + fuSpillEndTs = fvuSpillBreakMidTs[ fiUnpSpillIdxStop + 1 ]; //! + break; + } + case 2: + { + /// 2 = Break end + if( fvuSpillBreakEndTs.size() - 1 <= fiUnpSpillIdxStop ) + { + LOG(warning) << "Chosen last spill index larger than spills contained in chosen spill start vector: " + << fiUnpSpillIdxStop << " VS " << fvuSpillBreakEndTs.size() - 1; + if( fiUnpSpillIdxStart < fvuSpillBreakEndTs.size() - 1 ) + { + fiUnpSpillIdxStop = fvuSpillBreakEndTs.size() - 2; + LOG(warning) << "Using last possible spill instead as final one"; + } // if( fiUnpSpillIdxStart < fvuSpillBreakEndTs.size() - 1 ) + else LOG(fatal) << "Start index also too large, exiting"; + } // if( fvuSpillBreakEndTs.size() - 1 <= fiUnpSpillIdxStop ) + + fuSpillBegTs = fvuSpillBreakEndTs[ fiUnpSpillIdxStart ]; //! + fuSpillEndTs = fvuSpillBreakEndTs[ fiUnpSpillIdxStop + 1 ]; //! + break; + } + default: + { + LOG(fatal) << "Unknown spill start point option: " << fuFlagSpillStart; + break; + } + } // switch( fuFlagSpillStart ) + } // if (0 <= fiUnpSpillIdxStart) + return kTRUE; } @@ -248,26 +318,22 @@ Int_t CbmMcbm2018Source::FillBuffer() { } // for( auto it = it_list.first; it != it_list.second; ++it ) } // else of if( it == fUnpackers.end() ) } // for (size_t c {0}; c < ts.num_components(); c++) - } // if( 1 == fTSCounter ) - /// Apply TS throttling as set by user (default = 1 => no throttling) - if (0 == tsIndex % fuTsReduction) { - for (auto itUnp = fUnpackersToRun.begin(); itUnp != fUnpackersToRun.end(); - ++itUnp) { - (*itUnp)->DoUnpack(ts, 0); - } // for( auto itUnp = fUnpackersToRun.begin(); itUnp != fUnpackersToRun.end(); ++ itUnp ) - } // if( 0 == tsIndex % fuTsReduction ) - - /// Save the TimeSlice meta-data for access by higher level tasks - if (fTSCounter == 1) { + /// Compute and store the timeslice and microslices properties auto nMsInTs = ts.num_core_microslices(); - if (nMsInTs > 1) { + if (nMsInTs > 2) { // This assumes that we have a component 0 and component independent ms/ts settings! - auto msDescA = ts.descriptor(0, 0); - auto msDescB = ts.descriptor(0, 1); + auto msDescA = ts.descriptor(0, 1); + auto msDescB = ts.descriptor(0, 2); auto msLength = msDescB.idx - msDescA.idx; fTSLength = msLength * nMsInTs; fTSOverlappLength = msLength * (ts.num_microslices(0) - nMsInTs); + LOG(info) + << "CbmMcbm2018Source::FillBuffer() - TS 1 - Calculated " + << "TimesliceMetaData information from microslices Metadata -> " + << "MS length found to be " << msLength << " ns, TS length " + << fTSLength << " ns, and TS overlap length " + << fTSOverlappLength << " ns"; } else { LOG(warning) << "CbmMcbm2018Source::FillBuffer() - TS 1 - Calculate " @@ -275,7 +341,32 @@ Int_t CbmMcbm2018Source::FillBuffer() { "TS duration can not be calculated with the given method. Hence, " "TimesliceMetaData duration values are filled with 0"; } - } + } // if( 1 == fTSCounter ) + + if (0 <= fiUnpSpillIdxStart ) + { + if (tsIndex < fuSpillBegTs) + { + /// Jump all TS until reaching the first TS in the spill we want to unpack + continue; + } // if (tsIndex < fuSpillBegTs) + else if(fuSpillEndTs <= tsIndex) + { + /// Stop when reaching the first TS in the next spill + return 1; + } // else if + } // if (0 <= fiUnpSpillIdxStart) + + + /// Apply TS throttling as set by user (default = 1 => no throttling) + if (0 == tsIndex % fuTsReduction) { + for (auto itUnp = fUnpackersToRun.begin(); itUnp != fUnpackersToRun.end(); + ++itUnp) { + (*itUnp)->DoUnpack(ts, 0); + } // for( auto itUnp = fUnpackersToRun.begin(); itUnp != fUnpackersToRun.end(); ++ itUnp ) + } // if( 0 == tsIndex % fuTsReduction ) + + /// Save the TimeSlice meta-data for access by higher level tasks new ((*fTimeSliceMetaDataArray)[fTimeSliceMetaDataArray->GetEntriesFast()]) TimesliceMetaData( ts.descriptor(0, 0).idx, fTSLength, fTSOverlappLength, tsIndex); diff --git a/fles/mcbm2018/CbmMcbm2018Source.h b/fles/mcbm2018/CbmMcbm2018Source.h index d0d7e394621d5fd8a32194ae86230a053ee8f856..9d89d04c999b7db6c7d84fdde0680ac78e460fdb 100644 --- a/fles/mcbm2018/CbmMcbm2018Source.h +++ b/fles/mcbm2018/CbmMcbm2018Source.h @@ -77,6 +77,28 @@ public: fuTsReduction = uTsReduction; } + void UnpackSingleSpill( Int_t uSpillIdx, UInt_t uSpillStart = 1 ) { + fiUnpSpillIdxStart = uSpillIdx; + fiUnpSpillIdxStop = uSpillIdx; + fuFlagSpillStart = uSpillStart; + } + + void UnpackSelectSpills( Int_t uSpillIdxStart, Int_t uSpillIdxStop, UInt_t uSpillStart = 1 ) { + fiUnpSpillIdxStart = uSpillIdxStart; + fiUnpSpillIdxStop = uSpillIdxStop; + fuFlagSpillStart = uSpillStart; + } + + void LoadTsListSpillBreakBegin( std::vector< ULong64_t > vTsBeg ) { + fvuSpillBreakBegTs.assign( vTsBeg.begin(), vTsBeg.end() ); + } + void LoadTsListSpillBreakEnd( std::vector< ULong64_t > vTsEnd ) { + fvuSpillBreakEndTs.assign( vTsEnd.begin(), vTsEnd.end() ); + } + void LoadTsListSpillBreakMiddle( std::vector< ULong64_t > vTsMid ) { + fvuSpillBreakMidTs.assign( vTsMid.begin(), vTsMid.end() ); + } + void SetSubscriberHwm(UInt_t val = 1) { fuSubscriberHwm = val; } void SetWriteOutputFlag(Bool_t bFlagIn) { fbWriteOutput = bFlagIn; } @@ -105,6 +127,16 @@ private: UInt_t fuTsReduction; + Int_t fiUnpSpillIdxStart = -1; //! >= 0 means unpack only from this spill + Int_t fiUnpSpillIdxStop = -1; //! >= 0 means unpack only up to this spill (included) + UInt_t fuFlagSpillStart = 0; //! 0 = Break begin, 1 = Break middle, 2 = Break end + UInt_t fuSpillBegTs = 0; //! + UInt_t fuSpillEndTs = 0; //! + + std::vector< ULong64_t > fvuSpillBreakBegTs = {}; //! + std::vector< ULong64_t > fvuSpillBreakEndTs = {}; //! + std::vector< ULong64_t > fvuSpillBreakMidTs = {}; //! + std::unique_ptr<fles::TimesliceSource> fSource; //! UInt_t fuSubscriberHwm; diff --git a/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.cxx b/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.cxx new file mode 100644 index 0000000000000000000000000000000000000000..96a0e6f4d9e33f0a2a48ae773b3a14f92247812a --- /dev/null +++ b/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.cxx @@ -0,0 +1,511 @@ +// ----------------------------------------------------------------------------- +// ----- ----- +// ----- CbmMcbmSpillFindAlgo ----- +// ----- Created 10.02.2019 by P.-A. Loizeau ----- +// ----- ----- +// ----------------------------------------------------------------------------- + +#include "CbmMcbmSpillFindAlgo.h" + +#include "CbmFlesHistosTools.h" +#include "CbmFormatMsHeaderPrintout.h" +#include "CbmMcbm2018TofPar.h" +#include "CbmTofAddress.h" +#include "CbmTofDetectorId_v14a.h" // in cbmdata/tof + +#include "FairLogger.h" +#include "FairRootManager.h" +#include "FairRun.h" +#include "FairRunOnline.h" +#include "FairRuntimeDb.h" + +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TList.h" +#include "TPaveStats.h" +#include "TProfile.h" +#include "TROOT.h" +#include "TString.h" + +#include <fstream> +#include <iomanip> +#include <iostream> + +#include <stdint.h> + +// ------------------------------------------------------------------------- +CbmMcbmSpillFindAlgo::CbmMcbmSpillFindAlgo() : CbmStar2019Algo() {} +CbmMcbmSpillFindAlgo::~CbmMcbmSpillFindAlgo() +{ +} + +// ------------------------------------------------------------------------- +Bool_t CbmMcbmSpillFindAlgo::Init() +{ + LOG(info) << "Initializing mCBM T0 2019 monitor algo"; + + return kTRUE; +} +void CbmMcbmSpillFindAlgo::Reset() {} +void CbmMcbmSpillFindAlgo::Finish() +{ + /// If Spill is On, add a fake spill break to have the last spill + /// If Spill is Off, add a fake spill break end so that all modes include last spill + if (fbSpillOn) + { + fvuSpillBreakBegTs.push_back( fulCurrentTsIdx + 1 ); + fvuSpillBreakEndTs.push_back( fulCurrentTsIdx + 1 ); + } // if (fbSpillOn) + else fvuSpillBreakEndTs.push_back( fulCurrentTsIdx + 1 ); + + /// Fill the vector of spill break middle points + std::vector< ULong64_t >::iterator itBreakBeg = fvuSpillBreakBegTs.begin(); + std::vector< ULong64_t >::iterator itBreakEnd = fvuSpillBreakEndTs.begin(); + + if( itBreakBeg != fvuSpillBreakBegTs.end() && itBreakEnd != fvuSpillBreakEndTs.end() && *itBreakEnd < *itBreakBeg ) { + fvuSpillBreakMidTs.push_back((*itBreakEnd + fulFirstTsIdx) / 2); + ++itBreakEnd; + } // if( itBreakBeg != fvuSpillBreakBegTs.end() && itBreakEnd != fvuSpillBreakEndTs.end() && *itBreakEnd < *itBreakBeg ) + + while( itBreakBeg != fvuSpillBreakBegTs.end() && itBreakEnd != fvuSpillBreakEndTs.end() ) { + fvuSpillBreakMidTs.push_back((*itBreakBeg + *itBreakEnd) / 2); + ++itBreakBeg; + ++itBreakEnd; + } // while( itBreakBeg != fvuSpillBreakBegTs.end() && itBreakEnd != fvuSpillBreakEndTs.end() ) + + if( itBreakBeg != fvuSpillBreakBegTs.end() ) { + fvuSpillBreakMidTs.push_back((*itBreakBeg + fulCurrentTsIdx) / 2); + ++itBreakBeg; + } // if( itBreakBeg != fvuSpillBreakBegTs.end() ) + + if( itBreakBeg != fvuSpillBreakBegTs.end() || itBreakEnd != fvuSpillBreakEndTs.end() ) { + LOG(warning) << "Size of spill breaks beginning or end did not match: " + << fvuSpillBreakBegTs.size() << " VS " << fvuSpillBreakEndTs.size(); + } // if( itBreakBeg != fvuSpillBreakBegTs.end() || itBreakEnd != fvuSpillBreakEndTs.end() ) + + LOG(info) << "**********************************************"; + LOG(info) << "TS index for beginning of spill breaks:"; + for (ULong64_t uBeg : fvuSpillBreakBegTs) { + LOG(info)<< Form( "%9llu", uBeg ); + } // for (ULong64_t uBeg : fvuSpillBreakBegTs) + LOG(info) << "**********************************************"; + LOG(info) << "TS index for ending of spill breaks:"; + for (ULong64_t uEnd : fvuSpillBreakEndTs) { + LOG(info)<< Form( "%9llu", uEnd ); + } // for (ULong64_t uBeg : fvuSpillBreakBegTs) + LOG(info) << "**********************************************"; + LOG(info) << "TS index for middle of spill breaks:"; + for (ULong64_t uMid : fvuSpillBreakMidTs) { + LOG(info)<< Form( "%9llu", uMid ); + } // for (ULong64_t uBeg : fvuSpillBreakBegTs) + LOG(info) << "**********************************************"; + +} + +// ------------------------------------------------------------------------- +Bool_t CbmMcbmSpillFindAlgo::InitContainers() +{ + LOG(info) << "Init parameter containers for CbmMcbmSpillFindAlgo"; + Bool_t initOK = ReInitContainers(); + + return initOK; +} +Bool_t CbmMcbmSpillFindAlgo::ReInitContainers() +{ + LOG(info) << "**********************************************"; + LOG(info) << "ReInit parameter containers for CbmMcbmSpillFindAlgo"; + + fUnpackPar = (CbmMcbm2018TofPar*) fParCList->FindObject("CbmMcbm2018TofPar"); + if (nullptr == fUnpackPar) return kFALSE; + + Bool_t initOK = InitParameters(); + + return initOK; +} +TList* CbmMcbmSpillFindAlgo::GetParList() +{ + if (nullptr == fParCList) fParCList = new TList(); + fUnpackPar = new CbmMcbm2018TofPar("CbmMcbm2018TofPar"); + fParCList->Add(fUnpackPar); + + return fParCList; +} +Bool_t CbmMcbmSpillFindAlgo::InitParameters() +{ + + fuNrOfGdpbs = fUnpackPar->GetNrOfGdpbs(); + LOG(info) << "Nr. of Tof GDPBs: " << fuNrOfGdpbs; + + fuNrOfFeePerGdpb = fUnpackPar->GetNrOfFeesPerGdpb(); + LOG(info) << "Nr. of FEES per Tof GDPB: " << fuNrOfFeePerGdpb; + + fuNrOfGet4PerFee = fUnpackPar->GetNrOfGet4PerFee(); + LOG(info) << "Nr. of GET4 per Tof FEE: " << fuNrOfGet4PerFee; + + fuNrOfChannelsPerGet4 = fUnpackPar->GetNrOfChannelsPerGet4(); + LOG(info) << "Nr. of channels per GET4: " << fuNrOfChannelsPerGet4; + + fuNrOfChannelsPerFee = fuNrOfGet4PerFee * fuNrOfChannelsPerGet4; + LOG(info) << "Nr. of channels per FEE: " << fuNrOfChannelsPerFee; + + fuNrOfGet4 = fuNrOfGdpbs * fuNrOfFeePerGdpb * fuNrOfGet4PerFee; + LOG(info) << "Nr. of GET4s: " << fuNrOfGet4; + + fuNrOfGet4PerGdpb = fuNrOfFeePerGdpb * fuNrOfGet4PerFee; + LOG(info) << "Nr. of GET4s per GDPB: " << fuNrOfGet4PerGdpb; + + fuNrOfChannelsPerGdpb = fuNrOfGet4PerGdpb * fuNrOfChannelsPerGet4; + LOG(info) << "Nr. of channels per GDPB: " << fuNrOfChannelsPerGdpb; + + fGdpbIdIndexMap.clear(); + for (UInt_t i = 0; i < fuNrOfGdpbs; ++i) { + fGdpbIdIndexMap[fUnpackPar->GetGdpbId(i)] = i; + LOG(info) << "GDPB Id of TOF " << i << " : " << std::hex << fUnpackPar->GetGdpbId(i) << std::dec; + } // for( UInt_t i = 0; i < fuNrOfGdpbs; ++i ) + + return kTRUE; +} +// ------------------------------------------------------------------------- + +void CbmMcbmSpillFindAlgo::AddMsComponentToList(size_t component, UShort_t usDetectorId) +{ + /// Check for duplicates and ignore if it is the case + for (UInt_t uCompIdx = 0; uCompIdx < fvMsComponentsList.size(); ++uCompIdx) + if (component == fvMsComponentsList[uCompIdx]) return; + + /// Add to list + fvMsComponentsList.push_back(component); + + LOG(info) << "CbmMcbmSpillFindAlgo::AddMsComponentToList => Component " << component << " with detector ID 0x" + << std::hex << usDetectorId << std::dec << " added to list"; +} +// ------------------------------------------------------------------------- + +Bool_t CbmMcbmSpillFindAlgo::ProcessTs(const fles::Timeslice& ts) +{ + fulCurrentTsIdx = ts.index(); + fdTsStartTime = static_cast<Double_t>(ts.descriptor(0, 0).idx); + if( fulCurrentTsIdx < fulFirstTsIdx ) + fulFirstTsIdx = fulCurrentTsIdx; + + /// Ignore First TS as first MS is typically corrupt + if (0 == fulCurrentTsIdx) return kTRUE; + + /// On first TS, extract the TS parameters from header (by definition stable over time) + if (-1.0 == fdTsCoreSizeInNs) { + fuNbCoreMsPerTs = ts.num_core_microslices(); + fuNbOverMsPerTs = ts.num_microslices(0) - ts.num_core_microslices(); + fdTsCoreSizeInNs = fdMsSizeInNs * (fuNbCoreMsPerTs); + fdTsFullSizeInNs = fdMsSizeInNs * (fuNbCoreMsPerTs + fuNbOverMsPerTs); + LOG(info) << "Timeslice parameters: each TS has " << fuNbCoreMsPerTs << " Core MS and " << fuNbOverMsPerTs + << " Overlap MS, for a core duration of " << fdTsCoreSizeInNs << " ns and a full duration of " + << fdTsFullSizeInNs << " ns"; + + /// Ignore overlap ms if flag set by user + fuNbMsLoop = fuNbCoreMsPerTs; + if (kFALSE == fbIgnoreOverlapMs) fuNbMsLoop += fuNbOverMsPerTs; + LOG(info) << "In each TS " << fuNbMsLoop << " MS will be looped over"; + } // if( -1.0 == fdTsCoreSizeInNs ) + + /// Compute time of TS core end + fdTsStopTimeCore = fdTsStartTime + fdTsCoreSizeInNs; + // LOG(info) << Form( "TS %5d Start %12f Stop %12f", fulCurrentTsIdx, fdTsStartTime, fdTsStopTimeCore ); + + /// Loop over core microslices (and overlap ones if chosen) + for (fuMsIndex = 0; fuMsIndex < fuNbMsLoop; fuMsIndex++) { + /// Loop over registered components + for (UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx) { + UInt_t uMsComp = fvMsComponentsList[uMsCompIdx]; + + if (kFALSE == ProcessMs(ts, uMsComp, fuMsIndex)) { + LOG(error) << "Failed to process ts " << fulCurrentTsIdx << " MS " << fuMsIndex << " for component " << uMsComp; + return kFALSE; + } // if( kFALSE == ProcessMs( ts, uMsCompIdx, fuMsIndex ) ) + } // for( UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx ) + } // for( fuMsIndex = 0; fuMsIndex < uNbMsLoop; fuMsIndex ++ ) + + /// Fill plots if in monitor mode + if (fbMonitorMode) { + if (kFALSE == FillHistograms()) { + LOG(error) << "Failed to fill histos in ts " << fulCurrentTsIdx; + return kFALSE; + } // if( kFALSE == FillHistograms() ) + } // if( fbMonitorMode ) + + return kTRUE; +} + +Bool_t CbmMcbmSpillFindAlgo::ProcessMs(const fles::Timeslice& ts, size_t uMsCompIdx, size_t uMsIdx) +{ + auto msDescriptor = ts.descriptor(uMsCompIdx, uMsIdx); + fuCurrentEquipmentId = msDescriptor.eq_id; + const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts.content(uMsCompIdx, uMsIdx)); + + uint32_t uSize = msDescriptor.size; + fulCurrentMsIdx = msDescriptor.idx; + fdMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx); + LOG(debug) << "Microslice: " << fulCurrentMsIdx << " from EqId " << std::hex << fuCurrentEquipmentId << std::dec + << " has size: " << uSize; + + if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts.num_components(), kFALSE); + + fuCurrDpbId = static_cast<uint32_t>(fuCurrentEquipmentId & 0xFFFF); + + /* + * Should be only for first detected TS + */ + if (fulCurrentTsIdx < 10 && 0 == uMsIdx) { + LOG(INFO) << "---------------------------------------------------------------"; + LOG(INFO) << "Component " << uMsCompIdx << " TS Idx " << fulCurrentTsIdx; + LOG(INFO) << "hi hv eqid flag si sv idx/start crc size offset"; + LOG(INFO) << Form("%02x %02x %04x %04x %02x %02x %016lx %08x %08x %016lx", + static_cast<unsigned int>(msDescriptor.hdr_id), static_cast<unsigned int>(msDescriptor.hdr_ver), + msDescriptor.eq_id, msDescriptor.flags, static_cast<unsigned int>(msDescriptor.sys_id), + static_cast<unsigned int>(msDescriptor.sys_ver), static_cast<unsigned long>(msDescriptor.idx), + msDescriptor.crc, msDescriptor.size, static_cast<unsigned long>(msDescriptor.offset)); + } // if( fulCurrentTsIdx < 10 && 0 == uMsIdx ) + /* +*/ + + /// Check if this sDPB ID was declared in parameter file and stop there if not + auto it = fGdpbIdIndexMap.find(fuCurrDpbId); + if (it == fGdpbIdIndexMap.end()) { + if (kFALSE == fvbMaskedComponents[uMsCompIdx]) { + LOG(info) << "---------------------------------------------------------------"; + /* + LOG(info) << "hi hv eqid flag si sv idx/start crc size offset"; + LOG(info) << Form( "%02x %02x %04x %04x %02x %02x %016llx %08x %08x %016llx", + static_cast<unsigned int>(msDescriptor.hdr_id), + static_cast<unsigned int>(msDescriptor.hdr_ver), msDescriptor.eq_id, msDescriptor.flags, + static_cast<unsigned int>(msDescriptor.sys_id), + static_cast<unsigned int>(msDescriptor.sys_ver), msDescriptor.idx, msDescriptor.crc, + msDescriptor.size, msDescriptor.offset ); +*/ + LOG(info) << FormatMsHeaderPrintout(msDescriptor); + LOG(warning) << "Could not find the gDPB index for AFCK id 0x" << std::hex << fuCurrDpbId << std::dec + << " in timeslice " << fulCurrentTsIdx << " in microslice " << uMsIdx << " component " << uMsCompIdx + << "\n" + << "If valid this index has to be added in the TOF " + "parameter file in the DbpIdArray field"; + fvbMaskedComponents[uMsCompIdx] = kTRUE; + } // if( kFALSE == fvbMaskedComponents[ uMsComp ] ) + else + return kTRUE; + + /// Try to get it from the second message in buffer (first is epoch cycle without gDPB ID) + /// TODO!!!! + + return kFALSE; + } // if( it == fGdpbIdIndexMap.end() ) + else + fuCurrDpbIdx = fGdpbIdIndexMap[fuCurrDpbId]; + + /// Spill Detection + if (0 == fuCurrDpbIdx) { + /// Check only every user defined interval (0.5s per default) + if (fdSpillCheckInterval < fdMsTime - fdLastSecondTime) { + /// Spill Off detection + if (fbSpillOn && fuCountsLastInterval < fuOffSpillCountLimit) { + fbSpillOn = kFALSE; + fuCurrentSpillIdx++; + fdStartTimeSpill = fdMsTime; + if( 0 < fvuSpillBreakBegTs.size() ) + { + fhSpillDuration->Fill( fulCurrentTsIdx - fvuSpillBreakBegTs.back() ); + } // if( 0 < fvuSpillBreakBegTs.size() ) + fvuSpillBreakBegTs.push_back( fulCurrentTsIdx ); + } // if( fbSpillOn && fuCountsLastInterval < fuOffSpillCountLimit ) + else if (!fbSpillOn && fuOffSpillCountLimit < fuCountsLastInterval) { + fbSpillOn = kTRUE; + if( 0 < fvuSpillBreakBegTs.size() ) + { + fhSpillBreakDuration->Fill( fuCurrentSpillIdx, fulCurrentTsIdx - fvuSpillBreakBegTs.back() ); + } // if( 0 < fvuSpillBreakBegTs.size() ) + if( 0 < fvuSpillBreakEndTs.size() ) + { + fhHitsPerSpill->Fill( fuCurrentSpillIdx, fuCountsLastSpill ); + fhSpillDuration->Fill( fuCurrentSpillIdx, fulCurrentTsIdx - fvuSpillBreakEndTs.back() ); + } // if( 0 < fvuSpillBreakEndTs.size() ) + fvuSpillBreakEndTs.push_back( fulCurrentTsIdx ); + fuCountsLastSpill = 0; + } // else if (fuOffSpillCountLimit < fuCountsLastInterval) + + fuCountsLastInterval = 0; + fdLastSecondTime = fdMsTime; + } // if( fdSpillCheckInterval < fdMsTime - fdLastSecondTime ) + } // if( 0 == fuCurrDpbIdx ) + + /// Save start time of first valid MS ) + if (fdStartTime < 0) fdStartTime = fdMsTime; + /// Reset the histograms if reached the end of the evolution histos range + else if (fuHistoryHistoSize < fdMsTime - fdStartTime) { + ResetHistograms(); + fdStartTime = fdMsTime; + } // else if( fuHistoryHistoSize < fdMsTime - fdStartTime ) + + // If not integer number of message in input buffer, print warning/error + if (0 != (uSize % kuBytesPerMessage)) + LOG(error) << "The input microslice buffer does NOT " + << "contain only complete nDPB messages!"; + + // Compute the number of complete messages in the input microslice buffer + uint32_t uNbMessages = (uSize - (uSize % kuBytesPerMessage)) / kuBytesPerMessage; + + // Prepare variables for the loop on contents + Int_t messageType = -111; + ULong64_t ulNbHitsTs = 0; + const uint64_t* pInBuff = reinterpret_cast<const uint64_t*>(msContent); + for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) { + // Fill message + uint64_t ulData = static_cast<uint64_t>(pInBuff[uIdx]); + + /// Catch the Epoch cycle block which is always the first 64b of the MS + if (0 == uIdx) { + continue; + } // if( 0 == uIdx ) + + gdpbv100::Message mess(ulData); + /// Get message type + messageType = mess.getMessageType(); + + fuGet4Id = mess.getGdpbGenChipId(); + fuGet4Nr = fuGet4Id / 2; + // UInt_t uChannelT0 = ( fuGet4Id < 32 ) ? ( fuGet4Id / 8 ) : (fuGet4Id / 8 - 1); /// December 2018 mapping + // UInt_t uChannelT0 = fuGet4Id / 2 + 4 * fuCurrDpbIdx; /// 2019 mapping with 320/640 Mb/s FW + + if (fuNrOfGet4PerGdpb <= fuGet4Id && !mess.isStarTrigger() && (gdpbv100::kuChipIdMergedEpoch != fuGet4Id)) + LOG(warning) << "Message with Get4 ID too high: " << fuGet4Id << " VS " << fuNrOfGet4PerGdpb + << " set in parameters."; + + switch (messageType) { + case gdpbv100::MSG_HIT: { + if (mess.getGdpbHitIs24b()) { + LOG(error) << "This event builder does not support 24b hit message!!!."; + continue; + } // if( getGdpbHitIs24b() ) + else { + /// Spill detection + + /// Do not fill the pulser hits to keep counts low for channel 0 + /// => Check channel != first GET4 per board + TOT + UInt_t uTot = mess.getGdpbHit32Tot(); + if (0 != fuGet4Nr || uTot < fuMinTotPulser || fuMaxTotPulser < uTot) { + fuCountsLastInterval++; + fuCountsLastSpill++; + ulNbHitsTs++; + } // if (0 != fuGet4Nr || uTot < fuMinTotPulser || fuMaxTotPulser < uTot) { + } // else of if( getGdpbHitIs24b() ) + break; + } // case gdpbv100::MSG_HIT: + case gdpbv100::MSG_EPOCH: { + break; + } // case gdpbv100::MSG_EPOCH: + case gdpbv100::MSG_SLOWC: { + break; + } // case gdpbv100::MSG_SLOWC: + case gdpbv100::MSG_SYST: { + break; + } // case gdpbv100::MSG_SYST: + case gdpbv100::MSG_STAR_TRI_A: + case gdpbv100::MSG_STAR_TRI_B: + case gdpbv100::MSG_STAR_TRI_C: + case gdpbv100::MSG_STAR_TRI_D: { + break; + } // case gdpbv100::MSG_STAR_TRI_A-D + default: + LOG(error) << "Message type " << std::hex << std::setw(2) << static_cast<uint16_t>(messageType) + << " not included in Get4 unpacker."; + } // switch( mess.getMessageType() ) + } // for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx ++) + fhHitsEvo->Fill( fdTsStartTime*1e-9, ulNbHitsTs ); + + /// Fill histograms + FillHistograms(); + + return kTRUE; +} +// ------------------------------------------------------------------------- +Bool_t CbmMcbmSpillFindAlgo::CreateHistograms() +{ + std::string sFolder = "SpillFinder"; + + LOG(info) << "create Histos for T0 monitoring "; + + /// Logarithmic bining + uint32_t iNbBinsLog = 0; + /// Parameters are NbDecadesLog, NbStepsDecade, NbSubStepsInStep + std::vector<double> dBinsLogVector = GenerateLogBinArray(4, 9, 1, iNbBinsLog); + double* dBinsLog = dBinsLogVector.data(); + // double * dBinsLog = GenerateLogBinArray( 4, 9, 1, iNbBinsLog ); + + /*******************************************************************/ + fhHitsEvo = new TH1I("hHitsEvo", "Hit count evo; Time [s]; Hits Count []", fuHistoryHistoSize * 50, 0., + fuHistoryHistoSize); + fhHitsPerSpill = new TH1I("hHitsPerSpill", "Hit count per spill; Spill; Hits Count []", 2000, 0., 2000); + fhSpillBreakDuration = new TH1I("hSpillBreakDuration", "Spill break duration; Spill; Duration [TS]", 2000, 0., 2000); + fhSpillDuration = new TH1I("hSpillDuration", "Spill duration; Spill; Duration [TS]", 2000, 0., 2000); + + /// Add pointers to the vector with all histo for access by steering class + AddHistoToVector(fhHitsEvo, sFolder); + AddHistoToVector(fhHitsPerSpill, sFolder); + AddHistoToVector(fhSpillBreakDuration, sFolder); + AddHistoToVector(fhSpillDuration, sFolder); + + /*******************************************************************/ + /// Cleanup array of log bins + // delete dBinsLog; + + /*******************************************************************/ + + /// Canvases + Double_t w = 10; + Double_t h = 10; + + /*******************************************************************/ +/* + /// Map of hits over T0 detector and same vs time in run + fcHitMaps = new TCanvas("cHitMaps", "Hit maps", w, h); + fcHitMaps->Divide(2); + + fcHitMaps->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhChannelMap->Draw(); + + fcHitMaps->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhHitMapEvo->Draw("colz"); + + AddCanvasToVector(fcHitMaps, "canvases"); +*/ + /*******************************************************************/ + + /*******************************************************************/ + + return kTRUE; +} +Bool_t CbmMcbmSpillFindAlgo::FillHistograms() +{ + + return kTRUE; +} +Bool_t CbmMcbmSpillFindAlgo::ResetHistograms(Bool_t bResetTime) +{ + fuCurrentSpillIdx = 0; + fhHitsEvo->Reset(); + fhHitsPerSpill->Reset(); + fhSpillBreakDuration->Reset(); + fhSpillDuration->Reset(); + + if (kTRUE == bResetTime) { + /// Also reset the Start time for the evolution plots! + fdStartTime = -1.0; + } // if( kTRUE == bResetTime ) + + return kTRUE; +} +// ------------------------------------------------------------------------- diff --git a/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.h b/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.h new file mode 100644 index 0000000000000000000000000000000000000000..21dcbca9bb12f5baa229c351e01b7309ebad7521 --- /dev/null +++ b/fles/mcbm2018/tasks/CbmMcbmSpillFindAlgo.h @@ -0,0 +1,163 @@ +// ----------------------------------------------------------------------------- +// ----- ----- +// ----- CbmMcbmSpillFindAlgo ----- +// ----- Created 10.02.2019 by P.-A. Loizeau ----- +// ----- ----- +// ----------------------------------------------------------------------------- + +#ifndef CbmMcbmSpillFindAlgo_H +#define CbmMcbmSpillFindAlgo_H + +#include "CbmStar2019Algo.h" + +// Data +#include "CbmTofDigi.h" + +#include "gDpbMessv100.h" + +// CbmRoot + +// C++11 +#include <chrono> + +// C/C++ +#include <map> +#include <vector> + +class CbmMcbm2018TofPar; +/* +class TCanvas; +class THttpServer; +*/ +class TH1; +class TH2; +class TProfile; + +class CbmMcbmSpillFindAlgo : public CbmStar2019Algo<CbmTofDigi> { +public: + CbmMcbmSpillFindAlgo(); + ~CbmMcbmSpillFindAlgo(); + + virtual Bool_t Init(); + virtual void Reset(); + virtual void Finish(); + + Bool_t InitContainers(); + Bool_t ReInitContainers(); + TList* GetParList(); + + Bool_t InitParameters(); + + Bool_t ProcessTs(const fles::Timeslice& ts); + Bool_t ProcessTs(const fles::Timeslice& ts, size_t /*component*/) { return ProcessTs(ts); } + Bool_t ProcessMs(const fles::Timeslice& ts, size_t uMsCompIdx, size_t uMsIdx); + + void AddMsComponentToList(size_t component, UShort_t usDetectorId); + + Bool_t CreateHistograms(); + Bool_t FillHistograms(); + Bool_t ResetHistograms(Bool_t bResetTime = kTRUE); + + inline void SetMonitorMode(Bool_t bFlagIn = kTRUE) { fbMonitorMode = bFlagIn; } + inline void SetHistoryHistoSize(UInt_t inHistorySizeSec = 1800) { fuHistoryHistoSize = inHistorySizeSec; } + inline void SetPulserTotLimits(UInt_t uMin, UInt_t uMax) + { + fuMinTotPulser = uMin; + fuMaxTotPulser = uMax; + } + inline void SetSpillThreshold(UInt_t uCntLimit) { fuOffSpillCountLimit = uCntLimit; } + inline void SetSpillCheckIntervalSec(Double_t dInterval) { fdSpillCheckInterval = dInterval; } + +private: + /// Control flags + Bool_t fbMonitorMode = kFALSE; //! Switch ON the filling of a minimal set of histograms + Bool_t fbDebugMonitorMode = kFALSE; //! Switch ON the filling of a additional set of histograms + std::vector<Bool_t> fvbMaskedComponents = {}; + + /// Settings from parameter file + CbmMcbm2018TofPar* fUnpackPar = nullptr; //! + /// Readout chain dimensions and mapping + UInt_t fuNrOfGdpbs = 0; //! Total number of GDPBs in the system + std::map<UInt_t, UInt_t> fGdpbIdIndexMap = {}; //! gDPB ID to index map + UInt_t fuNrOfFeePerGdpb = 0; //! Number of FEBs per GDPB + UInt_t fuNrOfGet4PerFee = 0; //! Number of GET4s per FEE + UInt_t fuNrOfChannelsPerGet4 = 0; //! Number of channels in each GET4 + UInt_t fuNrOfChannelsPerFee = 0; //! Number of channels in each FEE + UInt_t fuNrOfGet4 = 0; //! Total number of Get4 chips in the system + UInt_t fuNrOfGet4PerGdpb = 0; //! Number of GET4s per GDPB + UInt_t fuNrOfChannelsPerGdpb = 0; //! Number of channels per GDPB + + /// User settings: Data correction parameters + UInt_t fuMinTotPulser = 90; + UInt_t fuMaxTotPulser = 100; + UInt_t fuOffSpillCountLimit = 100; + Double_t fdSpillCheckInterval = 0.5; + + /// Constants + static const Int_t kiMaxNbFlibLinks = 32; + static const UInt_t kuBytesPerMessage = 8; + static const UInt_t kuNbChanDiamond = 8; + + /// Running indices + /// TS/MS info + ULong64_t fulFirstTsIdx = 9999999999999; //! First TS index, forward point set ~30 years... + ULong64_t fulCurrentTsIdx = 0; + ULong64_t fulCurrentMsIdx = 0; + Double_t fdTsStartTime = -1.0; //! Time in ns of current TS from the index of the first MS first component + Double_t fdTsStopTimeCore = + -1.0; //! End Time in ns of current TS Core from the index of the first MS first component + Double_t fdMsTime = -1.0; //! Start Time in ns of current MS from its index field in header + UInt_t fuMsIndex = 0; //! Index of current MS within the TS + /// Current data properties + std::map<gdpbv100::MessageTypes, UInt_t> fmMsgCounter = {}; + UInt_t fuCurrentEquipmentId = 0; //! Current equipment ID, tells from which DPB the current MS is originating + UInt_t fuCurrDpbId = 0; //! Temp holder until Current equipment ID is properly filled in MS + UInt_t fuCurrDpbIdx = 0; //! Index of the DPB from which the MS currently unpacked is coming + Int_t fiRunStartDateTimeSec = -1; //! Start of run time since "epoch" in s, for the plots with date as X axis + Int_t fiBinSizeDatePlots = -1; //! Bin size in s for the plots with date as X axis + UInt_t fuGet4Id = 0; //! running number (0 to fuNrOfGet4PerGdpb) of the Get4 chip of a unique GDPB for current message + UInt_t fuGet4Nr = 0; //! running number (0 to fuNrOfGet4) of the Get4 chip in the system for current message + + /// Starting state book-keeping + Double_t fdStartTime = -1.0; //! Time of first valid hit (epoch available), used as reference for evolution plots + Double_t fdStartTimeMsSz = 0.0; //! Time of first microslice, used as reference for evolution plots + std::chrono::steady_clock::time_point ftStartTimeUnix = std::chrono::steady_clock:: + now(); //! Time of run Start from UNIX system, used as reference for long evolution plots against reception time + + /// Spill detection + Bool_t fbSpillOn = kTRUE; + UInt_t fuCurrentSpillIdx = 0; + Double_t fdStartTimeSpill = -1.0; + Double_t fdLastSecondTime = -1.0; + UInt_t fuCountsLastInterval = 0; + UInt_t fuCountsLastSpill = 0; + std::vector< ULong64_t > fvuSpillBreakBegTs = {}; + std::vector< ULong64_t > fvuSpillBreakEndTs = {}; + std::vector< ULong64_t > fvuSpillBreakMidTs = {}; + + /// Histograms related variables + UInt_t fuHistoryHistoSize = 3600; /** Size in seconds of the evolution histograms **/ + + /// Histograms + TH1* fhHitsEvo = nullptr; + TH1* fhHitsPerSpill = nullptr; + TH1* fhSpillBreakDuration = nullptr; + TH1* fhSpillDuration = nullptr; + + /// Canvases + /* + TCanvas* fcSummary = nullptr; + TCanvas* fcHitMaps = nullptr; + TCanvas* fcGenCntsPerMs = nullptr; + TCanvas* fcSpillCounts = nullptr; + TCanvas* fcSpillCountsHori = nullptr; + TCanvas* fcSpillDpbCountsHori = nullptr; +*/ + + CbmMcbmSpillFindAlgo(const CbmMcbmSpillFindAlgo&); + CbmMcbmSpillFindAlgo operator=(const CbmMcbmSpillFindAlgo&); + + ClassDef(CbmMcbmSpillFindAlgo, 1) +}; + +#endif diff --git a/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.cxx b/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cd2548beb8da36dae8bd13f870da2f41847bd8e6 --- /dev/null +++ b/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.cxx @@ -0,0 +1,216 @@ +// ----------------------------------------------------------------------------- +// ----- ----- +// ----- CbmMcbmSpillFindTask ----- +// ----- Created 10.02.2019 by P.-A. Loizeau ----- +// ----- ----- +// ----------------------------------------------------------------------------- + +#include "CbmMcbmSpillFindTask.h" + +#include "CbmMcbm2018TofPar.h" +#include "CbmMcbmSpillFindAlgo.h" + +#include "FairLogger.h" +#include "FairParGenericSet.h" +#include "FairRootManager.h" +#include "FairRun.h" +#include "FairRunOnline.h" +#include "FairRuntimeDb.h" + +#include "TCanvas.h" +#include "THttpServer.h" +#include "TList.h" +#include "TROOT.h" +#include "TString.h" +#include <TFile.h> + +#include <chrono> +#include <fstream> +#include <iomanip> +#include <iostream> + +#include <stdint.h> + +Bool_t bMcbmSpillFindResetHistos = kFALSE; + +CbmMcbmSpillFindTask::CbmMcbmSpillFindTask() + : CbmMcbmUnpack() + , fbMonitorMode(kTRUE) + , fbDebugMonitorMode(kFALSE) + , fuHistoryHistoSize(3600) + , fsHistoFileName("data/HistosMonitorT0.root") + , fuMinTotPulser(90) + , fuMaxTotPulser(100) + , fuOffSpillCountLimit(200) + , fulTsCounter(0) + , fMonitorAlgo(nullptr) +{ + fMonitorAlgo = new CbmMcbmSpillFindAlgo(); +} + +CbmMcbmSpillFindTask::~CbmMcbmSpillFindTask() { delete fMonitorAlgo; } + +Bool_t CbmMcbmSpillFindTask::Init() +{ + LOG(info) << "CbmMcbmSpillFindTask::Init"; + LOG(info) << "Initializing mCBM T0 2019 Monitor"; + + return kTRUE; +} + +void CbmMcbmSpillFindTask::SetParContainers() +{ + LOG(info) << "Setting parameter containers for " << GetName(); + + TList* parCList = fMonitorAlgo->GetParList(); + + for (Int_t iparC = 0; iparC < parCList->GetEntries(); ++iparC) { + FairParGenericSet* tempObj = (FairParGenericSet*) (parCList->At(iparC)); + parCList->Remove(tempObj); + + std::string sParamName {tempObj->GetName()}; + FairParGenericSet* newObj = + dynamic_cast<FairParGenericSet*>(FairRun::Instance()->GetRuntimeDb()->getContainer(sParamName.data())); + + if (nullptr == newObj) { + LOG(error) << "Failed to obtain parameter container " << sParamName << ", for parameter index " << iparC; + return; + } // if( nullptr == newObj ) + + parCList->AddAt(newObj, iparC); + // delete tempObj; + } // for( Int_t iparC = 0; iparC < parCList->GetEntries(); ++iparC ) +} + +Bool_t CbmMcbmSpillFindTask::InitContainers() +{ + LOG(info) << "Init parameter containers for " << GetName(); + + /// Control flags + CbmMcbm2018TofPar* pUnpackPar = + dynamic_cast<CbmMcbm2018TofPar*>(FairRun::Instance()->GetRuntimeDb()->getContainer("CbmMcbm2018TofPar")); + if (nullptr == pUnpackPar) { + LOG(error) << "Failed to obtain parameter container CbmMcbm2018TofPar"; + return kFALSE; + } // if( nullptr == pUnpackPar ) + + Bool_t initOK = fMonitorAlgo->InitContainers(); + + /// Transfer parameter values set from calling macro + fMonitorAlgo->SetMonitorMode(fbMonitorMode); + fMonitorAlgo->SetHistoryHistoSize(fuHistoryHistoSize); + fMonitorAlgo->SetPulserTotLimits(fuMinTotPulser, fuMaxTotPulser); + fMonitorAlgo->SetSpillThreshold(fuOffSpillCountLimit); + fMonitorAlgo->SetSpillCheckIntervalSec(fdSpillCheckInterval); + + /// Histos creation, obtain pointer on them and add them to the HTTP server + /// Trigger histo creation on all associated algos + initOK &= fMonitorAlgo->CreateHistograms(); + + /// Obtain vector of pointers on each histo from the algo (+ optionally desired folder) + std::vector<std::pair<TNamed*, std::string>> vHistos = fMonitorAlgo->GetHistoVector(); + /// Obtain vector of pointers on each canvas from the algo (+ optionally desired folder) + std::vector<std::pair<TCanvas*, std::string>> vCanvases = fMonitorAlgo->GetCanvasVector(); + + /// Register the histos in the HTTP server + THttpServer* server = FairRunOnline::Instance()->GetHttpServer(); + if (nullptr != server) { + for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) { + // LOG(info) << "Registering " << vHistos[ uHisto ].first->GetName() + // << " in " << vHistos[ uHisto ].second.data(); + server->Register(Form("/%s", vHistos[uHisto].second.data()), vHistos[uHisto].first); + } // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto ) + + for (UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv) { + // LOG(info) << "Registering " << vCanvases[ uCanv ].first->GetName() + // << " in " << vCanvases[ uCanv ].second.data(); + server->Register(Form("/%s", vCanvases[uCanv].second.data()), + gROOT->FindObject((vCanvases[uCanv].first)->GetName())); + } // for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv ) + + server->RegisterCommand("/Reset_MoniT0_Hist", "bMcbmSpillFindResetHistos=kTRUE"); + server->Restrict("/Reset_MoniT0_Hist", "allow=admin"); + } // if( nullptr != server ) + + return initOK; +} + +Bool_t CbmMcbmSpillFindTask::ReInitContainers() +{ + LOG(info) << "ReInit parameter containers for " << GetName(); + Bool_t initOK = fMonitorAlgo->ReInitContainers(); + + return initOK; +} + +void CbmMcbmSpillFindTask::AddMsComponentToList(size_t component, UShort_t usDetectorId) +{ + fMonitorAlgo->AddMsComponentToList(component, usDetectorId); +} + +Bool_t CbmMcbmSpillFindTask::DoUnpack(const fles::Timeslice& ts, size_t /*component*/) +{ + if (fbMonitorMode && bMcbmSpillFindResetHistos) { + LOG(info) << "Reset T0 Monitor histos "; + fMonitorAlgo->ResetHistograms(); + bMcbmSpillFindResetHistos = kFALSE; + } // if( fbMonitorMode && bMcbmSpillFindResetHistos ) + + if (kFALSE == fMonitorAlgo->ProcessTs(ts)) { + LOG(error) << "Failed processing TS " << ts.index() << " in unpacker algorithm class"; + return kTRUE; + } // if( kFALSE == fMonitorAlgo->ProcessTs( ts ) ) + + /// Cleqr the digis vector in case it was filled + std::vector<CbmTofDigi> vDigi = fMonitorAlgo->GetVector(); + fMonitorAlgo->ClearVector(); + + if (0 == fulTsCounter % 1000) LOG(info) << "Processed " << fulTsCounter << "TS"; + fulTsCounter++; + + return kTRUE; +} + +void CbmMcbmSpillFindTask::Reset() {} + +void CbmMcbmSpillFindTask::Finish() +{ + fMonitorAlgo->Finish(); + + /// Obtain vector of pointers on each histo from the algo (+ optionally desired folder) + std::vector<std::pair<TNamed*, std::string>> vHistos = fMonitorAlgo->GetHistoVector(); + + /// Save old global file and folder pointer to avoid messing with FairRoot + TFile* oldFile = gFile; + TDirectory* oldDir = gDirectory; + + TFile* histoFile = nullptr; + + // open separate histo file in recreate mode + histoFile = new TFile(fsHistoFileName, "RECREATE"); + histoFile->cd(); + + /// Save the histograms in a file + for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) { + /// Make sure we end up in chosen folder + TString sFolder = vHistos[uHisto].second.data(); + if (nullptr == gDirectory->Get(sFolder)) gDirectory->mkdir(sFolder); + gDirectory->cd(sFolder); + + /// Write plot + vHistos[uHisto].first->Write(); + + histoFile->cd(); + } // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto ) + + /// Restore old global file and folder pointer to avoid messing with FairRoot + gFile = oldFile; + gDirectory = oldDir; + + histoFile->Close(); +} + +void CbmMcbmSpillFindTask::SetIgnoreOverlapMs(Bool_t bFlagIn) { fMonitorAlgo->SetIgnoreOverlapMs(bFlagIn); } + + +ClassImp(CbmMcbmSpillFindTask) diff --git a/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.h b/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.h new file mode 100644 index 0000000000000000000000000000000000000000..45d639883ecc8858b3f8e5a21c4693c5c3f3e47f --- /dev/null +++ b/fles/mcbm2018/tasks/CbmMcbmSpillFindTask.h @@ -0,0 +1,77 @@ +// ----------------------------------------------------------------------------- +// ----- ----- +// ----- CbmMcbmSpillFindTaskzz ----- +// ----- Created 10.02.2019 by P.-A. Loizeau ----- +// ----- ----- +// ----------------------------------------------------------------------------- + +#ifndef CbmMcbmSpillFindTask_H +#define CbmMcbmSpillFindTask_H + +#include "CbmMcbmSpillFindAlgo.h" +#include "CbmMcbmUnpack.h" + +#include "Timeslice.hpp" + +#include "TString.h" + +class CbmMcbmSpillFindTask : public CbmMcbmUnpack { +public: + CbmMcbmSpillFindTask(); + CbmMcbmSpillFindTask(const CbmMcbmSpillFindTask&) = delete; + CbmMcbmSpillFindTask operator=(const CbmMcbmSpillFindTask&) = delete; + + virtual ~CbmMcbmSpillFindTask(); + + virtual Bool_t Init(); + virtual Bool_t DoUnpack(const fles::Timeslice& ts, size_t component); + virtual void Reset(); + + virtual void Finish(); + + void SetParContainers(); + + Bool_t InitContainers(); + + Bool_t ReInitContainers(); + + /// Temp until we change from CbmMcbmUnpack to something else + void AddMsComponentToList(size_t component, UShort_t usDetectorId); + void SetNbMsInTs(size_t /*uCoreMsNb*/, size_t /*uOverlapMsNb*/) {}; + + /// Algo settings setters + inline void SetMonitorMode(Bool_t bFlagIn = kTRUE) { fbMonitorMode = bFlagIn; } + void SetIgnoreOverlapMs(Bool_t bFlagIn = kTRUE); + inline void SetHistoryHistoSize(UInt_t inHistorySizeSec = 1800) { fuHistoryHistoSize = inHistorySizeSec; } + inline void SetHistoFilename(TString sNameIn) { fsHistoFileName = sNameIn; } + inline void SetPulserTotLimits(UInt_t uMin, UInt_t uMax) + { + fuMinTotPulser = uMin; + fuMaxTotPulser = uMax; + } + inline void SetSpillThreshold(UInt_t uCntLimit) { fuOffSpillCountLimit = uCntLimit; } + inline void SetSpillCheckIntervalSec(Double_t dInterval) { fdSpillCheckInterval = dInterval; } + +private: + /// Control flags + Bool_t fbMonitorMode; //! Switch ON the filling of a minimal set of histograms + Bool_t fbDebugMonitorMode; //! Switch ON the filling of a additional set of histograms + + /// User settings parameters + UInt_t fuHistoryHistoSize; + TString fsHistoFileName; + UInt_t fuMinTotPulser; + UInt_t fuMaxTotPulser; + UInt_t fuOffSpillCountLimit; + Double_t fdSpillCheckInterval = 0.5; + + /// Statistics & first TS rejection + uint64_t fulTsCounter; + + /// Processing algo + CbmMcbmSpillFindAlgo* fMonitorAlgo; + + ClassDef(CbmMcbmSpillFindTask, 1) +}; + +#endif diff --git a/macro/beamtime/mcbm2020/find_spills.C b/macro/beamtime/mcbm2020/find_spills.C new file mode 100644 index 0000000000000000000000000000000000000000..388fce1e95796cbe1bc60b805e8155b58ec5193e --- /dev/null +++ b/macro/beamtime/mcbm2020/find_spills.C @@ -0,0 +1,118 @@ +/** @file MCBM spill detection with T0 + ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de> + ** @date 16.02.2021 + ** ROOT macro to read tsa files which have been produced in mCBM and use the T0 detector to + ** find the spill breaks beginning, middle and end TS index + */ +// In order to call later Finish, we make this global +FairRunOnline* run = NULL; + +Bool_t find_spills(TString inFile = "", + UInt_t uRunId = 0, + TString sOutDir = "data", + TString sHostname = "localhost", + Int_t iServerHttpPort = 8080, + Int_t iServerRefreshRate = 100) +{ + TString srcDir = gSystem->Getenv("VMCWORKDIR"); + + // --- Specify number of events to be produced. + // --- -1 means run until the end of the input file. + Int_t nEvents = -1; + // --- Specify output file name (this is just an example) + TString runId = TString::Format("%u", uRunId); + TString parFile = "data/spill_finder_params_" + runId + ".root"; + + // --- Set log output levels + FairLogger::GetLogger(); + gLogger->SetLogScreenLevel("INFO"); + //gLogger->SetLogScreenLevel("DEBUG"); + gLogger->SetLogVerbosityLevel("MEDIUM"); + + // --- Define parameter files + TList* parFileList = new TList(); + TString paramDir = srcDir + "/macro/beamtime/mcbm2020/"; + + TString paramFileTof = paramDir + "mT0Par.par"; + TObjString* parTofFileName = new TObjString(paramFileTof); + parFileList->Add(parTofFileName); + + // --- Set debug level + gDebug = 0; + + std::cout << std::endl; + + // ======================================================================== + // ======================================================================== + std::cout << std::endl; + std::cout << ">>> SpillFinder: Initialising..." << std::endl; + CbmMcbmSpillFindTask* spill_finder_t0 = new CbmMcbmSpillFindTask(); + + spill_finder_t0->SetIgnoreOverlapMs(); + if (0 < uRunId) + spill_finder_t0->SetHistoFilename( Form("data/HistosSpillFinder_%03u.root", uRunId)); + spill_finder_t0->SetPulserTotLimits(180, 210); // for runs > 86 + spill_finder_t0->SetSpillCheckIntervalSec( 0.05 ); // ~every 4 TS + spill_finder_t0->SetSpillThreshold( 40 ); // ~10 hits per TS + + // --- Source task + CbmMcbm2018Source* source = new CbmMcbm2018Source(); + + if ("" != inFile) { + source->SetFileName(inFile); + } // if( "" != inFile ) + else { + source->SetHostName(sHostname); + } // else of if( "" != inFile ) + + // Use kHodo since there is no entry for T0 in the enum yet + source->AddUnpacker(spill_finder_t0, 0x90, ECbmModuleId::kHodo); //gDPB T0 + + source->SetSubscriberHwm(1000); + + // --- Run + run = new FairRunOnline(source); + run->ActivateHttpServer(iServerRefreshRate, + iServerHttpPort); // refresh each 100 events + /// To avoid the server sucking all Histos from gROOT when no output file is used + /// ===> Need to explicitely add the canvases to the server in the task! + run->GetHttpServer()->GetSniffer()->SetScanGlobalDir(kFALSE); + run->SetAutoFinish(kFALSE); + + + // ----- Runtime database --------------------------------------------- + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + FairParAsciiFileIo* parIn = new FairParAsciiFileIo(); + parIn->open(parFileList, "in"); + rtdb->setFirstInput(parIn); + + run->Init(); + + // --- Start run + TStopwatch timer; + timer.Start(); + std::cout << ">>> SpillFinder: Starting run..." << std::endl; + run->Run(-1, 0); // process full file(s)! + + run->Finish(); + + timer.Stop(); + + std::cout << "Processed " << std::dec << source->GetTsCount() << " timeslices" + << std::endl; + + // --- End-of-run info + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << ">>> SpillFinder: Macro finished successfully." << std::endl; + std::cout << ">>> SpillFinder: Real time " << rtime << " s, CPU time " << ctime + << " s" << std::endl; + std::cout << std::endl; + + /// --- Screen output for automatic tests + std::cout << " Test passed" << std::endl; + std::cout << " All ok " << std::endl; + + return kTRUE; +} diff --git a/macro/beamtime/mcbm2020/find_spills_kronos.C b/macro/beamtime/mcbm2020/find_spills_kronos.C new file mode 100644 index 0000000000000000000000000000000000000000..138396fbb96725dabd7696b97e3e320f692c87d8 --- /dev/null +++ b/macro/beamtime/mcbm2020/find_spills_kronos.C @@ -0,0 +1,62 @@ +/** @file MCBM DATA unpacking + ** @author Florian Uhlig <f.uhlig@gsi.de> + ** @date 20.06.2016 + ** Modified by P.-A. Loizeau + ** @date 30.01.2019 + ** ROOT macro to read tsa files which have been produced with the new data transport + ** Convert data into cbmroot format. + ** Uses CbmMcbm2018Source as source task. + */ +#include "find_spills.C" + +/// FIXME: Disable clang formatting to keep easy parameters overview +/* clang-format off */ +Bool_t find_spills_kronos(UInt_t uRunIdx = 28, + TString sOutDir = "data") +{ + /// FIXME: Re-enable clang formatting after parameters initial values setting + /* clang-format on */ + + UInt_t uRunId = 0; + if (99999 != uRunIdx) { + std::vector<UInt_t> vuListRunId = { + 692, 698, 702, 704, 705, 706, 707, // 7 => 0 - 6 + 744, 750, 759, 760, 761, 762, 799, // 7 => 7 - 13 + 811, 812, 816, 817, 819, // 5 => 14 - 18 + 820, 821, 822, 824, 826, 827, 828, 829, // 8 => 19 - 26 + 830, 831, 836, // 3 => 27 - 29 + 841, 846, 849, // 3 => 30 - 32 + 850, 851, 852, 854, 855, 856, 857, 858, 859, // 9 => 33 - 41 + 860, 861, 862, 863, 864, 865, 866 // 7 => 42 - 48 + /* + /// With runs < 1 min due to missmatch! + 811, 812, 816, 817, 818, 819, // 6 => 14 - 19 + 820, 821, 822, 824, 826, 827, 828, 829, // 8 => 20 - 27 + 830, 831, 836, 839, // 4 => 28 - 31 + 840, 841, 842, 844, 845, 846, 848, 849, // 8 => 32 - 39 + 850, 851, 852, 854, 855, 856, 857, 858, 859, // 9 => 40 - 48 + 860, 861, 862, 863, 864, 865, 866 // 7 => 49 - 55 +*/ + }; + if (vuListRunId.size() <= uRunIdx) { + std::cout << "Run index is out of range, not doing anything" << std::endl; + return kFALSE; + } + uRunId = vuListRunId[uRunIdx]; + } // if( 99999 != uRunIdx ) + + if (uRunId < 692) return kFALSE; + + TString inFile = Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn02_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn04_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn05_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn06_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn08_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn10_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn11_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn12_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn13_*.tsa;", uRunId); + inFile += Form("/lustre/cbm/users/ploizeau/mcbm2020/data/%3u_pn15_*.tsa", uRunId); + + return find_spills(inFile, uRunId, sOutDir); +}