Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Modules/CTP/include/CTP/RawDataQcTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
/// \file RawDataQcTask.h
/// \author Marek Bombara
/// \author Lucia Anna Tarasovicova
/// \author Jan Musinsky
/// \date 2026-02-17
///

#ifndef QC_MODULE_CTP_CTPRAWDATAQCTASK_H
Expand Down Expand Up @@ -47,16 +49,22 @@ class CTPRawDataReaderTask final : public TaskInterface
void endOfCycle() override;
void endOfActivity(const Activity& activity) override;
void reset() override;
void splitSortInputs();
void readLHCFillingScheme();

private:
o2::ctp::RawDataDecoder mDecoder; // ctp raw data decoder
std::unique_ptr<TH1DRatio> mHistoInputs = nullptr; // histogram with ctp inputs
std::unique_ptr<TH1DRatio> mHistoClasses = nullptr; // histogram with ctp classes
std::unique_ptr<TH1DRatio> mHistoInputRatios = nullptr; // histogram with ctp input ratios to MB
std::unique_ptr<TH1DRatio> mHistoClassRatios = nullptr; // histogram with ctp class ratios to MB
std::unique_ptr<TH1D> mHistoBCMinBias1 = nullptr; // histogram of BC positions to check LHC filling scheme
std::unique_ptr<TH1D> mHistoBCMinBias2 = nullptr; // histogram of BC positions to check LHC filling scheme
std::unique_ptr<TH1D> mHistoDecodeError = nullptr; // histogram of erros from decoder
o2::ctp::RawDataDecoder mDecoder; // ctp raw data decoder
std::unique_ptr<TH1DRatio> mHistoInputs = nullptr; // histogram with ctp inputs
std::unique_ptr<TH1DRatio> mHistoClasses = nullptr; // histogram with ctp classes
std::unique_ptr<TH1DRatio> mHistoInputRatios = nullptr; // histogram with ctp input ratios to MB
std::unique_ptr<TH1DRatio> mHistoClassRatios = nullptr; // histogram with ctp class ratios to MB
std::unique_ptr<TH1D> mHistoBCMinBias1 = nullptr; // histogram of BC positions to check LHC filling scheme
std::unique_ptr<TH1D> mHistoBCMinBias2 = nullptr; // histogram of BC positions to check LHC filling scheme
std::unique_ptr<TH1D> mHistoDecodeError = nullptr; // histogram of erros from decoder
std::array<TH1D*, o2::ctp::CTP_NINPUTS> mHisInputs = {}; ///< Array of input histograms, all BCs
std::array<TH1D*, o2::ctp::CTP_NINPUTS> mHisInputsYesLHC = {}; ///< Array of input histograms, LHC BCs
std::array<TH1D*, o2::ctp::CTP_NINPUTS> mHisInputsNotLHC = {}; ///< Array of input histograms, not LHC BCs
std::array<std::size_t, o2::ctp::CTP_NINPUTS> shiftBC = {}; ///< Array of shifts for the BCs for each input
int mRunNumber;
int indexMB1 = -1;
int indexMB2 = -1;
Expand All @@ -75,6 +83,8 @@ class CTPRawDataReaderTask final : public TaskInterface
std::string mMBclassName;
std::array<uint64_t, o2::ctp::CTP_NCLASSES> mClassErrorsA;
bool mPerformConsistencyCheck = false;
std::bitset<o2::constants::lhc::LHCMaxBunches> mLHCBCs; /// LHC filling scheme
bool lhcDataFileFound = true;
};

} // namespace o2::quality_control_modules::ctp
Expand Down
136 changes: 136 additions & 0 deletions Modules/CTP/src/RawDataQcTask.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
/// \file RawDataQcTask.cxx
/// \author Marek Bombara
/// \author Lucia Anna Tarasovicova
/// \author Jan Musinsky
/// \date 2026-02-17
///

#include <TCanvas.h>
#include <TLine.h>
#include <TH1.h>

#include "QualityControl/QcInfoLogger.h"
#include "CTP/RawDataQcTask.h"
#include <DataFormatsParameters/GRPLHCIFData.h>
#include <DetectorsBase/GRPGeomHelper.h>
#include "DetectorsRaw/RDHUtils.h"
#include "Headers/RAWDataHeader.h"
#include "DataFormatsCTP/Digits.h"
Expand All @@ -37,6 +42,12 @@ namespace o2::quality_control_modules::ctp

CTPRawDataReaderTask::~CTPRawDataReaderTask()
{
for (auto& h : mHisInputs)
delete h;
for (auto& h : mHisInputsNotLHC) // must be before mHisInputsYesLHC
delete h;
for (auto& h : mHisInputsYesLHC)
delete h;
}

