Skip to content

Commit 253d920

Browse files
pillotalcaliva
authored andcommitted
extract digits from selected BC ranges if any (#13625)
1 parent 2a06eb5 commit 253d920

File tree

4 files changed

+162
-49
lines changed

4 files changed

+162
-49
lines changed

Detectors/MUON/MCH/IO/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ o2_add_library(MCHIO
2525
O2::DataFormatsMCH
2626
O2::Framework
2727
O2::MCHBase
28+
O2::MCHDigitFiltering
2829
O2::SimulationDataFormat
2930
)
3031

Detectors/MUON/MCH/IO/include/MCHIO/DigitReaderSpec.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ framework::DataProcessorSpec getDigitReaderSpec(
2727
bool useMC,
2828
std::string_view specName = "mch-digit-reader",
2929
std::string_view outputDigitDataDescription = "DIGITS",
30-
std::string_view outputDigitRofDataDescription = "DIGITROFS");
30+
std::string_view outputDigitRofDataDescription = "DIGITROFS",
31+
std::string_view outputDigitLabelDataDescription = "DIGITLABELS");
3132
}
3233
} // namespace o2
3334

Detectors/MUON/MCH/IO/src/DigitReaderSpec.cxx

Lines changed: 156 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,32 @@
1717
#include "MCHIO/DigitReaderSpec.h"
1818

1919
#include <memory>
20-
#include <sstream>
20+
#include <stdexcept>
2121
#include <string>
22-
#include "DPLUtils/RootTreeReader.h"
22+
#include <vector>
23+
24+
#include <fmt/format.h>
25+
26+
#include <gsl/span>
27+
28+
#include <TFile.h>
29+
#include <TTree.h>
30+
#include <TTreeReader.h>
31+
#include <TTreeReaderValue.h>
32+
33+
#include "CommonDataFormat/IRFrame.h"
34+
#include "CommonUtils/IRFrameSelector.h"
35+
#include "CommonUtils/StringUtils.h"
36+
#include "DataFormatsMCH/Digit.h"
37+
#include "DataFormatsMCH/ROFRecord.h"
2338
#include "Framework/ConfigParamRegistry.h"
2439
#include "Framework/ControlService.h"
2540
#include "Framework/DataSpecUtils.h"
26-
#include "Framework/Logger.h"
27-
#include "Framework/Output.h"
2841
#include "Framework/Task.h"
2942
#include "Framework/WorkflowSpec.h"
30-
#include "SimulationDataFormat/MCTruthContainer.h"
43+
#include "MCHDigitFiltering/DigitFilterParam.h"
3144
#include "SimulationDataFormat/MCCompLabel.h"
32-
#include "DataFormatsMCH/Digit.h"
33-
#include "DataFormatsMCH/ROFRecord.h"
34-
#include "CommonUtils/StringUtils.h"
45+
#include "SimulationDataFormat/MCTruthContainer.h"
3546

3647
using namespace o2::framework;
3748

@@ -43,72 +54,171 @@ namespace mch
4354
class DigitsReaderDeviceDPL
4455
{
4556
public:
46-
DigitsReaderDeviceDPL(bool useMC, const std::vector<header::DataDescription>& descriptions)
47-
: mUseMC(useMC), mDescriptions(descriptions) {}
57+
DigitsReaderDeviceDPL(bool useMC) : mUseMC(useMC)
58+
{
59+
if (mUseMC) {
60+
mLabels = std::make_unique<TTreeReaderValue<dataformats::MCTruthContainer<MCCompLabel>>>(mTreeReader, "MCHMCLabels");
61+
}
62+
}
4863

4964
void init(InitContext& ic)
5065
{
51-
auto filename = o2::utils::Str::concat_string(o2::utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")), ic.options().get<std::string>("mch-digit-infile"));
66+
auto fileName = utils::Str::concat_string(utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")),
67+
ic.options().get<std::string>("mch-digit-infile"));
68+
connectTree(fileName);
5269

53-
if (mUseMC) {
54-
mReader = std::make_unique<RootTreeReader>("o2sim", filename.c_str(), -1,
55-
RootTreeReader::PublishingMode::Single,
56-
RootTreeReader::BranchDefinition<std::vector<Digit>>{
57-
Output{header::gDataOriginMCH, mDescriptions[0], 0, Lifetime::Timeframe}, "MCHDigit"},
58-
RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
59-
Output{header::gDataOriginMCH, mDescriptions[1], 0, Lifetime::Timeframe}, "MCHROFRecords"},
60-
RootTreeReader::BranchDefinition<dataformats::MCTruthContainer<MCCompLabel>>{
61-
Output{header::gDataOriginMCH, mDescriptions[2], 0, Lifetime::Timeframe}, "MCHMCLabels"});
62-
} else {
63-
mReader = std::make_unique<RootTreeReader>("o2sim", filename.c_str(), -1,
64-
RootTreeReader::PublishingMode::Single,
65-
RootTreeReader::BranchDefinition<std::vector<Digit>>{
66-
Output{header::gDataOriginMCH, mDescriptions[0], 0, Lifetime::Timeframe}, "MCHDigit"},
67-
RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
68-
Output{header::gDataOriginMCH, mDescriptions[1], 0, Lifetime::Timeframe}, "MCHROFRecords"});
70+
if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
71+
mUseIRFrames = true;
6972
}
73+
74+
mTimeOffset = ic.options().get<bool>("no-time-offset") ? 0 : DigitFilterParam::Instance().timeOffset;
7075
}
7176

