Commit 92e200bd authored by Pierre-Alain Loizeau's avatar Pierre-Alain Loizeau
Browse files

[mCBM] Improve spill detection in T0 monitor to make it compatible with MQ operation

- Add threshold for non pulser digis in both algo, Task and device
- Make interval for spill threshold checks configurable in both algo, Task and device
- Spill detection only when both threshold passed
- Add Monitor macro for mCBM 2021 using this functionality
parent fd52c53e
......@@ -6,7 +6,6 @@
*/
#include "CbmDeviceMonitorT0.h"
#include "CbmMQDefs.h"
#include "CbmFlesCanvasTools.h"
#include "CbmMcbm2018MonitorAlgoT0.h"
......@@ -49,7 +48,9 @@ CbmDeviceMonitorT0::CbmDeviceMonitorT0()
, fuHistoryHistoSize {3600}
, fuMinTotPulser {185}
, fuMaxTotPulser {195}
, fuOffSpillCountLimit {1000}
, fuOffSpillCountLimit {25}
, fuOffSpillCountLimitNonPulser {10}
, fdSpillCheckInterval {0.0128}
, fvuChanMap {0, 1, 2, 3, 4, 5, 6, 7}
, fuPublishFreqTs {100}
, fdMinPublishTime {0.5}
......@@ -74,6 +75,8 @@ void CbmDeviceMonitorT0::InitTask() try {
fuMinTotPulser = fConfig->GetValue<uint32_t>("PulsTotMin");
fuMaxTotPulser = fConfig->GetValue<uint32_t>("PulsTotMax");
fuOffSpillCountLimit = fConfig->GetValue<uint32_t>("SpillThr");
fuOffSpillCountLimitNonPulser = fConfig->GetValue<uint32_t>("SpillThrNonPuls");
fdSpillCheckInterval = fConfig->GetValue<double>("SpillCheckInt");
std::string sChanMap = fConfig->GetValue<std::string>("ChanMap");
fuPublishFreqTs = fConfig->GetValue<uint32_t>("PubFreqTs");
fdMinPublishTime = fConfig->GetValue<double_t>("PubTimeMin");
......@@ -130,8 +133,7 @@ void CbmDeviceMonitorT0::InitTask() try {
InitContainers();
} catch (InitTaskError& e) {
LOG(error) << e.what();
// Wrapper defined in CbmMQDefs.h to support different FairMQ versions
cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound);
ChangeState(fair::mq::Transition::ErrorFound);
}
bool CbmDeviceMonitorT0::IsChannelNameAllowed(std::string channelName) {
......@@ -200,6 +202,8 @@ Bool_t CbmDeviceMonitorT0::InitContainers() {
fMonitorAlgo->SetHistoryHistoSize(fuHistoryHistoSize);
fMonitorAlgo->SetPulserTotLimits(fuMinTotPulser, fuMaxTotPulser);
fMonitorAlgo->SetSpillThreshold(fuOffSpillCountLimit);
fMonitorAlgo->SetSpillThresholdNonPulser(fuOffSpillCountLimitNonPulser);
fMonitorAlgo->SetSpillCheckInterval(fdSpillCheckInterval);
fMonitorAlgo->SetChannelMap(fvuChanMap[0], fvuChanMap[1], fvuChanMap[2], fvuChanMap[3], fvuChanMap[4], fvuChanMap[5],
fvuChanMap[6], fvuChanMap[7]);
......
......@@ -50,6 +50,8 @@ private:
uint32_t fuMinTotPulser;
uint32_t fuMaxTotPulser;
uint32_t fuOffSpillCountLimit;
uint32_t fuOffSpillCountLimitNonPulser;
double fdSpillCheckInterval;
std::vector<uint32_t> fvuChanMap;
uint32_t fuPublishFreqTs;
double_t fdMinPublishTime;
......
......@@ -21,8 +21,14 @@ void addCustomOptions(bpo::options_description& options) {
bpo::value<uint32_t>()->default_value(195),
"Maximal TOT for pulser cut");
options.add_options()("SpillThr",
bpo::value<uint32_t>()->default_value(1000),
bpo::value<uint32_t>()->default_value(25),
"Hits Nb Thr for spill detection");
options.add_options()("SpillThrNonPuls",
bpo::value<uint32_t>()->default_value(10),
"Non pulser Hits Nb Thr for spill detection");
options.add_options()("SpillCheckInt",
bpo::value<double>()->default_value(0.128),
"Interval in seconds between count checks for spill detection");
options.add_options()("ChanMap", bpo::value<std::string>()->default_value("0,1,2,3,4,5,6,7"),
"Set T0 channel map e.g. 0,1,2,3,4,5,6,7");
options.add_options()("PubFreqTs",
......
......@@ -306,22 +306,30 @@ Bool_t CbmMcbm2018MonitorAlgoT0::ProcessMs(const fles::Timeslice& ts,
/// Spill Detection
if (0 == fuCurrDpbIdx) {
/// Check only every second
if (1.0 < fdMsTime - fdLastSecondTime) {
if (fdSpillCheckInterval < fdMsTime - fdLastInterTime) {
/// Spill Off detection
if (fbSpillOn && fuCountsLastSecond < fuOffSpillCountLimit) {
if (fbSpillOn && fuCountsLastInter < fuOffSpillCountLimit
&& fuNonPulserCountsLastInter < fuOffSpillCountLimitNonPulser) {
fbSpillOn = kFALSE;
fuCurrentSpillIdx++;
fuCurrentSpillPlot = (fuCurrentSpillPlot + 1) % kuNbSpillPlots;
fdStartTimeSpill = fdMsTime;
fvhDpbMapSpill[fuCurrentSpillPlot]->Reset();
fvhChannelMapSpill[fuCurrentSpillPlot]->Reset();
} // if( fbSpillOn && fuCountsLastSecond < fuOffSpillCountLimit )
else if (fuOffSpillCountLimit < fuCountsLastSecond)
} // if( fbSpillOn && fuCountsLastInter < fuOffSpillCountLimit && same for non pulser)
else if (fuOffSpillCountLimit < fuCountsLastInter)
fbSpillOn = kTRUE;
fuCountsLastSecond = 0;
fdLastSecondTime = fdMsTime;
} // if( 1 < fdMsTime - fdLastSecondTime )
LOG(debug) << Form( "%6llu %6.4f %9u %9u %2d",
fulCurrentTsIdx, fdMsTime - fdLastInterTime,
fuCountsLastInter,
fuNonPulserCountsLastInter,
fuCurrentSpillIdx);
fuCountsLastInter = 0;
fuNonPulserCountsLastInter = 0;
fdLastInterTime = fdMsTime;
} // if( fdSpillCheckInterval < fdMsTime - fdLastInterTime )
} // if( 0 == fuCurrDpbIdx )
/// Save start time of first valid MS )
......@@ -379,7 +387,7 @@ Bool_t CbmMcbm2018MonitorAlgoT0::ProcessMs(const fles::Timeslice& ts,
} // if( getGdpbHitIs24b() )
else {
/// Spill detection
fuCountsLastSecond++;
fuCountsLastInter++;
fhErrorFractEvo->Fill(fdMsTime - fdStartTime, 0.0);
fhLostEvtFractEvo->Fill(fdMsTime - fdStartTime, 0.0);
......@@ -396,6 +404,8 @@ Bool_t CbmMcbm2018MonitorAlgoT0::ProcessMs(const fles::Timeslice& ts,
/// Do not fill the pulser hits to keep counts low for channel 0
UInt_t uTot = mess.getGdpbHit32Tot();
if (uTot < fuMinTotPulser || fuMaxTotPulser < uTot) {
fuNonPulserCountsLastInter++;
fhDpbMap->Fill(fuCurrDpbIdx);
fhChannelMap->Fill(uChannelT0);
fhChanHitMap->Fill(fuDiamChanMap[uChannelT0]);
......@@ -1248,7 +1258,7 @@ Bool_t CbmMcbm2018MonitorAlgoT0::CreateHistograms() {
fcSpillCounts->cd(1 + uSpill);
gPad->SetGridx();
gPad->SetGridy();
// gPad->SetLogy();
gPad->SetLogy();
// fvhChannelMapSpill[ uSpill ]->SetStats( kTRUE );
fvhChannelMapSpill[uSpill]->Draw();
gPad->Update();
......@@ -1393,8 +1403,6 @@ Bool_t CbmMcbm2018MonitorAlgoT0::ResetHistograms(Bool_t bResetTime) {
fvhEvtLostFractPerMsEvoChan[uChan]->Reset();
} // for( UInt_t uChan = 0; uChan < kuNbChanDiamond; ++uChan )
fuCurrentSpillIdx = 0;
fuCurrentSpillPlot = 0;
fhDpbMap->Reset();
fhChannelMap->Reset();
fhHitMapEvo->Reset();
......@@ -1424,6 +1432,9 @@ Bool_t CbmMcbm2018MonitorAlgoT0::ResetHistograms(Bool_t bResetTime) {
if (kTRUE == bResetTime) {
/// Also reset the Start time for the evolution plots!
fdStartTime = -1.0;
fuCurrentSpillIdx = 0;
fuCurrentSpillPlot = 0;
} // if( kTRUE == bResetTime )
return kTRUE;
......
......@@ -72,6 +72,12 @@ public:
inline void SetSpillThreshold(UInt_t uCntLimit) {
fuOffSpillCountLimit = uCntLimit;
}
inline void SetSpillThresholdNonPulser(UInt_t uCntLimit) {
fuOffSpillCountLimitNonPulser = uCntLimit;
}
inline void SetSpillCheckInterval(Double_t dIntervalSec) {
fdSpillCheckInterval = dIntervalSec;
}
inline void SetChannelMap(UInt_t uChan0,
UInt_t uChan1,
UInt_t uChan2,
......@@ -115,6 +121,8 @@ private:
UInt_t fuMinTotPulser = 90;
UInt_t fuMaxTotPulser = 100;
UInt_t fuOffSpillCountLimit = 200;
UInt_t fuOffSpillCountLimitNonPulser = 80;
Double_t fdSpillCheckInterval = 1.0;
/// Constants
static const Int_t kiMaxNbFlibLinks = 32;
......@@ -169,6 +177,16 @@ private:
std::vector<gdpbv100::FullMessage> fvmHitsInMs =
{}; //! All hits (time in bins, TOT in bins, asic, channel) in last MS, sorted with "<" operator
/// Spill detection
Bool_t fbSpillOn = kTRUE;
UInt_t fuCurrentSpillIdx = 0;
UInt_t fuCurrentSpillPlot = 0;
Double_t fdStartTimeSpill = -1.0;
Double_t fdLastInterTime = -1.0;
UInt_t fuCountsLastInter = 0;
UInt_t fuNonPulserCountsLastInter = 0;
/// Histograms related variables
UInt_t fuHistoryHistoSize =
3600; /** Size in seconds of the evolution histograms **/
......@@ -205,12 +223,6 @@ private:
std::vector<TH2*> fvhEvtLostFractPerMsEvoChan =
std::vector<TH2*>(kuNbChanDiamond, nullptr);
/// Channels map
Bool_t fbSpillOn = kTRUE;
UInt_t fuCurrentSpillIdx = 0;
UInt_t fuCurrentSpillPlot = 0;
Double_t fdStartTimeSpill = -1.0;
Double_t fdLastSecondTime = -1.0;
UInt_t fuCountsLastSecond = 0;
static const UInt_t kuNbSpillPlots = 5;
// UInt_t kuDiamChanMap[ kuNbChanDiamond ] = { 2, 3, 4, 5, 0, 1, 6, 7 }; //! Map from electronics channel to Diamond strip
UInt_t fuDiamChanMap[kuNbChanDiamond] =
......
......@@ -41,6 +41,8 @@ CbmMcbm2018MonitorTaskT0::CbmMcbm2018MonitorTaskT0()
, fuMinTotPulser(90)
, fuMaxTotPulser(100)
, fuOffSpillCountLimit(200)
, fuOffSpillCountLimitNonPulser(80)
, fdSpillCheckInterval(1.0)
, fulTsCounter(0)
, fMonitorAlgo(nullptr) {
fMonitorAlgo = new CbmMcbm2018MonitorAlgoT0();
......@@ -105,6 +107,8 @@ Bool_t CbmMcbm2018MonitorTaskT0::InitContainers() {
fMonitorAlgo->SetHistoryHistoSize(fuHistoryHistoSize);
fMonitorAlgo->SetPulserTotLimits(fuMinTotPulser, fuMaxTotPulser);
fMonitorAlgo->SetSpillThreshold(fuOffSpillCountLimit);
fMonitorAlgo->SetSpillThresholdNonPulser(fuOffSpillCountLimitNonPulser);
fMonitorAlgo->SetSpillCheckInterval(fdSpillCheckInterval);
/// Histos creation, obtain pointer on them and add them to the HTTP server
/// Trigger histo creation on all associated algos
......
......@@ -55,6 +55,12 @@ public:
inline void SetSpillThreshold(UInt_t uCntLimit) {
fuOffSpillCountLimit = uCntLimit;
}
inline void SetSpillThresholdNonPulser(UInt_t uCntLimit) {
fuOffSpillCountLimitNonPulser = uCntLimit;
}
inline void SetSpillCheckInterval(Double_t dIntervalSec) {
fdSpillCheckInterval = dIntervalSec;
}
void SetChannelMap(UInt_t uChan0,
UInt_t uChan1,
UInt_t uChan2,
......@@ -77,6 +83,8 @@ private:
UInt_t fuMinTotPulser;
UInt_t fuMaxTotPulser;
UInt_t fuOffSpillCountLimit;
UInt_t fuOffSpillCountLimitNonPulser;
Double_t fdSpillCheckInterval;
/// Statistics & first TS rejection
uint64_t fulTsCounter;
......
/** @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.
*/
// In order to call later Finish, we make this global
FairRunOnline* run = NULL;
void MonitorT0(TString inFile = "",
TString sHostname = "cbmflesnode8:5558;cbmflesnode9:5559",
Int_t iServerHttpPort = 8080,
Int_t iServerRefreshRate = 100,
UInt_t uRunId = 0,
UInt_t nrEvents = 0) {
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/moni_t0_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/mcbm2021/";
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 << ">>> MonitorT0: Initialising..." << std::endl;
CbmMcbm2018MonitorTaskT0* monitor_t0 = new CbmMcbm2018MonitorTaskT0();
monitor_t0->SetIgnoreOverlapMs();
monitor_t0->SetHistoryHistoSize(1800);
if (0 < uRunId)
monitor_t0->SetHistoFilename(
Form("data/HistosMonitorT0_%03u.root", uRunId));
monitor_t0->SetPulserTotLimits(180, 210); // for runs > 86
// --- 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(monitor_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 << ">>> MonitorT0: Starting run..." << std::endl;
if (0 == nrEvents) {
run->Run(nEvents, 0); // run until end of input file
} else {
run->Run(0, nrEvents); // process 2000 Events
}
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 << ">>> MonitorT0: Macro finished successfully." << std::endl;
std::cout << ">>> MonitorT0: 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;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment