Project
Loading...
Searching...
No Matches
ClusterReaderSpec.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#include <cassert>
16
17#include <TTree.h>
18
21#include "Framework/Logger.h"
26
27using namespace o2::framework;
28using namespace o2::itsmft;
29
30namespace o2
31{
32namespace itsmft
33{
34
35template <int N>
36ClusterReader<N>::ClusterReader(bool useMC, bool doStag, bool usePatterns, bool triggerOut) : mUseMC(useMC), mUsePatterns(usePatterns), mTriggerOut(triggerOut), mDetName(Origin.as<std::string>()), mDetNameLC(mDetName)
37{
38 std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower);
39 if (doStag) {
41 mClusROFRec.resize(mLayers, nullptr);
42 mClusterCompArray.resize(mLayers, nullptr);
43 mPatternsArray.resize(mLayers, nullptr);
44 mClusterMCTruth.resize(mLayers, nullptr);
45 }
46}
48template <int N>
50{
52 ic.options().get<std::string>((mDetNameLC + "-cluster-infile").c_str()));
53 connectTree(mFileName);
55
56template <int N>
58{
59 auto ent = mTree->GetReadEntry() + 1;
60 // A timeframe holds no collision at all whenever the interaction rate is low enough, and
61 // the tree then has no entry to read. Publish empty containers instead of reading past the
62 // end and pushing branch addresses that GetEntry has not filled, so that the consumers
63 // downstream still see the timeframe. (This used to be an assert, which is compiled out of
64 // every production build since ENABLE_CASSERT defaults to OFF.)
65 const bool noEntry = ent >= mTree->GetEntries();
66 if (noEntry) {
67 LOG(info) << "no entry to read, publishing empty output";
68 } else {
69 mTree->GetEntry(ent);
70 }
71
72 static const std::vector<o2::itsmft::ROFRecord> noClusROFRec;
73 static const std::vector<o2::itsmft::CompClusterExt> noClusters;
74 static const std::vector<unsigned char> noPatterns;
76 for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) {
77 const auto& clusROFRec = noEntry ? noClusROFRec : *mClusROFRec[iLayer];
78 const auto& clusters = noEntry ? noClusters : *mClusterCompArray[iLayer];
79 LOG(info) << mDetName << "ClusterReader" << (mDoStaggering ? std::format(" on layer {}", iLayer) : "") << " pushes " << clusROFRec.size() << " ROFRecords, " << clusters.size() << " compact clusters at entry " << ent;
80 pc.outputs().snapshot(Output{Origin, "CLUSTERSROF", iLayer}, clusROFRec);
81 pc.outputs().snapshot(Output{Origin, "COMPCLUSTERS", iLayer}, clusters);
82 if (mUsePatterns) {
83 pc.outputs().snapshot(Output{Origin, "PATTERNS", iLayer}, noEntry ? noPatterns : *mPatternsArray[iLayer]);
84 }
85 if (mUseMC) {
86 pc.outputs().snapshot(Output{Origin, "CLUSTERSMCTR", iLayer}, noEntry ? noLabels : *mClusterMCTruth[iLayer]);
87 // read dummy MC2ROF vector to keep writer/readers backward compatible
88 static std::vector<o2::itsmft::MC2ROFRecord> dummyMC2ROF;
89 pc.outputs().snapshot(Output{Origin, "CLUSTERSMC2ROF", iLayer}, dummyMC2ROF);
90 }
91 }
92 if (mTriggerOut) {
93 std::vector<o2::itsmft::PhysTrigger> dummyTrig;
94 pc.outputs().snapshot(Output{Origin, "PHYSTRIG", 0}, dummyTrig);
95 }
96 if (noEntry || mTree->GetReadEntry() + 1 >= mTree->GetEntries()) {
97 pc.services().get<ControlService>().endOfStream();
98 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
99 }
100}
101
102template <int N>
104{
105 mTree.reset(nullptr); // in case it was already loaded
106 mFile.reset(TFile::Open(filename.c_str()));
107 assert(mFile && !mFile->IsZombie());
108 mTree.reset((TTree*)mFile->Get(mClusTreeName.c_str()));
109 assert(mTree);
110
111 for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) {
112 setBranchAddress(mClusROFBranchName, mClusROFRec[iLayer], iLayer);
113 setBranchAddress(mClusterCompBranchName, mClusterCompArray[iLayer], iLayer);
114 if (mUsePatterns) {
115 setBranchAddress(mClusterPattBranchName, mPatternsArray[iLayer], iLayer);
116 }
117 if (mUseMC) {
118 if (mTree->GetBranch(getBranchName(mClustMCTruthBranchName, iLayer).c_str())) {
119 setBranchAddress(mClustMCTruthBranchName, mClusterMCTruth[iLayer], iLayer);
120 } else {
121 LOG(info) << "MC-truth is missing";
122 mUseMC = false;
123 }
124 }
125 }
126 LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries";
127}
128
129template <int N>
130std::string ClusterReader<N>::getBranchName(const std::string& base, int index) const
131{
132 if (mDoStaggering) {
133 return mDetName + base + "_" + std::to_string(index);
134 }
135 return mDetName + base;
136}
137
138template <int N>
139template <typename Ptr>
140void ClusterReader<N>::setBranchAddress(const std::string& base, Ptr& addr, int layer)
141{
142 const auto name = getBranchName(base, layer);
143 if (Int_t ret = mTree->SetBranchAddress(name.c_str(), &addr); ret != 0) {
144 LOGP(fatal, "failed to set branch address for {} ret={}", name, ret);
145 }
146}
147
148namespace
149{
150template <int N>
151std::vector<OutputSpec> makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth, bool doStag, bool usePatterns, bool triggerOut)
152{
153 std::vector<OutputSpec> outputs;
154 for (uint32_t iLayer = 0; iLayer < ((doStag) ? o2::itsmft::DPLAlpideParam<N>::getNLayers() : 1); ++iLayer) {
155 outputs.emplace_back(detOrig, "CLUSTERSROF", iLayer, Lifetime::Timeframe);
156 outputs.emplace_back(detOrig, "COMPCLUSTERS", iLayer, Lifetime::Timeframe);
157 if (usePatterns) {
158 outputs.emplace_back(detOrig, "PATTERNS", iLayer, Lifetime::Timeframe);
159 }
160 if (mctruth) {
161 outputs.emplace_back(detOrig, "CLUSTERSMCTR", iLayer, Lifetime::Timeframe);
162 outputs.emplace_back(detOrig, "CLUSTERSMC2ROF", iLayer, Lifetime::Timeframe);
163 }
164 }
165 if (triggerOut) {
166 outputs.emplace_back(detOrig, "PHYSTRIG", 0, Lifetime::Timeframe);
167 }
168 return outputs;
169}
170} // namespace
171
172DataProcessorSpec getITSClusterReaderSpec(bool useMC, bool doStag, bool usePatterns, bool triggerOut)
173{
174 return DataProcessorSpec{
175 .name = "its-cluster-reader",
176 .inputs = Inputs{},
177 .outputs = makeOutChannels<o2::detectors::DetID::ITS>("ITS", useMC, doStag, usePatterns, triggerOut),
178 .algorithm = AlgorithmSpec{adaptFromTask<ITSClusterReader>(useMC, doStag, usePatterns, triggerOut)},
179 .options = Options{
180 {"its-cluster-infile", VariantType::String, "o2clus_its.root", {"Name of the input cluster file"}},
181 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
182}
183
184DataProcessorSpec getMFTClusterReaderSpec(bool useMC, bool doStag, bool usePatterns, bool triggerOut)
185{
186 return DataProcessorSpec{
187 .name = "mft-cluster-reader",
188 .inputs = Inputs{},
189 .outputs = makeOutChannels<o2::detectors::DetID::MFT>("MFT", useMC, doStag, usePatterns, triggerOut),
190 .algorithm = AlgorithmSpec{adaptFromTask<MFTClusterReader>(useMC, doStag, usePatterns, triggerOut)},
191 .options = Options{
192 {"mft-cluster-infile", VariantType::String, "mftclusters.root", {"Name of the input cluster file"}},
193 {"input-dir", VariantType::String, "none", {"Input directory"}}}};
194}
195
196} // namespace itsmft
197} // namespace o2
Definition of the Names Generator class.
Definition Physics trigger record extracted from the ITS/MFT stream.
A container to hold and manage MC truth information/labels.
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
ServiceRegistryRef services()
The services registry associated with this processing context.
void run(ProcessingContext &pc) final
std::string getBranchName(const std::string &base, int index) const
std::vector< std::vector< o2::itsmft::CompClusterExt > * > mClusterCompArray
void connectTree(const std::string &filename)
std::vector< std::vector< unsigned char > * > mPatternsArray
void init(InitContext &ic) final
void setBranchAddress(const std::string &base, Ptr &addr, int layer)
std::vector< std::vector< o2::itsmft::ROFRecord > * > mClusROFRec
std::vector< o2::dataformats::MCTruthContainer< o2::MCCompLabel > * > mClusterMCTruth
GLsizei const GLchar *const * string
Definition glcorearb.h:809
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
framework::DataProcessorSpec getMFTClusterReaderSpec(bool useMC=true, bool doStag=false, bool usePatterns=true, bool useTriggers=true)
framework::DataProcessorSpec getITSClusterReaderSpec(bool useMC=true, bool doStag=false, bool usePatterns=true, bool useTriggers=true)
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 std::string rectifyDirectory(const std::string_view p)
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters