Project
Loading...
Searching...
No Matches
ClusterFinderOriginalSpec.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
16
18
19#include <iostream>
20#include <fstream>
21#include <chrono>
22#include <vector>
23#include <stdexcept>
24#include <string>
25
26#include <gsl/span>
27
32#include "Framework/Lifetime.h"
33#include "Framework/Output.h"
34#include "Framework/Task.h"
35#include "Framework/Logger.h"
36
41#include "MCHBase/Error.h"
42#include "MCHBase/ErrorMap.h"
43#include "MCHBase/PreCluster.h"
48
49namespace o2
50{
51namespace mch
52{
53
54using namespace std;
55using namespace o2::framework;
56
58{
59 public:
60 //_________________________________________________________________________________________________
62 {
64 LOG(info) << "initializing cluster finder";
65
66 auto config = ic.options().get<std::string>("mch-config");
67 if (!config.empty()) {
68 o2::conf::ConfigurableParam::updateFromFile(config, "MCHClustering", true);
69 }
70 bool run2Config = ic.options().get<bool>("run2-config");
71 mClusterFinder.init(run2Config);
72
73 mAttachInitalPrecluster = ic.options().get<bool>("attach-initial-precluster");
74
76 ic.services().get<CallbackService>().set<CallbackService::Id::Stop>([this]() {
77 LOG(info) << "cluster finder duration = " << mTimeClusterFinder.count() << " s";
78 mErrorMap.forEach([](Error error) {
79 LOGP(warning, fmt::runtime(error.asString()));
80 });
81 this->mClusterFinder.deinit();
82 });
83 }
84
85 //_________________________________________________________________________________________________
87 {
89
90 // get the input preclusters and associated digits
91 auto preClusterROFs = pc.inputs().get<gsl::span<ROFRecord>>("preclusterrofs");
92 auto preClusters = pc.inputs().get<gsl::span<PreCluster>>("preclusters");
93 auto digits = pc.inputs().get<gsl::span<Digit>>("digits");
94
95 // create the output messages for clusters and attached digits
96 auto& clusterROFs = pc.outputs().make<std::vector<ROFRecord>>(OutputRef{"clusterrofs"});
97 auto& clusters = pc.outputs().make<std::vector<Cluster>>(OutputRef{"clusters"});
98 auto& usedDigits = pc.outputs().make<std::vector<Digit>>(OutputRef{"clusterdigits"});
99
100 // create the trackable ROF filtering if needed
101 ROFFilter trackable{};
102 if (ClusterizerParam::Instance().onlyTrackable) {
103 const auto& trackerParam = TrackerParam::Instance();
104 std::array<bool, 5> requestStation{
105 trackerParam.requestStation[0],
106 trackerParam.requestStation[1],
107 trackerParam.requestStation[2],
108 trackerParam.requestStation[3],
109 trackerParam.requestStation[4]};
110 trackable = createTrackableFilter(preClusters, digits, requestStation, trackerParam.moreCandidates);
111 }
112
113 clusterROFs.reserve(preClusterROFs.size());
114 auto& errorMap = mClusterFinder.getErrorMap();
115 errorMap.clear();
116 int nFilteredRofs = 0;
117 int nFilteredPreClusters = 0;
118 for (const auto& preClusterROF : preClusterROFs) {
119
120 // filter out non-trackable ROFs if requested
121 if (ClusterizerParam::Instance().onlyTrackable && !trackable(preClusterROF)) {
122 // create an empty cluster ROF
123 clusterROFs.emplace_back(preClusterROF.getBCData(), clusters.size(), 0, preClusterROF.getBCWidth());
124 continue;
125 }
126 ++nFilteredRofs;
127 nFilteredPreClusters += preClusterROF.getNEntries();
128
129 // prepare to clusterize the current ROF
130 auto clusterOffset = clusters.size();
131 mClusterFinder.reset();
132
133 for (const auto& preCluster : preClusters.subspan(preClusterROF.getFirstIdx(), preClusterROF.getNEntries())) {
134
135 auto preclusterDigits = digits.subspan(preCluster.firstDigit, preCluster.nDigits);
136 auto firstClusterIdx = mClusterFinder.getClusters().size();
137
138 // clusterize the current precluster
139 auto tStart = std::chrono::high_resolution_clock::now();
140 mClusterFinder.findClusters(preclusterDigits);
141 auto tEnd = std::chrono::high_resolution_clock::now();
142 mTimeClusterFinder += tEnd - tStart;
143
144 if (mAttachInitalPrecluster) {
145 // store the new clusters and associate them to all the digits of the precluster
146 writeClusters(preclusterDigits, firstClusterIdx, clusters, usedDigits);
147 }
148 }
149
150 if (!mAttachInitalPrecluster) {
151 // store all the clusters of the current ROF and the associated digits actually used in the clustering
152 writeClusters(clusters, usedDigits);
153 }
154
155 // create the cluster ROF
156 clusterROFs.emplace_back(preClusterROF.getBCData(), clusterOffset, clusters.size() - clusterOffset,
157 preClusterROF.getBCWidth());
158 }
159
160 // create the output message for clustering errors
161 auto& clusterErrors = pc.outputs().make<std::vector<Error>>(OutputRef{"clustererrors"});
162 errorMap.forEach([&clusterErrors](Error error) {
163 clusterErrors.emplace_back(error);
164 });
165 mErrorMap.add(errorMap);
166
167 LOGP(info, "Found {:4d} clusters from {:4d} preclusters (out of {:4d}) in {:2d} filtered ROFs (out of {:2d})",
168 clusters.size(), nFilteredPreClusters, preClusters.size(), nFilteredRofs, preClusterROFs.size());
169 }
170
171 private:
172 //_________________________________________________________________________________________________
173 void writeClusters(const gsl::span<const Digit>& preclusterDigits, size_t firstClusterIdx,
175 std::vector<Digit, o2::pmr::polymorphic_allocator<Digit>>& usedDigits) const
176 {
179
180 if (firstClusterIdx == mClusterFinder.getClusters().size()) {
181 return;
182 }
183
184 auto clusterOffset = clusters.size();
185 clusters.insert(clusters.end(), mClusterFinder.getClusters().begin() + firstClusterIdx, mClusterFinder.getClusters().end());
186
187 auto digitOffset = usedDigits.size();
188 usedDigits.insert(usedDigits.end(), preclusterDigits.begin(), preclusterDigits.end());
189
190 for (auto itCluster = clusters.begin() + clusterOffset; itCluster < clusters.end(); ++itCluster) {
191 itCluster->firstDigit = digitOffset;
192 itCluster->nDigits = preclusterDigits.size();
193 }
194 }
195
196 //_________________________________________________________________________________________________
197 void writeClusters(std::vector<Cluster, o2::pmr::polymorphic_allocator<Cluster>>& clusters,
198 std::vector<Digit, o2::pmr::polymorphic_allocator<Digit>>& usedDigits) const
199 {
202
203 auto clusterOffset = clusters.size();
204 clusters.insert(clusters.end(), mClusterFinder.getClusters().begin(), mClusterFinder.getClusters().end());
205
206 auto digitOffset = usedDigits.size();
207 usedDigits.insert(usedDigits.end(), mClusterFinder.getUsedDigits().begin(), mClusterFinder.getUsedDigits().end());
208
209 for (auto itCluster = clusters.begin() + clusterOffset; itCluster < clusters.end(); ++itCluster) {
210 itCluster->firstDigit += digitOffset;
211 }
212 }
213
214 bool mAttachInitalPrecluster = false;
215 ClusterFinderOriginal mClusterFinder{};
216 ErrorMap mErrorMap{};
217 std::chrono::duration<double> mTimeClusterFinder{};
218};
219
220//_________________________________________________________________________________________________
222{
223 return DataProcessorSpec{
224 specName,
225 Inputs{InputSpec{"preclusterrofs", "MCH", "PRECLUSTERROFS", 0, Lifetime::Timeframe},
226 InputSpec{"preclusters", "MCH", "PRECLUSTERS", 0, Lifetime::Timeframe},
227 InputSpec{"digits", "MCH", "PRECLUSTERDIGITS", 0, Lifetime::Timeframe}},
228 Outputs{OutputSpec{{"clusterrofs"}, "MCH", "CLUSTERROFS", 0, Lifetime::Timeframe},
229 OutputSpec{{"clusters"}, "MCH", "CLUSTERS", 0, Lifetime::Timeframe},
230 OutputSpec{{"clusterdigits"}, "MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe},
231 OutputSpec{{"clustererrors"}, "MCH", "CLUSTERERRORS", 0, Lifetime::Timeframe}},
232 AlgorithmSpec{adaptFromTask<ClusterFinderOriginalTask>()},
233 Options{{"mch-config", VariantType::String, "", {"JSON or INI file with clustering parameters"}},
234 {"run2-config", VariantType::Bool, false, {"setup for run2 data"}},
235 {"attach-initial-precluster", VariantType::Bool, false, {"attach all digits of initial precluster to cluster"}}}};
236}
237
238} // end namespace mch
239} // end namespace o2
Definition of a data processor to run the original MLEM cluster finder.
Definition of a class to reconstruct clusters with the original MLEM algorithm.
Configurable parameters for MCH clustering.
Definition of the MCH cluster minimal structure.
definition of the MCH processing errors
char error[CURL_ERROR_SIZE]
Definition of the MCH precluster minimal structure.
Configurable parameters for MCH tracking.
Definition of the MCH ROFrame record.
const char * specName
static void updateFromFile(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
decltype(auto) make(const Output &spec, Args... args)
ServiceRegistryRef services()
Definition InitContext.h:34
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.
HMPID cluster implementation.
Definition Cluster.h:27
void init(framework::InitContext &ic)
void run(framework::ProcessingContext &pc)
const std::vector< Digit > & getUsedDigits() const
return the list of digits used in reconstructed clusters
ErrorMap & getErrorMap()
return the counting of encountered errors
void findClusters(gsl::span< const Digit > digits)
const std::vector< Cluster > & getClusters() const
return the list of reconstructed clusters
MCH digit implementation.
Definition Digit.h:31
void forEach(ErrorFunction f) const
Definition ErrorMap.cxx:90
void add(ErrorType errorType, uint32_t id0, uint32_t id1, uint64_t n=1)
Definition ErrorMap.cxx:33
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
std::function< bool(const ROFRecord &)> ROFFilter
Definition ROFFilter.h:25
o2::framework::DataProcessorSpec getClusterFinderOriginalSpec(const char *specName="mch-cluster-finder-original")
ROFFilter createTrackableFilter(gsl::span< const T > items, std::array< bool, 5 > requestStation={true, true, true, true, true}, bool moreCandidates=false)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
cluster minimal structure
Definition Cluster.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
std::vector< Digit > digits