Skip to content

Commit 2e9fae4

Browse files
dstoccoalcaliva
authored andcommitted
MID: extract digits from selected BC ranges (#13631)
1 parent 87c82bd commit 2e9fae4

File tree

1 file changed

+136
-47
lines changed

1 file changed

+136
-47
lines changed

Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx

Lines changed: 136 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,28 @@
1717
#include "MIDWorkflow/DigitReaderSpec.h"
1818

1919
#include <memory>
20+
#include <stdexcept>
2021
#include <sstream>
2122
#include <string>
22-
#include "DPLUtils/RootTreeReader.h"
23+
24+
#include "TFile.h"
25+
#include "TTree.h"
26+
#include "TTreeReader.h"
27+
#include "TTreeReaderValue.h"
28+
2329
#include "Framework/ConfigParamRegistry.h"
2430
#include "Framework/ControlService.h"
2531
#include "Framework/DataSpecUtils.h"
26-
#include "Framework/Logger.h"
27-
#include "Framework/Output.h"
2832
#include "Framework/Task.h"
2933
#include "Framework/WorkflowSpec.h"
34+
#include "Framework/Variant.h"
35+
#include "CommonDataFormat/IRFrame.h"
36+
#include "CommonUtils/IRFrameSelector.h"
37+
#include "CommonUtils/StringUtils.h"
3038
#include "SimulationDataFormat/MCTruthContainer.h"
3139
#include "DataFormatsMID/ColumnData.h"
3240
#include "DataFormatsMID/ROFRecord.h"
3341
#include "DataFormatsMID/MCLabel.h"
34-
#include "CommonUtils/NameConf.h"
35-
#include "CommonUtils/StringUtils.h"
3642

3743
using namespace o2::framework;
3844

@@ -44,82 +50,165 @@ namespace mid
4450
class DigitsReaderDeviceDPL
4551
{
4652
public:
47-
DigitsReaderDeviceDPL(bool useMC, const std::vector<header::DataDescription>& descriptions)
48-
: mUseMC(useMC), mDescriptions(descriptions) {}
53+
DigitsReaderDeviceDPL(bool useMC) : mUseMC(useMC)
54+
{
55+
if (mUseMC) {
56+
mLabels = std::make_unique<TTreeReaderValue<dataformats::MCTruthContainer<MCLabel>>>(mTreeReader, "MIDDigitMCLabels");
57+
}
58+
}
4959

5060
void init(InitContext& ic)
5161
{
5262
auto filename = utils::Str::concat_string(utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")),
5363
ic.options().get<std::string>("mid-digit-infile"));
54-
if (mUseMC) {
55-
mReader = std::make_unique<RootTreeReader>("o2sim", filename.c_str(), -1,
56-
RootTreeReader::PublishingMode::Single,
57-
RootTreeReader::BranchDefinition<std::vector<ColumnData>>{
58-
Output{header::gDataOriginMID, mDescriptions[0], 0, Lifetime::Timeframe}, "MIDDigit"},
59-
RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
60-
Output{header::gDataOriginMID, mDescriptions[1], 0, Lifetime::Timeframe}, "MIDROFRecords"},
61-
RootTreeReader::BranchDefinition<dataformats::MCTruthContainer<MCLabel>>{
62-
Output{header::gDataOriginMID, mDescriptions[2], 0, Lifetime::Timeframe}, "MIDDigitMCLabels"},
63-
&mPublishDigits);
64-
} else {
65-
mReader = std::make_unique<RootTreeReader>("o2sim", filename.c_str(), -1,
66-
RootTreeReader::PublishingMode::Single,
67-
RootTreeReader::BranchDefinition<std::vector<ColumnData>>{
68-
Output{header::gDataOriginMID, mDescriptions[0], 0, Lifetime::Timeframe}, "MIDDigit"},
69-
RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
70-
Output{header::gDataOriginMID, mDescriptions[1], 0, Lifetime::Timeframe}, "MIDROFRecords"},
71-
&mPublishDigits);
64+
65+
connectTree(filename);
66+
67+
if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
68+
mUseIRFrames = true;
7269
}
7370
}
7471

