Project
Loading...
Searching...
No Matches
TrackReaderSpec.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>
20
21using namespace o2::framework;
22
23namespace o2
24{
25namespace tpc
26{
27
29{
30 mUseMC = useMC;
31}
32
34{
35 mInputFileName = o2::utils::Str::concat_string(o2::utils::Str::rectifyDirectory(ic.options().get<std::string>("input-dir")),
36 ic.options().get<std::string>("infile"));
37 mSkipClusRefs = ic.options().get<bool>("skip-clusref");
38 connectTree(mInputFileName);
39}
40
42{
43 auto ent = mTree->GetReadEntry() + 1;
44 // A timeframe holds no collision at all whenever the interaction rate is low enough, and
45 // the tree then has no entry to read. Publish empty containers instead of reading past the
46 // end and pushing branch addresses that GetEntry has not filled, so that the consumers
47 // downstream still see the timeframe. (This used to be an assert, which is compiled out of
48 // every production build since ENABLE_CASSERT defaults to OFF.)
49 const bool noEntry = ent >= mTree->GetEntries();
50 if (noEntry) {
51 LOG(info) << "no entry to read, publishing empty output";
52 } else {
53 accumulate(ent, 1); // to really accumulate all, use accumulate(ent,mTree->GetEntries());
54 }
56 const auto& trackTune = TrackTunePar::Instance();
57 // Normally we should not apply tuning here as with sourceLevelTPC==true it is already applied in the tracking.
58 // Note that there is no way to apply lumi scaling here!!!
59 if ((trackTune.sourceLevelTPC && trackTune.applyWhenReading) &&
60 (trackTune.useTPCInnerCorr || trackTune.useTPCOuterCorr ||
61 trackTune.tpcCovInnerType != TrackTunePar::AddCovType::Disable || trackTune.tpcCovOuterType != TrackTunePar::AddCovType::Disable)) {
62 for (auto& trc : mTracksOut) {
63 if (trc.getNClusters() == 0) {
64 continue; // filtered/reduced track
65 }
66 if (trackTune.useTPCInnerCorr) {
67 trc.updateParams(trackTune.tpcParInner);
68 }
69 if (trackTune.tpcCovInnerType != TrackTunePar::AddCovType::Disable) {
70 trc.updateCov(trackTune.tpcCovInner, trackTune.tpcCovInnerType == TrackTunePar::AddCovType::WithCorrelations);
71 }
72 if (trackTune.useTPCOuterCorr) {
73 trc.getParamOut().updateParams(trackTune.tpcParOuter);
74 }
75 if (trackTune.tpcCovOuterType != TrackTunePar::AddCovType::Disable) {
76 trc.getParamOut().updateCov(trackTune.tpcCovOuter, trackTune.tpcCovOuterType == TrackTunePar::AddCovType::WithCorrelations);
77 }
78 }
79 }
80
81 pc.outputs().snapshot(Output{"TPC", "TRACKS", 0}, mTracksOut);
82 pc.outputs().snapshot(Output{"TPC", "CLUSREFS", 0}, mCluRefVecOut);
83 if (mUseMC) {
84 pc.outputs().snapshot(Output{"TPC", "TRACKSMCLBL", 0}, mMCTruthOut);
85 }
86 if (noEntry || mTree->GetReadEntry() + 1 >= mTree->GetEntries()) {
87 pc.services().get<ControlService>().endOfStream();
88 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
89 }
90}
91
92void TrackReader::accumulate(int from, int n)
93{
94 assert(from + n <= mTree->GetEntries());
95 if (n == 1) {
96 mTree->GetEntry(from);
97 mTracksOut.swap(*mTracksInp);
98 mCluRefVecOut.swap(*mCluRefVecInp);
99 if (mUseMC) {
100 std::copy(mMCTruthInp->begin(), mMCTruthInp->end(), std::back_inserter(mMCTruthOut));
101 }
102 } else {
103 for (int iev = 0; iev < n; iev++) {
104 mTree->GetEntry(from + iev);
105 //
106 uint32_t shift = mCluRefVecOut.size(); // during accumulation clusters refs need to be shifted
107
108 auto cl0 = mCluRefVecInp->begin();
109 auto cl1 = mCluRefVecInp->end();
110 std::copy(cl0, cl1, std::back_inserter(mCluRefVecOut));
111
112 auto tr0 = mTracksInp->begin();
113 auto tr1 = mTracksInp->end();
114 // fix cluster references
115 if (shift) {
116 for (auto tr = tr0; tr != tr1; tr++) {
117 tr->shiftFirstClusterRef(shift);
118 }
119 }
120 std::copy(tr0, tr1, std::back_inserter(mTracksOut));
121 // MC
122 if (mUseMC) {
123 std::copy(mMCTruthInp->begin(), mMCTruthInp->end(), std::back_inserter(mMCTruthOut));
124 }
125 }
126 }
127 LOG(info) << "TPCTrackReader pushes " << mTracksOut.size() << " tracks from entries " << from << " : " << from + n - 1;
128}
129
130void TrackReader::connectTree(const std::string& filename)
131{
132 mTree.reset(nullptr); // in case it was already loaded
133 mFile.reset(TFile::Open(filename.c_str()));
134 if (!(mFile && !mFile->IsZombie())) {
135 throw std::runtime_error("Error opening tree file");
136 }
137 mTree.reset((TTree*)mFile->Get(mTrackTreeName.c_str()));
138 if (!mTree) {
139 throw std::runtime_error("Error opening tree");
140 }
141
142 mTree->SetBranchAddress(mTrackBranchName.c_str(), &mTracksInp);
143 if (!mSkipClusRefs) {
144 mTree->SetBranchAddress(mClusRefBranchName.c_str(), &mCluRefVecInp);
145 } else {
146 mCluRefVecInp = new std::vector<o2::tpc::TPCClRefElem>;
147 }
148 if (mUseMC) {
149 if (mTree->GetBranch(mTrackMCTruthBranchName.c_str())) {
150 mTree->SetBranchAddress(mTrackMCTruthBranchName.c_str(), &mMCTruthInp);
151 LOG(info) << "Will use MC-truth from " << mTrackMCTruthBranchName;
152 } else {
153 LOG(info) << "MC-truth is missing";
154 mUseMC = false;
155 }
156 }
157 LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries";
158}
159
161{
162 std::vector<OutputSpec> outputSpec;
163 outputSpec.emplace_back("TPC", "TRACKS", 0, Lifetime::Timeframe);
164 outputSpec.emplace_back("TPC", "CLUSREFS", 0, Lifetime::Timeframe);
165 if (useMC) {
166 outputSpec.emplace_back("TPC", "TRACKSMCLBL", 0, Lifetime::Timeframe);
167 }
168
169 return DataProcessorSpec{
170 "tpc-track-reader",
171 Inputs{},
172 outputSpec,
173 AlgorithmSpec{adaptFromTask<TrackReader>(useMC)},
174 Options{
175 {"infile", VariantType::String, "tpctracks.root", {"Name of the input track file"}},
176 {"input-dir", VariantType::String, "none", {"Input directory"}},
177 {"skip-clusref", VariantType::Bool, false, {"Skip reading cluster references"}}}};
178}
179
180} // namespace tpc
181} // namespace o2
Definition of the Names Generator class.
Configurable params for tracks ad hoc tuning.
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 init(InitContext &ic) final
void run(ProcessingContext &pc) final
TrackReader(bool useMC=true)
GLdouble n
Definition glcorearb.h:1982
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
framework::DataProcessorSpec getTPCTrackReaderSpec(bool useMC=true)
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"