Skip to content

Commit 25c8f84

Browse files
lietavamusinsky
andauthored
Ctp split sort less histos (#2643)
* [CTP] added split and sort functionality * [CTP] fix curly brackets * [CTP] correct clang format * quick fix to reduce number of histos * clang --------- Co-authored-by: Jan Musinsky <musinsky@gmail.com>
1 parent 4aebbdd commit 25c8f84

File tree

2 files changed

+165
-1
lines changed

2 files changed

+165
-1
lines changed

Modules/CTP/include/CTP/RawDataQcTask.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
/// \file RawDataQcTask.h
1414
/// \author Marek Bombara
1515
/// \author Lucia Anna Tarasovicova
16+
/// \author Jan Musinsky
17+
/// \date 2026-02-17
1618
///
1719

1820
#ifndef QC_MODULE_CTP_CTPRAWDATAQCTASK_H
@@ -47,6 +49,8 @@ class CTPRawDataReaderTask final : public TaskInterface
4749
void endOfCycle() override;
4850
void endOfActivity(const Activity& activity) override;
4951
void reset() override;
52+
void splitSortInputs();
53+
void readLHCFillingScheme();
5054

5155
private:
5256
o2::ctp::RawDataDecoder mDecoder; // ctp raw data decoder
@@ -57,6 +61,11 @@ class CTPRawDataReaderTask final : public TaskInterface
5761
std::unique_ptr<TH1D> mHistoBCMinBias1 = nullptr; // histogram of BC positions to check LHC filling scheme
5862
std::unique_ptr<TH1D> mHistoBCMinBias2 = nullptr; // histogram of BC positions to check LHC filling scheme
5963
std::unique_ptr<TH1D> mHistoDecodeError = nullptr; // histogram of erros from decoder
64+
static constexpr int mUsedInputsMax = 18;
65+
std::array<TH1D*, mUsedInputsMax> mHisInputs = {}; ///< Array of input histograms, all BCs
66+
std::array<TH1D*, mUsedInputsMax> mHisInputsYesLHC = {}; ///< Array of input histograms, LHC BCs
67+
std::array<TH1D*, mUsedInputsMax> mHisInputsNotLHC = {}; ///< Array of input histograms, not LHC BCs
68+
std::array<std::size_t, mUsedInputsMax> shiftBC = {}; ///< Array of shifts for the BCs for each input
6069
int mRunNumber;
6170
int indexMB1 = -1;
6271
int indexMB2 = -1;
@@ -75,6 +84,8 @@ class CTPRawDataReaderTask final : public TaskInterface
7584
std::string mMBclassName;
7685
std::array<uint64_t, o2::ctp::CTP_NCLASSES> mClassErrorsA;
7786
bool mPerformConsistencyCheck = false;
87+
std::bitset<o2::constants::lhc::LHCMaxBunches> mLHCBCs; /// LHC filling scheme
88+
bool lhcDataFileFound = true;
7889
};
7990

8091
} // namespace o2::quality_control_modules::ctp

Modules/CTP/src/RawDataQcTask.cxx

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
/// \file RawDataQcTask.cxx
1414
/// \author Marek Bombara
1515
/// \author Lucia Anna Tarasovicova
16+
/// \author Jan Musinsky
17+
/// \date 2026-02-17
1618
///
1719

1820
#include <TCanvas.h>
21+
#include <TLine.h>
1922
#include <TH1.h>
2023

2124
#include "QualityControl/QcInfoLogger.h"
2225
#include "CTP/RawDataQcTask.h"
26+
#include <DataFormatsParameters/GRPLHCIFData.h>
27+
#include <DetectorsBase/GRPGeomHelper.h>
2328
#include "DetectorsRaw/RDHUtils.h"
2429
#include "Headers/RAWDataHeader.h"
2530
#include "DataFormatsCTP/Digits.h"
@@ -37,6 +42,15 @@ namespace o2::quality_control_modules::ctp
3742

3843
CTPRawDataReaderTask::~CTPRawDataReaderTask()
3944
{
45+
for (auto& h : mHisInputs) {
46+
delete h;
47+
}
48+
for (auto& h : mHisInputsNotLHC) { // must be before mHisInputsYesLHC
49+
delete h;
50+
}
51+
for (auto& h : mHisInputsYesLHC) {
52+
delete h;
53+
}
4054
}
4155