void CTPRawDataReaderTask::initialize(o2::framework::InitContext& /*ctx*/)
Expand All @@ -57,6 +68,27 @@ void CTPRawDataReaderTask::initialize(o2::framework::InitContext& /*ctx*/)
getObjectsManager()->startPublishing(mHistoInputRatios.get());
getObjectsManager()->startPublishing(mHistoBCMinBias1.get());
getObjectsManager()->startPublishing(mHistoBCMinBias2.get());
std::string sTmp1, sTmp2;
for (std::size_t i = 0; i < mHisInputs.size(); i++) {
sTmp1 = std::format("input{:02}", i);
sTmp2 = std::format("input[{:02}] {}", i, o2::ctp::CTPInputsConfiguration::getInputNameFromIndex(i + 1));
// getInputNameFromIndex in range [1-48]
mHisInputs[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);

sTmp1 = std::format("input{:02}_yesLHC", i);
mHisInputsYesLHC[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);
mHisInputsYesLHC[i]->SetLineColor(kGreen + 2);
mHisInputsYesLHC[i]->SetFillColor(kGreen + 2);

sTmp1 = std::format("input{:02}_notLHC", i);
mHisInputsNotLHC[i] = new TH1D(sTmp1.c_str(), sTmp2.c_str(), norbits, 0, norbits);
mHisInputsNotLHC[i]->SetLineColor(kRed + 1);
mHisInputsNotLHC[i]->SetFillColor(kRed + 1);

getObjectsManager()->startPublishing(mHisInputs[i]);
getObjectsManager()->startPublishing(mHisInputsYesLHC[i]);
// getObjectsManager()->startPublishing(mHisInputsNotLHC[i]);
}

mDecoder.setDoLumi(1);
mDecoder.setDoDigits(1);
Expand All @@ -76,9 +108,16 @@ void CTPRawDataReaderTask::startOfActivity(const Activity& activity)
mHistoInputRatios->Reset();
mHistoBCMinBias1->Reset();
mHistoBCMinBias2->Reset();
for (auto& h : mHisInputs)
h->Reset();
for (auto& h : mHisInputsYesLHC)
h->Reset("ICES");
for (auto& h : mHisInputsNotLHC)
h->Reset();

mRunNumber = activity.mId;
mTimestamp = activity.mValidity.getMin();
readLHCFillingScheme(); // call after mTimestamp is set

std::string readCTPConfig = getFromExtendedConfig<std::string>(activity, mCustomParameters, "readCTPconfigInMonitorData", "false");
if (readCTPConfig == "true") {
Expand Down Expand Up @@ -211,8 +250,17 @@ void CTPRawDataReaderTask::startOfActivity(const Activity& activity)
mDecoder.setCheckConsistency(1);
mDecoder.setDecodeInps(1);
mPerformConsistencyCheck = true;
// clang-format off
for (std::size_t i = 0; i < shiftBC.size(); i++)
shiftBC[i] = 0; // no shift
} else {
mDecoder.setCheckConsistency(0);
for (std::size_t i = 0; i < shiftBC.size(); i++) {
if (i <= 10) shiftBC[i] = 0; // [00-10] without shift
if (i >= 11 && i <= 23) shiftBC[i] = 15; // [11-23] shift by 15 BCs
else if (i >= 24 && i <= 47) shiftBC[i] = 296; // [24-47] shift by 296 BCs
}
// clang-format on
}

if (mPerformConsistencyCheck) {
Expand Down Expand Up @@ -297,6 +345,9 @@ void CTPRawDataReaderTask::monitorData(o2::framework::ProcessingContext& ctx)
int bc = bcid - mShiftInput2 >= 0 ? bcid - mShiftInput2 : bcid - mShiftInput2 + 3564;
mHistoBCMinBias2->Fill(bc, 1. / mScaleInput2);
}
// int bc = (bcid - shiftBC[i]) >= 0 ? bcid - shiftBC[i] : bcid - shiftBC[i] + o2::constants::lhc::LHCMaxBunches;
int bc = bcid - shiftBC[i];
mHisInputs[i]->Fill(bc);
}
}
}
Expand Down Expand Up @@ -327,6 +378,56 @@ void CTPRawDataReaderTask::endOfCycle()
mHistoInputRatios->update();
mHistoClasses->update();
mHistoClassRatios->update();
splitSortInputs();
}