7277
void run(ProcessingContext& pc)
7378
{
74-
if ((++(*mReader))(pc) == false) {
75-
pc.services().get<ControlService>().endOfStream();
79+
if (mUseIRFrames) {
80+
sendNextIRFrames(pc);
81+
} else {
82+
sendNextTF(pc);
7683
}
7784
}
7885

7986
private:
80-
std::unique_ptr<RootTreeReader> mReader{};
81-
std::vector<header::DataDescription> mDescriptions{};
87+
TTreeReader mTreeReader{};
88+
TTreeReaderValue<std::vector<ROFRecord>> mRofs = {mTreeReader, "MCHROFRecords"};
89+
TTreeReaderValue<std::vector<Digit>> mDigits = {mTreeReader, "MCHDigit"};
90+
std::unique_ptr<TTreeReaderValue<dataformats::MCTruthContainer<MCCompLabel>>> mLabels{};
8291
bool mUseMC = true;
92+
bool mUseIRFrames = false;
93+
int mTimeOffset = 0;
94+
95+
void connectTree(std::string fileName)
96+
{
97+
auto file = TFile::Open(fileName.c_str());
98+
if (!file || file->IsZombie()) {
99+
throw std::invalid_argument(fmt::format("Opening file {} failed", fileName));
100+
}
101+
102+
auto tree = file->Get<TTree>("o2sim");
103+
if (!tree) {
104+
throw std::invalid_argument(fmt::format("Tree o2sim not found in {}", fileName));
105+
}
106+
mTreeReader.SetTree(tree);
107+
mTreeReader.Restart();
108+
}
109+
110+
void sendNextTF(ProcessingContext& pc)
111+
{
112+
// load the next TF and check its validity (missing branch, ...)
113+
if (!mTreeReader.Next()) {
114+
throw std::invalid_argument(mTreeReader.fgEntryStatusText[mTreeReader.GetEntryStatus()]);
115+
}
116+
117+
// send the whole TF
118+
pc.outputs().snapshot(OutputRef{"rofs"}, *mRofs);
119+
pc.outputs().snapshot(OutputRef{"digits"}, *mDigits);
120+
if (mUseMC) {
121+
pc.outputs().snapshot(OutputRef{"labels"}, **mLabels);
122+
}
123+
124+
// stop here if it was the last one
125+
if (mTreeReader.GetCurrentEntry() + 1 >= mTreeReader.GetEntries()) {
126+
pc.services().get<ControlService>().endOfStream();
127+
pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
128+
}
129+
}
130+
131+
void sendNextIRFrames(ProcessingContext& pc)
132+
{
133+
std::vector<ROFRecord> rofs{};
134+
std::vector<Digit> digits{};
135+
dataformats::MCTruthContainer<MCCompLabel> labels{};
136+
137+
// get the IR frames to select
138+
auto irFrames = pc.inputs().get<gsl::span<dataformats::IRFrame>>("driverInfo");
139+
140+
if (!irFrames.empty()) {
141+
utils::IRFrameSelector irfSel{};
142+
irfSel.setSelectedIRFrames(irFrames, 0, 0, -mTimeOffset, true);
143+
const auto irMin = irfSel.getIRFrames().front().getMin();
144+
const auto irMax = irfSel.getIRFrames().back().getMax();
145+
146+
// load the first TF if not already done
147+
bool loadNextTF = mTreeReader.GetCurrentEntry() < 0;
148+
149+
while (true) {
150+
// load the next TF if requested
151+
if (loadNextTF && !mTreeReader.Next()) {
152+
throw std::invalid_argument(mTreeReader.fgEntryStatusText[mTreeReader.GetEntryStatus()]);
153+
}
154+
155+
// look for selected ROFs in this TF and copy them
156+
if (!mRofs->empty() && mRofs->front().getBCData() <= irMax &&
157+
mRofs->back().getBCData() + mRofs->back().getBCWidth() - 1 >= irMin) {
158+
for (const auto& rof : *mRofs) {
159+
if (irfSel.check({rof.getBCData(), rof.getBCData() + rof.getBCWidth() - 1}) != -1) {
160+
rofs.emplace_back(rof);
161+
rofs.back().setDataRef(digits.size(), rof.getNEntries());
162+
digits.insert(digits.end(), mDigits->begin() + rof.getFirstIdx(), mDigits->begin() + rof.getFirstIdx() + rof.getNEntries());
163+
if (mUseMC) {
164+
for (auto i = 0; i < rof.getNEntries(); ++i) {
165+
labels.addElements(labels.getIndexedSize(), (*mLabels)->getLabels(rof.getFirstIdx() + i));
166+
}
167+
}
168+
}
169+
}
170+
}
171+
172+
// move to the next TF if needed and if any
173+
if ((mRofs->empty() || mRofs->back().getBCData() + mRofs->back().getBCWidth() - 1 < irMax) &&
174+
mTreeReader.GetCurrentEntry() + 1 < mTreeReader.GetEntries()) {
175+
loadNextTF = true;
176+
continue;
177+
}
178+
179+
break;
180+
}
181+
}
182+
183+
// send the selected data
184+
pc.outputs().snapshot(OutputRef{"rofs"}, rofs);
185+
pc.outputs().snapshot(OutputRef{"digits"}, digits);
186+
if (mUseMC) {
187+
pc.outputs().snapshot(OutputRef{"labels"}, labels);
188+
}
189+
190+
// stop here if they were the last IR frames to select
191+
if (irFrames.empty() || irFrames.back().isLast()) {
192+
pc.services().get<ControlService>().endOfStream();
193+
pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
194+
}
195+
}
83196
};
84197