4256
void CTPRawDataReaderTask::initialize(o2::framework::InitContext& /*ctx*/)
@@ -57,6 +71,27 @@ void CTPRawDataReaderTask::initialize(o2::framework::InitContext& /*ctx*/)
5771
getObjectsManager()->startPublishing(mHistoInputRatios.get());
5872
getObjectsManager()->startPublishing(mHistoBCMinBias1.get());
5973
getObjectsManager()->startPublishing(mHistoBCMinBias2.get());
74+
std::string sTmp1, sTmp2;
75+
for (std::size_t i = 0; i < mHisInputs.size(); i++) {
76+
sTmp1 = std::format("input{:02}", i);
77+
sTmp2 = std::format("input[{:02}] {}", i, o2::ctp::CTPInputsConfiguration::getInputNameFromIndex(i + 1));
78+
// getInputNameFromIndex in range [1-48]
79+
mHisInputs[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);
80+
81+
sTmp1 = std::format("input{:02}_yesLHC", i);
82+
mHisInputsYesLHC[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);
83+
mHisInputsYesLHC[i]->SetLineColor(kGreen + 2);
84+
mHisInputsYesLHC[i]->SetFillColor(kGreen + 2);
85+
86+
sTmp1 = std::format("input{:02}_notLHC", i);
87+
mHisInputsNotLHC[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);
88+
mHisInputsNotLHC[i]->SetLineColor(kRed + 1);
89+
mHisInputsNotLHC[i]->SetFillColor(kRed + 1);
90+
91+
getObjectsManager()->startPublishing(mHisInputs[i]);
92+
getObjectsManager()->startPublishing(mHisInputsYesLHC[i]);
93+
// getObjectsManager()->startPublishing(mHisInputsNotLHC[i]);
94+
}
6095

6196
mDecoder.setDoLumi(1);
6297
mDecoder.setDoDigits(1);
@@ -76,9 +111,19 @@ void CTPRawDataReaderTask::startOfActivity(const Activity& activity)
76111
mHistoInputRatios->Reset();
77112
mHistoBCMinBias1->Reset();
78113
mHistoBCMinBias2->Reset();
114+
for (auto& h : mHisInputs) {
115+
h->Reset();
116+
}
117+
for (auto& h : mHisInputsYesLHC) {
118+
h->Reset("ICES");
119+
}
120+
for (auto& h : mHisInputsNotLHC) {
121+
h->Reset();
122+
}
79123

80124
mRunNumber = activity.mId;
81125
mTimestamp = activity.mValidity.getMin();
126+
readLHCFillingScheme(); // call after mTimestamp is set
82127

83128
std::string readCTPConfig = getFromExtendedConfig<std::string>(activity, mCustomParameters, "readCTPconfigInMonitorData", "false");
84129
if (readCTPConfig == "true") {
@@ -211,8 +256,21 @@ void CTPRawDataReaderTask::startOfActivity(const Activity& activity)
211256
mDecoder.setCheckConsistency(1);
212257
mDecoder.setDecodeInps(1);
213258
mPerformConsistencyCheck = true;
259+
for (std::size_t i = 0; i < shiftBC.size(); i++) {
260+
shiftBC[i] = 0; // no shift
261+
}
214262
} else {
215263
mDecoder.setCheckConsistency(0);
264+
for (std::size_t i = 0; i < shiftBC.size(); i++) {
265+
if (i <= 10) {
266+
shiftBC[i] = 0; // [00-10] without shift
267+
}
268+
if (i >= 11 && i <= 23) {
269+
shiftBC[i] = 15; // [11-23] shift by 15 BCs
270+
} else if (i >= 24 && i <= 47) {
271+
shiftBC[i] = 296; // [24-47] shift by 296 BCs
272+
}
273+
}
216274
}
217275

