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
13
14#include <string>
15#include <vector>
16
17#include "TTree.h"
18
21#include "Framework/Logger.h"
33#include <cassert>
34
35using namespace o2::framework;
36using namespace o2::itsmft;
37
38namespace o2
39{
40namespace itsmft
41{
42
43template <int N>
44DigitReader<N>::DigitReader(bool useMC, bool useCalib, bool triggerOut) : mUseMC(useMC), mUseCalib(useCalib), mTriggerOut(triggerOut), mDetNameLC(mDetName = ID.getName()), mDigTreeName("o2sim")
45{
49
52
53 std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower);
55 for (uint32_t i = 0; i < NLayers; ++i) {
56 mDigits[i] = nullptr;
57 mDigROFRec[i] = nullptr;
58 mDigMC2ROFs[i] = nullptr;
59 mPLabels[i] = nullptr;
60 }
61}
62
63template <int N>
65{
66 mFileName = o2::utils::Str::concat_string(o2::utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")),
67 ic.options().get<std::string>((mDetNameLC + "-digit-infile").c_str()));
68 if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
69 mUseIRFrames = true;
70 }
71 connectTree(mFileName);
72}
73
74template <int N>
76{
77 const auto& tinfo = pc.services().get<o2::framework::TimingInfo>();
78 const auto& alpideParam = o2::itsmft::DPLAlpideParam<N>::Instance();
79 if (tinfo.globalRunNumberChanged && mUseIRFrames) { // new run is starting: 1st call
80 // TODO: we have to find a way define CCDBInput for IRFrames mode only using DPL fetcher
82 auto rlim = ccdb.getRunDuration(tinfo.runNumber);
83 long ts = (rlim.first + rlim.second) / 2;
84 if constexpr (N == o2::detectors::DetID::ITS) {
85 ccdb.getForTimeStamp<o2::itsmft::DPLAlpideParam<o2::detectors::DetID::ITS>>("ITS/Config/AlpideParam", ts);
86 mROFBiasInBC = alpideParam.roFrameBiasInBC;
87 mROFLengthInBC = alpideParam.roFrameLengthInBC;
89 } else {
90 ccdb.getForTimeStamp<o2::itsmft::DPLAlpideParam<o2::detectors::DetID::MFT>>("MFT/Config/AlpideParam", ts);
91 mROFBiasInBC = alpideParam.roFrameBiasInBC;
92 mROFLengthInBC = alpideParam.roFrameLengthInBC;
94 }
95 }
96 gsl::span<const o2::dataformats::IRFrame> irFrames{};
97 if (mUseIRFrames) {
98 irFrames = pc.inputs().get<gsl::span<o2::dataformats::IRFrame>>("driverInfo");
99 }
100
101 auto ent = mTree->GetReadEntry();
102 if (!mUseIRFrames) {
103 ent++;
104 assert(ent < mTree->GetEntries()); // this should not happen
105 mTree->GetEntry(ent);
106 for (uint32_t iLayer = 0; iLayer < RLayers; ++iLayer) {
107 LOG(info) << mDetName << "DigitReader:" << iLayer << " pushes " << mDigROFRec[iLayer]->size() << " ROFRecords, " << mDigits[iLayer]->size() << " digits at entry " << ent;
108 pc.outputs().snapshot(Output{Origin, "DIGITSROF", iLayer}, *mDigROFRec[iLayer]);
109 pc.outputs().snapshot(Output{Origin, "DIGITS", iLayer}, *mDigits[iLayer]);
110 if (mUseMC) {
111 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{Origin, "DIGITSMCTR", iLayer});
112 mPLabels[iLayer]->copyandflatten(sharedlabels);
113 delete mPLabels[iLayer];
114 mPLabels[iLayer] = nullptr;
115 pc.outputs().snapshot(Output{Origin, "DIGITSMC2ROF", iLayer}, *mDigMC2ROFs[iLayer]);
116 }
117 }
118 if (mUseCalib) {
119 pc.outputs().snapshot(Output{Origin, "GBTCALIB", 0}, mCalib);
120 }
121 if (mTriggerOut) {
122 std::vector<o2::itsmft::PhysTrigger> dummyTrig;
123 pc.outputs().snapshot(Output{Origin, "PHYSTRIG", 0}, dummyTrig);
124 }
125 if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) {
126 pc.services().get<ControlService>().endOfStream();
127 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
128 }
129 } else { // need to select particulars IRs range, presumably from the same tree entry
130 // TODO implement for staggering
131 std::vector<o2::itsmft::Digit> digitsSel;
132 std::vector<o2::itsmft::GBTCalibData> calibSel;
133 std::vector<o2::itsmft::ROFRecord> digROFRecSel;
134 std::vector<o2::itsmft::MC2ROFRecord> digMC2ROFsSel;
136
137 if (irFrames.size()) { // we assume the IRFrames are in the increasing order
138 if (ent < 0) {
139 ent++;
140 }
142 irfSel.setSelectedIRFrames(irFrames, 0, 0, -mROFBiasInBC, true);
143 const auto irMin = irfSel.getIRFrames().front().getMin(); // use processed IRframes for rough comparisons (possible shift!)
144 const auto irMax = irfSel.getIRFrames().back().getMax();
145 LOGP(info, "Selecting IRFrame {}-{}", irMin.asString(), irMax.asString());
146 while (ent < mTree->GetEntries()) {
147 // do we need to read a new entry?
148 if (ent > mTree->GetReadEntry()) {
149 if (mUseMC) {
150 delete mPLabels[0];
151 mPLabels[0] = nullptr;
152 mConstLabels[0].clear();
153 mTree->SetBranchAddress(mDigitMCTruthBranchName.c_str(), &mPLabels[0]);
154 }
155 mTree->GetEntry(ent);
156 if (mUseMC) {
157 mPLabels[0]->copyandflatten(mConstLabels[0]);
158 delete mPLabels[0];
159 mPLabels[0] = nullptr;
160 }
161 }
162 std::vector<int> rofOld2New;
163 rofOld2New.resize(mDigROFRec[0]->size(), -1);
164
165 if (mDigROFRec[0]->front().getBCData() <= irMax && (mDigROFRec[0]->back().getBCData() + mROFLengthInBC - 1) >= irMin) { // there is an overlap
166 for (int irof = 0; irof < (int)mDigROFRec[0]->size(); irof++) {
167 const auto& rof = mDigROFRec[0]->at(irof);
168 if (irfSel.check({rof.getBCData(), rof.getBCData() + mROFLengthInBC - 1}) != -1) {
169 rofOld2New[irof] = (int)digROFRecSel.size();
170 LOGP(debug, "Adding selected ROF {}", rof.getBCData().asString());
171 digROFRecSel.push_back(rof);
172 int offs = digitsSel.size();
173 digROFRecSel.back().setFirstEntry(offs);
174 std::copy(mDigits[0]->begin() + rof.getFirstEntry(), mDigits[0]->begin() + rof.getFirstEntry() + rof.getNEntries(), std::back_inserter(digitsSel));
175 for (int id = 0; id < rof.getNEntries(); id++) { // copy MC info
176 digitLabelsSel.addElements(id + offs, mConstLabels[0].getLabels(id + rof.getFirstEntry()));
177 }
178 if (mCalib.size() >= size_t((irof + 1) * mNRUs)) {
179 std::copy(mCalib.begin() + irof * mNRUs, mCalib.begin() + (irof + 1) * mNRUs, std::back_inserter(calibSel));
180 }
181 }
182 }
183 }
184 if (mUseMC) {
185 digMC2ROFsSel = *mDigMC2ROFs[0];
186 for (auto& mc2rof : digMC2ROFsSel) {
187 if (mc2rof.rofRecordID < 0) {
188 continue; // did not contribute even to the original data
189 }
190 unsigned int mn = 0xffff, mx = 0;
191 for (int ir = mc2rof.minROF; ir <= mc2rof.maxROF; ir++) {
192 if (rofOld2New[ir] >= 0) { // used
193 mx = rofOld2New[ir];
194 if (mn > mx) {
195 mn = mx;
196 }
197 }
198 }
199 mc2rof.rofRecordID = mn == 0xffff ? -1 : int(mn);
200 mc2rof.minROF = mn;
201 mc2rof.maxROF = mx;
202 }
203 }
204 if (mDigROFRec[0]->back().getBCData() + mROFLengthInBC - 1 < irMax) { // need to check the next entry
205 ent++;
206 continue;
207 }
208 break; // push collected data
209 }
210 }
211 pc.outputs().snapshot(Output{Origin, "DIGITSROF", 0}, digROFRecSel);
212 pc.outputs().snapshot(Output{Origin, "DIGITS", 0}, digitsSel);
213 if (mUseCalib) {
214 pc.outputs().snapshot(Output{Origin, "GBTCALIB", 0}, calibSel);
215 }
216 if (mTriggerOut) {
217 std::vector<o2::itsmft::PhysTrigger> dummyTrig;
218 pc.outputs().snapshot(Output{Origin, "PHYSTRIG", 0}, dummyTrig);
219 }
220 if (mUseMC) {
221 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{Origin, "DIGITSMCTR", 0});
222 digitLabelsSel.flatten_to(sharedlabels);
223 pc.outputs().snapshot(Output{Origin, "DIGITSMC2ROF", 0}, digMC2ROFsSel);
224 }
225
226 if (!irFrames.size() || irFrames.back().isLast()) {
227 pc.services().get<ControlService>().endOfStream();
228 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
229 }
230 }
231}
232
233template <int N>
234void DigitReader<N>::connectTree(const std::string& filename)
235{
236 mTree.reset(nullptr); // in case it was already loaded
237 mFile.reset(TFile::Open(filename.c_str()));
238 assert(mFile && !mFile->IsZombie());
239 mTree.reset((TTree*)mFile->Get(mDigTreeName.c_str()));
240 assert(mTree);
241 for (uint32_t iLayer = 0; iLayer < RLayers; ++iLayer) {
242 setBranchAddress(mDigitROFBranchName, mDigROFRec[iLayer], iLayer);
243 setBranchAddress(mDigitBranchName, mDigits[iLayer], iLayer);
244 if (mUseMC) {
245 if (!mTree->GetBranch(getBranchName(mDigitMC2ROFBranchName, iLayer).c_str()) || !mTree->GetBranch(getBranchName(mDigitMCTruthBranchName, iLayer).c_str())) {
246 throw std::runtime_error("MC data requested but not found in the tree");
247 }
248 setBranchAddress(mDigitMC2ROFBranchName, mDigMC2ROFs[iLayer], iLayer);
249 if (!mPLabels[iLayer]) {
250 setBranchAddress(mDigitMCTruthBranchName, mPLabels[iLayer], iLayer);
251 }
252 }
253 }
254 if (mUseCalib) {
255 if (!mTree->GetBranch(mCalibBranchName.c_str())) {
256 throw std::runtime_error("GBT calibration data requested but not found in the tree");
257 }
258 setBranchAddress(mCalibBranchName, mCalibPtr);
259 }
260 LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries";
261}
262
263template <int N>
264std::string DigitReader<N>::getBranchName(const std::string& base, int index)
265{
267 return base;
268 }
269 return base + "_" + std::to_string(index);
270}
271
272template <int N>
273template <typename Ptr>
274void DigitReader<N>::setBranchAddress(const std::string& base, Ptr& addr, int layer)
275{
276 const auto name = getBranchName(base, layer);
277 if (Int_t ret = mTree->SetBranchAddress(name.c_str(), &addr); ret != 0) {
278 LOGP(fatal, "failed to set branch address for {} ret={}", name, ret);
279 }
280}
281
282namespace
283{
284template <int N>
285std::vector<OutputSpec> makeOutChannels(bool mctruth, bool useCalib)
286{
288 std::vector<OutputSpec> outputs;
290 for (int iLayer = 0; iLayer < RLayers; ++iLayer) {
291 outputs.emplace_back(Origin, "DIGITS", iLayer, Lifetime::Timeframe);
292 outputs.emplace_back(Origin, "DIGITSROF", iLayer, Lifetime::Timeframe);
293 if (mctruth) {
294 outputs.emplace_back(Origin, "DIGITSMC2ROF", iLayer, Lifetime::Timeframe);
295 outputs.emplace_back(Origin, "DIGITSMCTR", iLayer, Lifetime::Timeframe);
296 }
297 }
298 if (useCalib) {
299 outputs.emplace_back(Origin, "GBTCALIB", 0, Lifetime::Timeframe);
300 }
301 outputs.emplace_back(Origin, "PHYSTRIG", 0, Lifetime::Timeframe);
302 return outputs;
303}
304} // namespace
305
306DataProcessorSpec getITSDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname)
307{
308 return DataProcessorSpec{
309 .name = "its-digit-reader",
310 .inputs = Inputs{},
311 .outputs = makeOutChannels<o2::detectors::DetID::ITS>(useMC, useCalib),
312 .algorithm = AlgorithmSpec{adaptFromTask<ITSDigitReader>(useMC, useCalib)},
313 .options = Options{
314 {"its-digit-infile", VariantType::String, defname, {"Name of the input digit file"}},
315 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
316}
317
318DataProcessorSpec getMFTDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname)
319{
320 return DataProcessorSpec{
321 .name = "mft-digit-reader",
322 .inputs = Inputs{},
323 .outputs = makeOutChannels<o2::detectors::DetID::MFT>(useMC, useCalib),
324 .algorithm = AlgorithmSpec{adaptFromTask<MFTDigitReader>(useMC, useCalib)},
325 .options = Options{
326 {"mft-digit-infile", VariantType::String, defname, {"Name of the input digit file"}},
327 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
328}
329
330} // namespace itsmft
331} // namespace o2
std::string getName(const TDataMember *dm, int index, int size)
A const (ready only) version of MCTruthContainer.
std::ostringstream debug
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.
Definition of the Names Generator class.
Definition Physics trigger record extracted from the ITS/MFT stream.
static BasicCCDBManager & instance()
A read-only version of MCTruthContainer allowing for storage optimisation.
A container to hold and manage MC truth information/labels.
void addElements(uint32_t dataindex, gsl::span< CompatibleLabel > elements)
size_t flatten_to(ContainerType &container) const
static constexpr ID ITS
Definition DetID.h:63
bool hasOption(const char *key) const
void snapshot(const Output &spec, T const &object)
decltype(auto) make(const Output &spec, Args... args)
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.
static constexpr int getNRUs()
total number of chips
static constexpr Int_t getNRUs()
< total number of RUs
void setBranchAddress(const std::string &base, Ptr &addr, int layer=-1)
std::string getBranchName(const std::string &base, int index)
std::array< std::vector< o2::itsmft::ROFRecord > *, NLayers > mDigROFRec
static constexpr int NLayers
void run(ProcessingContext &pc) final
std::array< o2::dataformats::IOMCTruthContainerView *, NLayers > mPLabels
void init(InitContext &ic) final
void connectTree(const std::string &filename)
std::string mDigitMCTruthBranchName
std::array< std::vector< o2::itsmft::Digit > *, NLayers > mDigits
std::array< std::vector< o2::itsmft::MC2ROFRecord > *, NLayers > mDigMC2ROFs
std::string mDigitMC2ROFBranchName
long check(o2::dataformats::IRFrame fr, size_t bwd=0, size_t fwd=0)
void setSelectedIRFrames(const SPAN &sp, size_t bwd=0, size_t fwd=0, long shift=0, bool removeOverlaps=true)
GLsizeiptr size
Definition glcorearb.h:659
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
constexpr o2::header::DataOrigin gDataOriginMFT
Definition DataHeader.h:572
constexpr o2::header::DataOrigin gDataOriginITS
Definition DataHeader.h:570
Defining PrimaryVertex explicitly as messageable.
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
framework::DataProcessorSpec getITSDigitReaderSpec(bool useMC=true, bool useCalib=false, bool useTriggers=true, std::string defname="o2_itsdigits.root")
framework::DataProcessorSpec getMFTDigitReaderSpec(bool useMC=true, bool useCalib=false, bool useTriggers=true, std::string defname="o2_mftdigits.root")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::string filename()
static constexpr int getNLayers()
static constexpr bool supportsStaggering() noexcept
static std::string rectifyDirectory(const std::string_view p)
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)