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 <vector>
15
16#include "TTree.h"
17
20#include "Framework/Logger.h"
32#include <cassert>
33
34using namespace o2::framework;
35using namespace o2::itsmft;
36
37namespace o2
38{
39namespace itsmft
40{
41
42DigitReader::DigitReader(o2::detectors::DetID id, bool useMC, bool useCalib, bool triggerOut)
43{
45 mDetNameLC = mDetName = id.getName();
46 mDigTreeName = "o2sim";
47
51
54 mTriggerOut = triggerOut;
55 mUseMC = useMC;
56 mUseCalib = useCalib;
57 std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower);
58}
59
61{
63 ic.options().get<std::string>((mDetNameLC + "-digit-infile").c_str()));
64 if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
65 mUseIRFrames = true;
66 }
68}
69
71{
72 const auto& tinfo = pc.services().get<o2::framework::TimingInfo>();
73 if (tinfo.globalRunNumberChanged && mUseIRFrames) { // new run is starting: 1st call
74 // TODO: we have to find a way define CCDBInput for IRFrames mode only using DPL fetcher
76 auto rlim = ccdb.getRunDuration(tinfo.runNumber);
77 long ts = (rlim.first + rlim.second) / 2;
79 ccdb.getForTimeStamp<o2::itsmft::DPLAlpideParam<o2::detectors::DetID::ITS>>("ITS/Config/AlpideParam", ts);
81 mROFBiasInBC = alpideParam.roFrameBiasInBC;
84 } else {
85 ccdb.getForTimeStamp<o2::itsmft::DPLAlpideParam<o2::detectors::DetID::MFT>>("MFT/Config/AlpideParam", ts);
87 mROFBiasInBC = alpideParam.roFrameBiasInBC;
90 }
91 }
92 gsl::span<const o2::dataformats::IRFrame> irFrames{};
93 if (mUseIRFrames) {
94 irFrames = pc.inputs().get<gsl::span<o2::dataformats::IRFrame>>("driverInfo");
95 }
96 static o2::dataformats::IOMCTruthContainerView* plabels = nullptr;
97 if (mUseMC && !plabels) {
98 mTree->SetBranchAddress(mDigtMCTruthBranchName.c_str(), &plabels);
99 }
100 auto ent = mTree->GetReadEntry();
101
102 if (!mUseIRFrames) {
103 ent++;
104 assert(ent < mTree->GetEntries()); // this should not happen
105 mTree->GetEntry(ent);
106 LOG(info) << mDetName << "DigitReader pushes " << mDigROFRec.size() << " ROFRecords, " << mDigits.size() << " digits at entry " << ent;
107 pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mDigROFRec);
108 pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits);
109 if (mUseCalib) {
110 pc.outputs().snapshot(Output{mOrigin, "GBTCALIB", 0}, mCalib);
111 }
112 if (mTriggerOut) {
113 std::vector<o2::itsmft::PhysTrigger> dummyTrig;
114 pc.outputs().snapshot(Output{mOrigin, "PHYSTRIG", 0}, dummyTrig);
115 }
116 if (mUseMC) {
117 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{mOrigin, "DIGITSMCTR", 0});
118 plabels->copyandflatten(sharedlabels);
119 delete plabels;
120 plabels = nullptr;
121 pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, mDigMC2ROFs);
122 }
123 if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) {
125 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
126 }
127 } else { // need to select particulars IRs range, presumably from the same tree entry
128 std::vector<o2::itsmft::Digit> digitsSel;
129 std::vector<o2::itsmft::GBTCalibData> calibSel;
130 std::vector<o2::itsmft::ROFRecord> digROFRecSel;
131 std::vector<o2::itsmft::MC2ROFRecord> digMC2ROFsSel;
133
134 if (irFrames.size()) { // we assume the IRFrames are in the increasing order
135 if (ent < 0) {
136 ent++;
137 }
139 irfSel.setSelectedIRFrames(irFrames, 0, 0, -mROFBiasInBC, true);
140 const auto irMin = irfSel.getIRFrames().front().getMin(); // use processed IRframes for rough comparisons (possible shift!)
141 const auto irMax = irfSel.getIRFrames().back().getMax();
142 LOGP(info, "Selecting IRFrame {}-{}", irMin.asString(), irMax.asString());
143 while (ent < mTree->GetEntries()) {
144 // do we need to read a new entry?
145 if (ent > mTree->GetReadEntry()) {
146 if (mUseMC) {
147 delete plabels;
148 plabels = nullptr;
149 mConstLabels.clear();
150 mTree->SetBranchAddress(mDigtMCTruthBranchName.c_str(), &plabels);
151 }
152 mTree->GetEntry(ent);
153 if (mUseMC) {
155 delete plabels;
156 plabels = nullptr;
157 }
158 }
159 std::vector<int> rofOld2New;
160 rofOld2New.resize(mDigROFRec.size(), -1);
161
162 if (mDigROFRec.front().getBCData() <= irMax && (mDigROFRec.back().getBCData() + mROFLengthInBC - 1) >= irMin) { // there is an overlap
163 for (int irof = 0; irof < (int)mDigROFRec.size(); irof++) {
164 const auto& rof = mDigROFRec[irof];
165 if (irfSel.check({rof.getBCData(), rof.getBCData() + mROFLengthInBC - 1}) != -1) {
166 rofOld2New[irof] = (int)digROFRecSel.size();
167 LOGP(debug, "Adding selected ROF {}", rof.getBCData().asString());
168 digROFRecSel.push_back(rof);
169 int offs = digitsSel.size();
170 digROFRecSel.back().setFirstEntry(offs);
171 std::copy(mDigits.begin() + rof.getFirstEntry(), mDigits.begin() + rof.getFirstEntry() + rof.getNEntries(), std::back_inserter(digitsSel));
172 for (int id = 0; id < rof.getNEntries(); id++) { // copy MC info
173 digitLabelsSel.addElements(id + offs, mConstLabels.getLabels(id + rof.getFirstEntry()));
174 }
175 if (mCalib.size() >= size_t((irof + 1) * mNRUs)) {
176 std::copy(mCalib.begin() + irof * mNRUs, mCalib.begin() + (irof + 1) * mNRUs, std::back_inserter(calibSel));
177 }
178 }
179 }
180 }
181 if (mUseMC) {
182 digMC2ROFsSel = mDigMC2ROFs;
183 for (auto& mc2rof : digMC2ROFsSel) {
184 if (mc2rof.rofRecordID < 0) {
185 continue; // did not contribute even to the original data
186 }
187 unsigned int mn = 0xffff, mx = 0;
188 for (int ir = mc2rof.minROF; ir <= mc2rof.maxROF; ir++) {
189 if (rofOld2New[ir] >= 0) { // used
190 mx = rofOld2New[ir];
191 if (mn > mx) {
192 mn = mx;
193 }
194 }
195 }
196 mc2rof.rofRecordID = mn == 0xffff ? -1 : int(mn);
197 mc2rof.minROF = mn;
198 mc2rof.maxROF = mx;
199 }
200 }
201 if (mDigROFRec.back().getBCData() + mROFLengthInBC - 1 < irMax) { // need to check the next entry
202 ent++;
203 continue;
204 }
205 break; // push collected data
206 }
207 }
208 pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, digROFRecSel);
209 pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, digitsSel);
210 if (mUseCalib) {
211 pc.outputs().snapshot(Output{mOrigin, "GBTCALIB", 0}, calibSel);
212 }
213 if (mTriggerOut) {
214 std::vector<o2::itsmft::PhysTrigger> dummyTrig;
215 pc.outputs().snapshot(Output{mOrigin, "PHYSTRIG", 0}, dummyTrig);
216 }
217 if (mUseMC) {
218 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{mOrigin, "DIGITSMCTR", 0});
219 digitLabelsSel.flatten_to(sharedlabels);
220 pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, digMC2ROFsSel);
221 }
222
223 if (!irFrames.size() || irFrames.back().isLast()) {
225 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
226 }
227 }
228}
229
230void DigitReader::connectTree(const std::string& filename)
231{
232 mTree.reset(nullptr); // in case it was already loaded
233 mFile.reset(TFile::Open(filename.c_str()));
234 assert(mFile && !mFile->IsZombie());
235 mTree.reset((TTree*)mFile->Get(mDigTreeName.c_str()));
236 assert(mTree);
237
238 mTree->SetBranchAddress(mDigROFBranchName.c_str(), &mDigROFRecPtr);
239 mTree->SetBranchAddress(mDigitBranchName.c_str(), &mDigitsPtr);
240 if (mUseCalib) {
241 if (!mTree->GetBranch(mCalibBranchName.c_str())) {
242 throw std::runtime_error("GBT calibration data requested but not found in the tree");
243 }
244 mTree->SetBranchAddress(mCalibBranchName.c_str(), &mCalibPtr);
245 }
246 if (mUseMC) {
247 if (!mTree->GetBranch(mDigtMC2ROFBranchName.c_str()) || !mTree->GetBranch(mDigtMCTruthBranchName.c_str())) {
248 throw std::runtime_error("MC data requested but not found in the tree");
249 }
250 mTree->SetBranchAddress(mDigtMC2ROFBranchName.c_str(), &mDigMC2ROFsPtr);
251 }
252 LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries";
253}
254
255DataProcessorSpec getITSDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname)
256{
257 std::vector<OutputSpec> outputSpec;
258 outputSpec.emplace_back("ITS", "DIGITS", 0, Lifetime::Timeframe);
259 outputSpec.emplace_back("ITS", "DIGITSROF", 0, Lifetime::Timeframe);
260 if (useCalib) {
261 outputSpec.emplace_back("ITS", "GBTCALIB", 0, Lifetime::Timeframe);
262 }
263 if (useMC) {
264 outputSpec.emplace_back("ITS", "DIGITSMCTR", 0, Lifetime::Timeframe);
265 outputSpec.emplace_back("ITS", "DIGITSMC2ROF", 0, Lifetime::Timeframe);
266 }
267 if (useTriggers) {
268 outputSpec.emplace_back("ITS", "PHYSTRIG", 0, Lifetime::Timeframe);
269 }
270 return DataProcessorSpec{
271 "its-digit-reader",
272 Inputs{},
273 outputSpec,
274 AlgorithmSpec{adaptFromTask<ITSDigitReader>(useMC, useCalib)},
275 Options{
276 {"its-digit-infile", VariantType::String, defname, {"Name of the input digit file"}},
277 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
278}
279
280DataProcessorSpec getMFTDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname)
281{
282 std::vector<OutputSpec> outputSpec;
283 outputSpec.emplace_back("MFT", "DIGITS", 0, Lifetime::Timeframe);
284 outputSpec.emplace_back("MFT", "DIGITSROF", 0, Lifetime::Timeframe);
285 if (useCalib) {
286 outputSpec.emplace_back("MFT", "GBTCALIB", 0, Lifetime::Timeframe);
287 }
288 if (useMC) {
289 outputSpec.emplace_back("MFT", "DIGITSMCTR", 0, Lifetime::Timeframe);
290 outputSpec.emplace_back("MFT", "DIGITSMC2ROF", 0, Lifetime::Timeframe);
291 }
292 if (useTriggers) {
293 outputSpec.emplace_back("MFT", "PHYSTRIG", 0, Lifetime::Timeframe);
294 }
295 return DataProcessorSpec{
296 "mft-digit-reader",
297 Inputs{},
298 outputSpec,
299 AlgorithmSpec{adaptFromTask<MFTDigitReader>(useMC, useCalib)},
300 Options{
301 {"mft-digit-infile", VariantType::String, defname, {"Name of the input digit file"}},
302 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
303}
304
305} // namespace itsmft
306} // namespace o2
A const (ready only) version of MCTruthContainer.
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.
std::ostringstream debug
static BasicCCDBManager & instance()
A read-only version of MCTruthContainer allowing for storage optimisation.
gsl::span< const TruthElement > getLabels(uint32_t dataindex) const
void copyandflatten(std::vector< char, Alloc > &output) const
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 class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID MFT
Definition DetID.h:71
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.
virtual void endOfStream(EndOfStreamContext &context)
This is invoked whenever we have an EndOfStream event.
Definition Task.h:43
static constexpr int getNRUs()
total number of chips
static constexpr Int_t getNRUs()
< total number of RUs
void connectTree(const std::string &filename)
void init(InitContext &ic) final
o2::header::DataOrigin mOrigin
std::vector< o2::itsmft::MC2ROFRecord > mDigMC2ROFs
std::vector< o2::itsmft::GBTCalibData > * mCalibPtr
std::vector< o2::itsmft::GBTCalibData > mCalib
std::unique_ptr< TTree > mTree
std::vector< o2::itsmft::Digit > mDigits
std::string mDigtMC2ROFBranchName
void run(ProcessingContext &pc) final
std::vector< o2::itsmft::ROFRecord > mDigROFRec
std::vector< o2::itsmft::MC2ROFRecord > * mDigMC2ROFsPtr
std::vector< o2::itsmft::ROFRecord > * mDigROFRecPtr
o2::dataformats::ConstMCTruthContainer< o2::MCCompLabel > mConstLabels
std::unique_ptr< TFile > mFile
std::string mDigtMCTruthBranchName
std::vector< o2::itsmft::Digit > * mDigitsPtr
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)
constexpr o2::header::DataOrigin gDataOriginITS
Definition DataHeader.h:570
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
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 filename()
int roFrameBiasInBC
bias of the start of ROF wrt orbit start: t_irof = (irof*roFrameLengthInBC + roFrameBiasInBC)*BClengt...
int roFrameLengthInBC
ROF length in BC for continuos mode.
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)