Project
Loading...
Searching...
No Matches
ClusterReaderSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 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
18#include "Framework/Logger.h"
19
20#include <algorithm>
21#include <cctype>
22#include <format>
23#include <stdexcept>
24#include <string>
25
26using namespace o2::framework;
27
28namespace o2::trk
29{
30
31namespace
32{
33template <int DetID>
34std::string detName()
35{
37}
38
39template <int DetID>
40std::string lowerName()
41{
42 auto name = detName<DetID>();
43 std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return std::tolower(c); });
44 return name;
45}
46
47template <int DetID>
48std::string branchName(const std::string& base, int layer)
49{
50 return std::format("{}{}_{}", detName<DetID>(), base, layer);
51}
52} // namespace
53
54template <int DetID>
56 : mClusters(NLayers, nullptr), mPatterns(NLayers, nullptr), mROFs(NLayers, nullptr), mLabels(NLayers, nullptr), mUseMC(useMC)
57{
58}
59
60template <int DetID>
62{
63 connectTree(ic.options().get<std::string>((lowerName<DetID>() + "-cluster-infile").c_str()));
64}
65
66template <int DetID>
68{
69 constexpr auto origin = DetID == o2::detectors::DetID::TRK ? o2::header::gDataOriginTRK : o2::header::gDataOriginFT3;
70 const auto entry = mTree->GetReadEntry() + 1;
71 // A timeframe without a collision has no entry: publish empty streams, so
72 // that the consumers still see the timeframe (as the digit reader does).
73 const bool noEntry = entry >= mTree->GetEntries();
74 if (noEntry) {
75 LOG(info) << detName<DetID>() << "ClusterReader: no entry to read, publishing empty output";
76 } else {
77 mTree->GetEntry(entry);
78 }
79 static const std::vector<o2::trkft3::Cluster<DetID>> noClusters;
80 static const std::vector<unsigned char> noPatterns;
81 static const std::vector<o2::trkft3::ROFRecord> noROFs;
83 for (int layer = 0; layer < NLayers; ++layer) {
84 const auto subspec = static_cast<DataAllocator::SubSpecificationType>(layer);
85 const auto& clusters = noEntry ? noClusters : *mClusters[layer];
86 const auto& rofs = noEntry ? noROFs : *mROFs[layer];
87 LOG(info) << detName<DetID>() << "ClusterReader on layer " << layer << " pushes " << clusters.size() << " clusters in " << rofs.size()
88 << " RO frames at entry " << entry;
89 pc.outputs().snapshot(Output{origin, "COMPCLUSTERS", subspec}, clusters);
90 pc.outputs().snapshot(Output{origin, "PATTERNS", subspec}, noEntry ? noPatterns : *mPatterns[layer]);
91 pc.outputs().snapshot(Output{origin, "CLUSTERSROF", subspec}, rofs);
92 if (mUseMC) {
93 pc.outputs().snapshot(Output{origin, "CLUSTERSMCTR", subspec}, noEntry ? noLabels : *mLabels[layer]);
94 }
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 DetID>
103void ClusterReader<DetID>::connectTree(const std::string& filename)
104{
105 mTree.reset();
106 mFile.reset(TFile::Open(filename.c_str()));
107 if (!mFile || mFile->IsZombie()) {
108 throw std::runtime_error(detName<DetID>() + "ClusterReader: cannot open " + filename);
109 }
110 mTree.reset(mFile->Get<TTree>("o2sim"));
111 if (!mTree) {
112 throw std::runtime_error(detName<DetID>() + "ClusterReader: no tree o2sim in " + filename);
113 }
114 for (int layer = 0; layer < NLayers; ++layer) {
115 setBranchAddress("ClusterComp", layer, mClusters[layer]);
116 setBranchAddress("ClusterPatt", layer, mPatterns[layer]);
117 setBranchAddress("ClustersROF", layer, mROFs[layer]);
118 if (mUseMC) {
119 setBranchAddress("ClusterMCTruth", layer, mLabels[layer]);
120 }
121 }
122 LOG(info) << detName<DetID>() << "ClusterReader: " << filename << " with " << mTree->GetEntries() << " entries";
123}
124
125template <int DetID>
126template <typename Ptr>
127void ClusterReader<DetID>::setBranchAddress(const std::string& base, int layer, Ptr& address)
128{
129 const auto name = branchName<DetID>(base, layer);
130 if (!mTree->GetBranch(name.c_str())) {
131 throw std::runtime_error(detName<DetID>() + "ClusterReader: no branch " + name + (base == "ClusterMCTruth" ? " (MC labels requested)" : ""));
132 }
133 if (const Int_t status = mTree->SetBranchAddress(name.c_str(), &address); status != 0) {
134 throw std::runtime_error(std::format("{}ClusterReader: cannot set the address of {} ({})", detName<DetID>(), name, status));
135 }
136}
137
138namespace
139{
140template <int DetID>
141DataProcessorSpec getClusterReaderSpecT(bool useMC, std::string defname)
142{
143 constexpr auto origin = DetID == o2::detectors::DetID::TRK ? o2::header::gDataOriginTRK : o2::header::gDataOriginFT3;
144 std::vector<OutputSpec> outputs;
145 for (int layer = 0; layer < ClusterReader<DetID>::NLayers; ++layer) {
146 outputs.emplace_back(origin, "COMPCLUSTERS", layer, Lifetime::Timeframe);
147 outputs.emplace_back(origin, "PATTERNS", layer, Lifetime::Timeframe);
148 outputs.emplace_back(origin, "CLUSTERSROF", layer, Lifetime::Timeframe);
149 if (useMC) {
150 outputs.emplace_back(origin, "CLUSTERSMCTR", layer, Lifetime::Timeframe);
151 }
152 }
153 return DataProcessorSpec{
154 lowerName<DetID>() + "-cluster-reader",
155 Inputs{},
156 outputs,
157 AlgorithmSpec{adaptFromTask<ClusterReader<DetID>>(useMC)},
158 Options{{lowerName<DetID>() + "-cluster-infile", VariantType::String, std::move(defname), {"Name of the input cluster file"}}}};
159}
160} // namespace
161
162DataProcessorSpec getTRKClusterReaderSpec(bool useMC, std::string defname)
163{
164 return getClusterReaderSpecT<o2::detectors::DetID::TRK>(useMC, std::move(defname));
165}
166
167DataProcessorSpec getFT3ClusterReaderSpec(bool useMC, std::string defname)
168{
169 return getClusterReaderSpecT<o2::detectors::DetID::FT3>(useMC, std::move(defname));
170}
171
172template class ClusterReader<o2::detectors::DetID::TRK>;
173template class ClusterReader<o2::detectors::DetID::FT3>;
174
175} // namespace o2::trk
header::DataOrigin origin
uint32_t c
Definition RawData.h:2
Reads the TRK or FT3 clusters the cluster writer stored, one stream per layer.
A container to hold and manage MC truth information/labels.
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:60
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:148
void snapshot(const Output &spec, T const &object)
o2::header::DataHeader::SubSpecificationType SubSpecificationType
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(framework::ProcessingContext &pc) final
void init(framework::InitContext &ic) final
GLuint GLuint64EXT address
Definition glcorearb.h:5846
GLuint entry
Definition glcorearb.h:5735
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
constexpr o2::header::DataOrigin gDataOriginTRK
Definition DataHeader.h:587
constexpr o2::header::DataOrigin gDataOriginFT3
Definition DataHeader.h:588
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< InputSpec > Inputs
framework::DataProcessorSpec getFT3ClusterReaderSpec(bool useMC=true, std::string defname="o2clus_ft3.root")
framework::DataProcessorSpec getTRKClusterReaderSpec(bool useMC=true, std::string defname="o2clus_trk.root")
The reader of defname, by default the cluster writer's file.
std::string filename()
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters