Project
Loading...
Searching...
No Matches
DigitReaderSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
19#include <memory>
20#include <stdexcept>
21#include <string>
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
41#include "Framework/Task.h"
46
47using namespace o2::framework;
48
49namespace o2
50{
51namespace mch
52{
53
55{
56 public:
57 DigitsReaderDeviceDPL(bool useMC) : mUseMC(useMC)
58 {
59 if (mUseMC) {
60 mLabels = std::make_unique<TTreeReaderValue<dataformats::MCTruthContainer<MCCompLabel>>>(mTreeReader, "MCHMCLabels");
61 }
62 }
63
64 void init(InitContext& ic)
65 {
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);
69
70 if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
71 mUseIRFrames = true;
72 }
73
74 mTimeOffset = ic.options().get<bool>("no-time-offset") ? 0 : DigitFilterParam::Instance().timeOffset;
75 }
76
78 {
79 if (mUseIRFrames) {
80 sendNextIRFrames(pc);
81 } else {
82 sendNextTF(pc);
83 }
84 }
85
86 private:
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{};
91 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{};
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 }
196};
197
198DataProcessorSpec getDigitReaderSpec(bool useMC, std::string_view specName,
199 std::string_view outputDigitDataDescription,
200 std::string_view outputDigitRofDataDescription,
201 std::string_view outputDigitLabelDataDescription)
202{
203 std::string output = fmt::format("digits:MCH/{}/0;rofs:MCH/{}/0", outputDigitDataDescription, outputDigitRofDataDescription);
204 if (useMC) {
205 output += fmt::format(";labels:MCH/{}/0", outputDigitLabelDataDescription);
206 }
207
208 std::vector<OutputSpec> outputs;
209 auto matchers = select(output.c_str());
210 for (auto& matcher : matchers) {
211 outputs.emplace_back(DataSpecUtils::asOutputSpec(matcher));
212 }
213
214 return DataProcessorSpec{
215 std::string(specName),
216 Inputs{},
217 outputs,
218 AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC)},
219 Options{{"mch-digit-infile", VariantType::String, "mchdigits.root", {"Name of the input file"}},
220 {"input-dir", VariantType::String, "none", {"Input directory"}},
221 {"no-time-offset", VariantType::Bool, false, {"no time offset between IRFrames and digits"}}}};
222}
223} // namespace mch
224} // namespace o2
int32_t i
Class to check if give InteractionRecord or IRFrame is selected by the external IRFrame vector.
Class to delimit start and end IR of certain time period.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the MCH ROFrame record.
const char * specName
A container to hold and manage MC truth information/labels.
bool hasOption(const char *key) const
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
void run(ProcessingContext &pc)
void setSelectedIRFrames(const SPAN &sp, size_t bwd=0, size_t fwd=0, long shift=0, bool removeOverlaps=true)
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > select(char const *matcher="")
std::vector< InputSpec > Inputs
framework::DataProcessorSpec getDigitReaderSpec(bool useMC, std::string_view specName="mch-digit-reader", std::string_view outputDigitDataDescription="DIGITS", std::string_view outputDigitRofDataDescription="DIGITROFS", std::string_view outputDigitLabelDataDescription="DIGITLABELS")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static OutputSpec asOutputSpec(InputSpec const &spec)
static std::string rectifyDirectory(const std::string_view p)
static std::string concat_string(Ts const &... ts)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::vector< Digit > digits