7572
void run(ProcessingContext& pc)
7673
{
77-
if ((++(*mReader))(pc) == false) {
78-
pc.services().get<ControlService>().endOfStream();
74+
if (mUseIRFrames) {
75+
sendNextIRFrames(pc);
76+
} else {
77+
sendNextTF(pc);
7978
}
8079
}
8180

8281
private:
83-
std::unique_ptr<RootTreeReader> mReader{};
84-
std::vector<header::DataDescription> mDescriptions{};
82+
TTreeReader mTreeReader{};
83+
TTreeReaderValue<std::vector<ROFRecord>> mRofs = {mTreeReader, "MIDROFRecords"};
84+
TTreeReaderValue<std::vector<ColumnData>> mDigits = {mTreeReader, "MIDDigit"};
85+
std::unique_ptr<TTreeReaderValue<dataformats::MCTruthContainer<MCLabel>>> mLabels{};
8586
bool mUseMC = true;
87+
bool mUseIRFrames = false;
88+
89+
void connectTree(std::string filename)
90+
{
91+
auto file = TFile::Open(filename.c_str());
92+
if (!file || file->IsZombie()) {
93+
throw std::invalid_argument(fmt::format("Opening file {} failed", filename));
94+
}
95+
96+
auto tree = file->Get<TTree>("o2sim");
97+
if (!tree) {
98+
throw std::invalid_argument(fmt::format("Tree o2sim not found in {}", filename));
99+
}
100+
mTreeReader.SetTree(tree);
101+
mTreeReader.Restart();
102+
}
103+
104+
void sendNextTF(ProcessingContext& pc)
105+
{
106+
// load the next TF and check its validity (missing branch, ...)
107+
if (!mTreeReader.Next()) {
108+
throw std::invalid_argument(mTreeReader.fgEntryStatusText[mTreeReader.GetEntryStatus()]);
109+
}
86110

87-
/// structure holding the function to convert and publish the digits
88-
RootTreeReader::SpecialPublishHook mPublishDigits{
89-
[](std::string_view name, ProcessingContext& pc, Output const& output, char* data) -> bool {
90-
if (name == "MIDDigit") {
91-
auto inputDigits = reinterpret_cast<std::vector<ColumnData>*>(data);
92-
std::vector<ColumnData> digits{};
93-
digits.insert(digits.end(), inputDigits->begin(), inputDigits->end());
94-
pc.outputs().snapshot(output, digits);
95-
LOG(debug) << "MIDDigitsReader pushed " << digits.size() << " digits";
96-
return true;
111+
// send the whole TF
112+
pc.outputs().snapshot(OutputRef{"rofs"}, *mRofs);
113+
pc.outputs().snapshot(OutputRef{"digits"}, *mDigits);
114+
if (mUseMC) {
115+
pc.outputs().snapshot(OutputRef{"labels"}, **mLabels);
116+
}
117+
118+
// stop here if it was the last one
119+
if (mTreeReader.GetCurrentEntry() + 1 >= mTreeReader.GetEntries()) {
120+
pc.services().get<ControlService>().endOfStream();
121+
pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
122+
}
123+
}
124+
125+
void sendNextIRFrames(ProcessingContext& pc)
126+
{
127+
std::vector<ROFRecord> rofs{};
128+
std::vector<ColumnData> digits{};
129+
dataformats::MCTruthContainer<MCLabel> labels{};
130+
131+
// get the IR frames to select
132+
auto irFrames = pc.inputs().get<gsl::span<dataformats::IRFrame>>("driverInfo");
133+
134+
if (!irFrames.empty()) {
135+
utils::IRFrameSelector irfSel{};
136+
irfSel.setSelectedIRFrames(irFrames, 0, 0, 0, true);
137+
const auto irMin = irfSel.getIRFrames().front().getMin();
138+
const auto irMax = irfSel.getIRFrames().back().getMax();
139+
140+
// load the first TF if not already done
141+
bool loadNextTF = mTreeReader.GetCurrentEntry() < 0;
142+
143+
while (true) {
144+
// load the next TF if requested
145+
if (loadNextTF && !mTreeReader.Next()) {
146+
throw std::invalid_argument(mTreeReader.fgEntryStatusText[mTreeReader.GetEntryStatus()]);
147+
}
148+
149+
// look for selected ROFs in this TF and copy them
150+
if (!mRofs->empty() && mRofs->front().interactionRecord <= irMax &&
151+
mRofs->back().interactionRecord >= irMin) {
152+
for (const auto& rof : *mRofs) {
153+
if (irfSel.check(rof.interactionRecord) != -1) {
154+
rofs.emplace_back(rof);
155+
rofs.back().firstEntry = digits.size();
156+
rofs.back().nEntries = rof.nEntries;
157+
digits.insert(digits.end(), mDigits->begin() + rof.firstEntry, mDigits->begin() + rof.getEndIndex());
158+
if (mUseMC) {
159+
for (auto idig = 0; idig < rof.nEntries; ++idig) {
160+
labels.addElements(labels.getIndexedSize(), (*mLabels)->getLabels(rof.firstEntry + idig));
161+
}
162+
}
163+
}
164+
}
165+
}
166+
167+
// move to the next TF if needed and if any
168+
if ((mRofs->empty() || mRofs->back().interactionRecord < irMax) &&
169+
mTreeReader.GetCurrentEntry() + 1 < mTreeReader.GetEntries()) {
170+
loadNextTF = true;
171+
continue;
172+
}
173+
174+
break;
97175
}
98-
return false;
99-
}};
176+
}
177+
178+
// send the selected data
179+
pc.outputs().snapshot(OutputRef{"rofs"}, rofs);
180+
pc.outputs().snapshot(OutputRef{"digits"}, digits);
181+
if (mUseMC) {
182+
pc.outputs().snapshot(OutputRef{"labels"}, labels);
183+
}
184+
185+
// stop here if they were the last IR frames to select
186+
if (irFrames.empty() || irFrames.back().isLast()) {
187+
pc.services().get<ControlService>().endOfStream();
188+
pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
189+
}
190+
}
100191
};
101192

102193
DataProcessorSpec getDigitReaderSpec(bool useMC, const char* baseDescription)
103194
{
104195
std::vector<OutputSpec> outputs;
105-
std::vector<header::DataDescription> descriptions;
106196
std::stringstream ss;
107-
ss << "A:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "/0";
108-
ss << ";B:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "ROF/0";
197+
ss << "digits:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "/0";
198+
ss << ";rofs:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "ROF/0";
109199
if (useMC) {
110-
ss << ";C:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "LABELS/0";
200+
ss << ";labels:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "LABELS/0";
111201
}
112202
auto matchers = select(ss.str().c_str());
113203
for (auto& matcher : matchers) {
114204
outputs.emplace_back(DataSpecUtils::asOutputSpec(matcher));
115-
descriptions.emplace_back(DataSpecUtils::asConcreteDataDescription(matcher));
116205
}
117206

118207
return DataProcessorSpec{
119208
"MIDDigitsReader",
120209
Inputs{},
121210
outputs,
122-
AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC, descriptions)},
211+
AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC)},
123212
Options{{"mid-digit-infile", VariantType::String, "middigits.root", {"Name of the input file"}},
124213
{"input-dir", VariantType::String, "none", {"Input directory"}}}};
125214
}

0 commit comments

Comments
 (0)