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 "TFile.h"
15#include "TTree.h"
18#include "Headers/DataHeader.h"
25#include "Framework/Task.h"
28#include "Framework/Logger.h"
29#include <vector>
30
31using namespace o2::framework;
32
33namespace o2
34{
35namespace ctp
36{
37
38class DigitReader : public Task
39{
40 public:
41 DigitReader() = delete;
42 DigitReader(bool useMC);
43 ~DigitReader() override = default;
44 void init(InitContext& ic) final;
45 void run(ProcessingContext& pc) final;
46
47 protected:
48 void connectTree(const std::string& filename);
49
50 std::vector<o2::ctp::CTPDigit> mDigits, *mDigitsPtr = &mDigits;
52 std::unique_ptr<TFile> mFile;
53 std::unique_ptr<TTree> mTree;
54
55 bool mUseMC = false; // use MC truth
56 bool mUseIRFrames = false; // selected IRFrames mode
57 std::string mDigTreeName = "o2sim";
58 std::string mDigitBranchName = "CTPDigits";
59 std::string mLumiBranchName = "CTPLumi";
60};
61
63{
64 if (useMC) {
65 LOG(info) << "CTP : truth = data as CTP inputs are already digital";
66 }
67}
68
70{
72 ic.options().get<std::string>("ctp-digit-infile"));
73 if (ic.options().hasOption("ignore-irframes") && !ic.options().get<bool>("ignore-irframes")) {
74 mUseIRFrames = true;
75 }
77}
78
80{
81 gsl::span<const o2::dataformats::IRFrame> irFrames{};
82 // LOG(info) << "Using IRs:" << mUseIRFrames;
83 if (mUseIRFrames) {
84 irFrames = pc.inputs().get<gsl::span<o2::dataformats::IRFrame>>("driverInfo");
85 }
86 auto ent = mTree->GetReadEntry();
87 if (!mUseIRFrames) {
88 ent++;
89 // A timeframe holds no collision at all whenever the interaction rate is low enough, and
90 // the tree then has no entry to read. Publish empty containers instead of reading past the
91 // end and pushing branch addresses that GetEntry has not filled, so that the consumers
92 // downstream still see the timeframe. (This used to be an assert, which is compiled out of
93 // every production build since ENABLE_CASSERT defaults to OFF.)
94 const bool noEntry = ent >= mTree->GetEntries();
95 if (noEntry) {
96 LOG(info) << "no entry to read, publishing empty output";
97 } else {
98 mTree->GetEntry(ent);
99 }
100 LOG(info) << "DigitReader pushes " << mDigits.size() << " digits at entry " << ent;
101 pc.outputs().snapshot(Output{"CTP", "DIGITS", 0}, mDigits);
102 pc.outputs().snapshot(Output{"CTP", "LUMI", 0}, mLumi);
103 if (noEntry || mTree->GetReadEntry() + 1 >= mTree->GetEntries()) {
105 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
106 }
107 } else {
108 std::vector<o2::ctp::CTPDigit> digitSel;
109 if (irFrames.size()) { // we assume the IRFrames are in the increasing order
110 if (ent < 0) {
111 ent++;
112 }
114 // MC digits are already aligned
115 irfSel.setSelectedIRFrames(irFrames, 0, 0, 0, true);
116 const auto irMin = irfSel.getIRFrames().front().getMin(); // use processed IRframes for rough comparisons (possible shift!)
117 const auto irMax = irfSel.getIRFrames().back().getMax();
118 LOGP(info, "Selecting IRFrame {}-{}", irMin.asString(), irMax.asString());
119 while (ent < mTree->GetEntries()) {
120 if (ent > mTree->GetReadEntry()) {
121 mTree->GetEntry(ent);
122 }
123 if (mDigits.front().intRecord <= irMax && mDigits.back().intRecord >= irMin) { // THere is overlap
124 for (int i = 0; i < (int)mDigits.size(); i++) {
125 const auto& dig = mDigits[i];
126 // if(irfSel.check(dig.intRecord)) { // adding selected digit
127 if (dig.intRecord >= irMin && dig.intRecord <= irMax) {
128 digitSel.push_back(dig);
129 LOG(info) << "adding:" << dig.intRecord << " ent:" << ent;
130 }
131 }
132 }
133 if (mDigits.back().intRecord < irMax) { // need to check the next entry
134 ent++;
135 continue;
136 }
137 break; // push collected data
138 }
139 }
140 pc.outputs().snapshot(Output{"CTP", "DIGITS", 0}, digitSel);
141 pc.outputs().snapshot(Output{"CTP", "LUMI", 0}, mLumi); // add full lumi for this TF
142 if (!irFrames.size() || irFrames.back().isLast()) {
144 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
145 }
146 }
147}
148
149void DigitReader::connectTree(const std::string& filename)
150{
151 mTree.reset(nullptr); // in case it was already loaded
152 mFile.reset(TFile::Open(filename.c_str()));
153 assert(mFile && !mFile->IsZombie());
154 mTree.reset((TTree*)mFile->Get(mDigTreeName.c_str()));
155 assert(mTree);
156 if (mTree->GetBranch(mDigitBranchName.c_str())) {
157 mTree->SetBranchAddress(mDigitBranchName.c_str(), &mDigitsPtr);
158 } else {
159 LOGP(warn, "Digits branch {} is absent", mDigitBranchName);
160 }
161 if (mTree->GetBranch(mLumiBranchName.c_str())) {
162 mTree->SetBranchAddress(mLumiBranchName.c_str(), &mLumiPtr);
163 } else {
164 LOGP(warn, "Lumi branch {} is absent", mLumiBranchName);
165 }
166 mTree->SetBranchAddress(mDigitBranchName.c_str(), &mDigitsPtr);
167 LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries";
168}
169
170DataProcessorSpec getDigitsReaderSpec(bool useMC, const std::string& defFile)
171{
172 return DataProcessorSpec{
173 "ctp-digit-reader",
174 Inputs{},
175 Outputs{{"CTP", "DIGITS", 0, Lifetime::Timeframe},
176 {"CTP", "LUMI", 0, o2::framework::Lifetime::Timeframe}},
177 AlgorithmSpec{adaptFromTask<DigitReader>(useMC)},
178 Options{
179 {"ctp-digit-infile", VariantType::String, defFile, {"Name of the input digit file"}},
180 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
181}
182
183} // namespace ctp
184
185} // namespace o2
A const (ready only) version of MCTruthContainer.
definition of CTPDigit, CTPInputDigit
int32_t i
Class to check if give InteractionRecord or IRFrame is selected by the external IRFrame vector.
Definition of the Names Generator class.
std::vector< o2::ctp::CTPDigit > mDigits
void init(InitContext &ic) final
std::unique_ptr< TFile > mFile
~DigitReader() override=default
std::unique_ptr< TTree > mTree
o2::ctp::LumiInfo mLumi
void run(ProcessingContext &pc) final
std::vector< o2::ctp::CTPDigit > * mDigitsPtr
void connectTree(const std::string &filename)
o2::ctp::LumiInfo * mLumiPtr
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.
virtual void endOfStream(EndOfStreamContext &context)
This is invoked whenever we have an EndOfStream event.
Definition Task.h:43
void setSelectedIRFrames(const SPAN &sp, size_t bwd=0, size_t fwd=0, long shift=0, bool removeOverlaps=true)
framework::DataProcessorSpec getDigitsReaderSpec(bool propagateMC=true, const std::string &defFile="ctpdigits.root")
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string filename()
static std::string rectifyDirectory(const std::string_view p)
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"