void CTPRawDataReaderTask::splitSortInputs()
{
struct BC { // BC (Bunch Crossing)
int id; // id [0-3563]
double entries; // number of entries for id
// TH1::GetBinContent(i) return always double over TH1::RetrieveBinContent(i) implemented in TH1*
};

std::vector<BC> BCs; // ?! std::array<BC, 3564> BCs = {} ?!
for (std::size_t ih = 0; ih < mHisInputs.size(); ih++) {
if (mHisInputs[ih]->GetEntries() == 0)
continue;
BCs.clear();
for (int ib = 1; ib <= mHisInputs[ih]->GetNbinsX(); ib++) // skip underflow bin
BCs.emplace_back(ib - 1, mHisInputs[ih]->GetBinContent(ib));

std::sort(BCs.begin(), BCs.end(),
[](const BC& a, const BC& b) { return a.entries > b.entries; }); // sort by BC.entries
// std::cout << "size: " << BCs.size() << std::endl;
// for (const BC& bc : BCs) {
// std::cout << "BC.id: " << std::setw(4) << bc.id << ", BC.entries: " << bc.entries << std::endl;
// }

mHisInputsYesLHC[ih]->Reset("ICES"); // don't delete mHisInputsNotLHC[ih] object
mHisInputsNotLHC[ih]->Reset();
for (std::size_t ibc = 0; ibc < BCs.size(); ibc++) { // skip underflow bin (in loop)
if (mLHCBCs.test(BCs[ibc].id))
mHisInputsYesLHC[ih]->SetBinContent(ibc + 1, BCs[ibc].entries);
else
mHisInputsNotLHC[ih]->SetBinContent(ibc + 1, BCs[ibc].entries);
}

TLine* line = nullptr;
if (!mHisInputsYesLHC[ih]->FindObject(mHisInputsNotLHC[ih])) { // only once
// temporary hack: hisNotLHC->Draw("same")
mHisInputsYesLHC[ih]->GetListOfFunctions()->Add(mHisInputsNotLHC[ih], "same");
// temporary hack: line->Draw("same")
line = new TLine(mLHCBCs.count(), 0, mLHCBCs.count(), mHisInputsYesLHC[ih]->GetMaximum() * 1.05);
line->SetLineStyle(kDotted);
line->SetLineColor(mHisInputsYesLHC[ih]->GetLineColor());
mHisInputsYesLHC[ih]->GetListOfFunctions()->Add(line, "same");
} else { // always set Y2 line maximum (is different for each cycle)
line = dynamic_cast<TLine*>(mHisInputsYesLHC[ih]->FindObject("TLine"));
if (line)
line->SetY2(mHisInputsYesLHC[ih]->GetMaximum() * 1.05);
}
}
}

void CTPRawDataReaderTask::endOfActivity(const Activity& /*activity*/)
Expand All @@ -345,8 +446,43 @@ void CTPRawDataReaderTask::reset()
mHistoClassRatios->Reset();
mHistoBCMinBias1->Reset();
mHistoBCMinBias2->Reset();
for (auto& h : mHisInputs)
h->Reset();
for (auto& h : mHisInputsYesLHC)
h->Reset("ICES");
for (auto& h : mHisInputsNotLHC)
h->Reset();
if (mPerformConsistencyCheck)
mHistoDecodeError->Reset();
}

void CTPRawDataReaderTask::readLHCFillingScheme()
{
// mTimestamp = activity.mValidity.getMin(); // set in startOfActivity()
//
// manually added timestamps corresponding to known fills and runs (for testing)
// mTimestamp = 1716040930304 + 1; // fill: 9644, run: 551731
// mTimestamp = 1754317528872 + 1; // fill: 10911, run: 565118
// mTimestamp = 1760845636156 + 1; // fill: 11203, run: 567147

std::map<std::string, std::string> metadata; // can be empty
auto lhcifdata = UserCodeInterface::retrieveConditionAny<o2::parameters::GRPLHCIFData>("GLO/Config/GRPLHCIF", metadata, mTimestamp);
if (lhcifdata == nullptr) {
ILOG(Info, Support) << "LHC data not found for (task) timestamp:" << mTimestamp << ENDM;
lhcDataFileFound = false;
return;
} else {
ILOG(Info, Support) << "LHC data found for (task) timestamp:" << mTimestamp << ENDM;
lhcDataFileFound = true;
lhcifdata->print();
}
auto bfilling = lhcifdata->getBunchFilling();
std::vector<int> bcs = bfilling.getFilledBCs();
mLHCBCs.reset();
for (auto const& bc : bcs) {
mLHCBCs.set(bc, 1);
}
// ?! test on mLHCBCs.size() == or <= o2::constants::lhc::LHCMaxBunches ?!
}

} // namespace o2::quality_control_modules::ctp