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
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< ConfigParamSpec > Options
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