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 <sstream>
22#include <string>
23
24#include "TFile.h"
25#include "TTree.h"
26#include "TTreeReader.h"
27#include "TTreeReaderValue.h"
28
32#include "Framework/Task.h"
34#include "Framework/Variant.h"
42
43using namespace o2::framework;
44
45namespace o2
46{
47namespace mid
48{
49
51{
52 public:
53 DigitsReaderDeviceDPL(bool useMC) : mUseMC(useMC)
54 {
55 if (mUseMC) {
56 mLabels = std::make_unique<TTreeReaderValue<dataformats::MCTruthContainer<MCLabel>>>(mTreeReader, "MIDDigitMCLabels");
57 }
58 }
59
60 void init(InitContext& ic)
61 {
62 auto filename = utils::Str::concat_string(utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")),
63 ic.options().get<std::string>("mid-digit-infile"));
64
65 connectTree(filename);
66
67 if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
68 mUseIRFrames = true;
69 }
70 }
71
73 {
74 if (mUseIRFrames) {
75 sendNextIRFrames(pc);
76 } else {
77 sendNextTF(pc);
78 }
79 }
80
81 private:
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{};
86 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 }
110
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{};
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;
175 }
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 }
191};
192
193DataProcessorSpec getDigitReaderSpec(bool useMC, const char* baseDescription)
194{
195 std::vector<OutputSpec> outputs;
196 std::stringstream ss;
197 ss << "digits:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "/0";
198 ss << ";rofs:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "ROF/0";
199 if (useMC) {
200 ss << ";labels:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "LABELS/0";
201 }
202 auto matchers = select(ss.str().c_str());
203 for (auto& matcher : matchers) {
204 outputs.emplace_back(DataSpecUtils::asOutputSpec(matcher));
205 }
206
207 return DataProcessorSpec{
208 "MIDDigitsReader",
209 Inputs{},
210 outputs,
211 AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC)},
212 Options{{"mid-digit-infile", VariantType::String, "middigits.root", {"Name of the input file"}},
213 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
214}
215} // namespace mid
216} // namespace o2
Strip pattern (aka digits)
Label for MID.
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.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Data processor specs for MID digits reader device.
Definition of the MID event record.
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)
constexpr o2::header::DataOrigin gDataOriginMID
Definition DataHeader.h:573
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, const char *baseDescription="DATAMC")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string filename()
static OutputSpec asOutputSpec(InputSpec const &spec)
std::enable_if_t< std::is_same< T, std::string >::value==true, T > as() const
get the descriptor as std::string
Definition DataHeader.h:301
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