218276
if (mPerformConsistencyCheck) {
@@ -284,7 +342,7 @@ void CTPRawDataReaderTask::monitorData(o2::framework::ProcessingContext& ctx)
284342
for (auto const digit : outputDigits) {
285343
uint16_t bcid = digit.intRecord.bc;
286344
if (digit.CTPInputMask.count()) {
287-
for (int i = 0; i < o2::ctp::CTP_NINPUTS; i++) {
345+
for (int i = 0; i < mUsedInputsMax; i++) {
288346
if (digit.CTPInputMask[i]) {
289347
mHistoInputs->getNum()->Fill(i);
290348
mHistoInputRatios->getNum()->Fill(i);
@@ -297,6 +355,9 @@ void CTPRawDataReaderTask::monitorData(o2::framework::ProcessingContext& ctx)
297355
int bc = bcid - mShiftInput2 >= 0 ? bcid - mShiftInput2 : bcid - mShiftInput2 + 3564;
298356
mHistoBCMinBias2->Fill(bc, 1. / mScaleInput2);
299357
}
358+
// int bc = (bcid - shiftBC[i]) >= 0 ? bcid - shiftBC[i] : bcid - shiftBC[i] + o2::constants::lhc::LHCMaxBunches;
359+
int bc = bcid - shiftBC[i];
360+
mHisInputs[i]->Fill(bc);
300361
}
301362
}
302363
}
@@ -327,6 +388,60 @@ void CTPRawDataReaderTask::endOfCycle()
327388
mHistoInputRatios->update();
328389
mHistoClasses->update();
329390
mHistoClassRatios->update();
391+
splitSortInputs();
392+
}
393+
394+
void CTPRawDataReaderTask::splitSortInputs()
395+
{
396+
struct BC { // BC (Bunch Crossing)
397+
int id; // id [0-3563]
398+
double entries; // number of entries for id
399+
// TH1::GetBinContent(i) return always double over TH1::RetrieveBinContent(i) implemented in TH1*
400+
};
401+
402+
std::vector<BC> BCs; // ?! std::array<BC, 3564> BCs = {} ?!
403+
for (std::size_t ih = 0; ih < mHisInputs.size(); ih++) {
404+
if (mHisInputs[ih]->GetEntries() == 0) {
405+
continue;
406+
}
407+
BCs.clear();
408+
for (int ib = 1; ib <= mHisInputs[ih]->GetNbinsX(); ib++) { // skip underflow bin
409+
BCs.emplace_back(ib - 1, mHisInputs[ih]->GetBinContent(ib));
410+
}
411+
412+
std::sort(BCs.begin(), BCs.end(),
413+
[](const BC& a, const BC& b) { return a.entries > b.entries; }); // sort by BC.entries
414+
// std::cout << "size: " << BCs.size() << std::endl;
415+
// for (const BC& bc : BCs) {
416+
// std::cout << "BC.id: " << std::setw(4) << bc.id << ", BC.entries: " << bc.entries << std::endl;
417+
// }
418+
419+
mHisInputsYesLHC[ih]->Reset("ICES"); // don't delete mHisInputsNotLHC[ih] object
420+
mHisInputsNotLHC[ih]->Reset();
421+
for (std::size_t ibc = 0; ibc < BCs.size(); ibc++) { // skip underflow bin (in loop)
422+
if (mLHCBCs.test(BCs[ibc].id)) {
423+
mHisInputsYesLHC[ih]->SetBinContent(ibc + 1, BCs[ibc].entries);
424+
} else {
425+
mHisInputsNotLHC[ih]->SetBinContent(ibc + 1, BCs[ibc].entries);
426+
}
427+
}
428+
429+
TLine* line = nullptr;
430+
if (!mHisInputsYesLHC[ih]->FindObject(mHisInputsNotLHC[ih])) { // only once
431+
// temporary hack: hisNotLHC->Draw("same")
432+
mHisInputsYesLHC[ih]->GetListOfFunctions()->Add(mHisInputsNotLHC[ih], "same");
433+
// temporary hack: line->Draw("same")
434+
line = new TLine(mLHCBCs.count(), 0, mLHCBCs.count(), mHisInputsYesLHC[ih]->GetMaximum() * 1.05);
435+
line->SetLineStyle(kDotted);
436+
line->SetLineColor(mHisInputsYesLHC[ih]->GetLineColor());
437+
mHisInputsYesLHC[ih]->GetListOfFunctions()->Add(line, "same");
438+
} else { // always set Y2 line maximum (is different for each cycle)
439+
line = dynamic_cast<TLine*>(mHisInputsYesLHC[ih]->FindObject("TLine"));
440+
if (line) {
441+
line->SetY2(mHisInputsYesLHC[ih]->GetMaximum() * 1.05);
442+
}
443+
}
444+
}
330445
}
331446

332447
void CTPRawDataReaderTask::endOfActivity(const Activity& /*activity*/)
@@ -345,8 +460,46 @@ void CTPRawDataReaderTask::reset()
345460
mHistoClassRatios->Reset();
346461
mHistoBCMinBias1->Reset();
347462
mHistoBCMinBias2->Reset();
463+
for (auto& h : mHisInputs) {
464+
h->Reset();
465+
}
466+
for (auto& h : mHisInputsYesLHC) {
467+
h->Reset("ICES");
468+
}
469+
for (auto& h : mHisInputsNotLHC) {
470+
h->Reset();
471+
}
348472
if (mPerformConsistencyCheck)
349473
mHistoDecodeError->Reset();
350474
}
351475

476+
void CTPRawDataReaderTask::readLHCFillingScheme()
477+
{
478+
// mTimestamp = activity.mValidity.getMin(); // set in startOfActivity()
479+
//
480+
// manually added timestamps corresponding to known fills and runs (for testing)
481+
// mTimestamp = 1716040930304 + 1; // fill: 9644, run: 551731
482+
// mTimestamp = 1754317528872 + 1; // fill: 10911, run: 565118
483+
// mTimestamp = 1760845636156 + 1; // fill: 11203, run: 567147
484+
485+
std::map<std::string, std::string> metadata; // can be empty
486+
auto lhcifdata = UserCodeInterface::retrieveConditionAny<o2::parameters::GRPLHCIFData>("GLO/Config/GRPLHCIF", metadata, mTimestamp);
487+
if (lhcifdata == nullptr) {
488+
ILOG(Info, Support) << "LHC data not found for (task) timestamp:" << mTimestamp << ENDM;
489+
lhcDataFileFound = false;
490+
return;
491+
} else {
492+
ILOG(Info, Support) << "LHC data found for (task) timestamp:" << mTimestamp << ENDM;
493+
lhcDataFileFound = true;
494+
// lhcifdata->print();
495+
}
496+
auto bfilling = lhcifdata->getBunchFilling();
497+
std::vector<int> bcs = bfilling.getFilledBCs();
498+
mLHCBCs.reset();
499+
for (auto const& bc : bcs) {
500+
mLHCBCs.set(bc, 1);
501+
}
502+
// ?! test on mLHCBCs.size() == or <= o2::constants::lhc::LHCMaxBunches ?!
503+
}
504+
352505
} // namespace o2::quality_control_modules::ctp

0 commit comments

Comments
 (0)