85-
framework::DataProcessorSpec getDigitReaderSpec(
86-
bool useMC,
87-
std::string_view specName,
88-
std::string_view outputDigitDataDescription,
89-
std::string_view outputDigitRofDataDescription)
198+
DataProcessorSpec getDigitReaderSpec(bool useMC, std::string_view specName,
199+
std::string_view outputDigitDataDescription,
200+
std::string_view outputDigitRofDataDescription,
201+
std::string_view outputDigitLabelDataDescription)
90202
{
91-
std::vector<OutputSpec> outputs;
92-
std::vector<header::DataDescription> descriptions;
93-
std::stringstream ss;
94-
ss << "A:" << header::gDataOriginMCH.as<std::string>() << "/" << outputDigitDataDescription << "/0";
95-
ss << ";B:" << header::gDataOriginMCH.as<std::string>() << "/" << outputDigitRofDataDescription << "/0";
203+
std::string output = fmt::format("digits:MCH/{}/0;rofs:MCH/{}/0", outputDigitDataDescription, outputDigitRofDataDescription);
96204
if (useMC) {
97-
ss << ";C:" << header::gDataOriginMCH.as<std::string>() << "/DIGITLABELS/0";
205+
output += fmt::format(";labels:MCH/{}/0", outputDigitLabelDataDescription);
98206
}
99-
auto matchers = select(ss.str().c_str());
207+
208+
std::vector<OutputSpec> outputs;
209+
auto matchers = select(output.c_str());
100210
for (auto& matcher : matchers) {
101211
outputs.emplace_back(DataSpecUtils::asOutputSpec(matcher));
102-
descriptions.emplace_back(DataSpecUtils::asConcreteDataDescription(matcher));
103212
}
104213

105214
return DataProcessorSpec{
106215
std::string(specName),
107216
Inputs{},
108217
outputs,
109-
AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC, descriptions)},
218+
AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC)},
110219
Options{{"mch-digit-infile", VariantType::String, "mchdigits.root", {"Name of the input file"}},
111-
{"input-dir", VariantType::String, "none", {"Input directory"}}}};
220+
{"input-dir", VariantType::String, "none", {"Input directory"}},
221+
{"no-time-offset", VariantType::Bool, false, {"no time offset between IRFrames and digits"}}}};
112222
}
113223
} // namespace mch
114224
} // namespace o2

Detectors/MUON/MCH/IO/src/digits-reader-workflow.cxx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions)
3535
{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}},
3636
{"mch-output-digits-data-description", VariantType::String, "DIGITS", {"description string for the output digits message"}},
3737
{"mch-output-digitrofs-data-description", VariantType::String, "DIGITROFS", {"description string for the output digit rofs message"}},
38-
};
38+
{"mch-output-digitlabels-data-description", VariantType::String, "DIGITLABELS", {"description string for the output digit labels message"}}};
3939
workflowOptions.insert(workflowOptions.end(), options.begin(), options.end());
4040
o2::raw::HBFUtilsInitializer::addConfigOption(workflowOptions);
4141
}
@@ -55,7 +55,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cc)
5555
useMC,
5656
name,
5757
cc.options().get<std::string>("mch-output-digits-data-description"),
58-
cc.options().get<std::string>("mch-output-digitrofs-data-description")));
58+
cc.options().get<std::string>("mch-output-digitrofs-data-description"),
59+
cc.options().get<std::string>("mch-output-digitlabels-data-description")));
5960

6061
o2::raw::HBFUtilsInitializer hbfIni(cc, specs);
6162

0 commit comments

Comments
 (0)