Project
Loading...
Searching...
No Matches
ClusterFinderGEMSpec.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
15
17
18#include <iostream>
19#include <fstream>
20#include <chrono>
21#include <vector>
22#include <stdexcept>
23#include <string>
24
25#include <gsl/span>
26
31#include "Framework/Lifetime.h"
32#include "Framework/Output.h"
33#include "Framework/Task.h"
34#include "Framework/Logger.h"
35
39#include "MCHBase/ErrorMap.h"
40#include "MCHBase/PreCluster.h"
48
49namespace o2
50{
51namespace mch
52{
53
54using namespace std;
55using namespace o2::framework;
56
58{
59 public:
60 static constexpr int DoOriginal = 0x0001;
61 static constexpr int DoGEM = 0x0002;
62 static constexpr int DumpOriginal = 0x0004;
63 static constexpr int DumpGEM = 0x0008;
64 static constexpr int GEMOutputStream = 0x0010; // default is Original
65 static constexpr int TimingStats = 0x0020;
66 static constexpr char statFileName[] = "statistics.csv";
67 std::fstream statStream;
68 //
69 bool isActive(int selectedMode) const
70 {
71 return (mode & selectedMode);
72 }
73 /* invalid
74 bool isGEMDumped()
75 {
76 return (mode & DumpGEM);
77 }
78
79 bool isOriginalActivated()
80 {
81 return (mode & DoOriginal);
82 }
83
84 bool isOriginalDumped()
85 {
86 return (mode & DumpOriginal);
87 }
88
89 bool isGEMOutputStream() const
90 {
91 return (mode & GEMOutputStream);
92 }
93
94 bool isGEMTimingStats() const
95 {
96 return (mode & isGEMTimingStats());
97 }
98 */
99 void saveStatistics(uint32_t orbit, uint16_t bunchCrossing, uint32_t iPreCluster, uint16_t nPads, uint16_t nbrClusters, uint16_t DEId, double duration)
100 {
101 statStream << iPreCluster << " " << bunchCrossing << " " << orbit << " "
102 << nPads << " " << nbrClusters << " " << DEId << " " << duration << std::endl;
103 }
104
105 //_________________________________________________________________________________________________
107 {
109 LOG(info) << "initializing cluster finder";
110
111 auto config = ic.options().get<std::string>("mch-config");
112 if (!config.empty()) {
113 o2::conf::ConfigurableParam::updateFromFile(config, "MCHClustering", true);
114 }
115 bool run2Config = ic.options().get<bool>("run2-config");
116
117 // GG auto mode = ic.options().get<int>("mode");
118 mode = ic.options().get<int>("mode");
119 printf("------------------------------------> GG Mode mode=%d\n", mode);
120
122 LOG(info) << "initializing cluster finder";
123
125 mode = mode & (~DumpOriginal);
126 }
127 if (isActive(DumpGEM) && !isActive(DoGEM)) {
128 mode = mode & (~DumpGEM);
129 }
130 if (isActive(DumpOriginal)) {
131 mOriginalDump = new ClusterDump("OrigRun2.dat", 0);
132 }
133 if (isActive(DumpGEM)) {
134 mGEMDump = new ClusterDump("GEMRun2.dat", 0);
135 }
136 if (isActive(TimingStats)) {
137 statStream.open(statFileName, std::fstream::out);
138 statStream << "# iPrecluster bunchCrossing orbit nPads nClusters DEId duration (in ms)" << std::endl;
139 }
140
141 //
142 LOG(info) << "Configuration";
143 LOG(info) << " Mode : " << mode;
144 LOG(info) << " Original: " << isActive(DoOriginal);
145 LOG(info) << " GEM : " << isActive(DoGEM);
146 LOG(info) << " Dump Original: " << isActive(DumpOriginal);
147 LOG(info) << " Dump GEM : " << isActive(DumpGEM);
148 LOG(info) << " GEM stream output : " << isActive(GEMOutputStream);
149 LOG(info) << " Timing statistics: " << isActive(TimingStats);
150
151 // mClusterFinder.init( ClusterFinderGEM::DoGEM );
152 if (isActive(DoOriginal)) {
153 mClusterFinderOriginal.init(run2Config);
154 } else if (isActive(DoGEM)) {
155 mClusterFinderGEM.init(mode, run2Config);
156 }
157 // Inv ??? LOG(info) << "GG = lowestPadCharge = " << ClusterizerParam::Instance().lowestPadCharge;
158
160 ic.services().get<CallbackService>().set<CallbackService::Id::Stop>([this]() {
161 LOG(info) << "cluster finder duration = " << mTimeClusterFinder.count() << " s";
162 if (isActive(DoOriginal)) {
163 this->mClusterFinderOriginal.deinit();
164 } else if (isActive(DoGEM)) {
165 this->mClusterFinderGEM.deinit();
166 }
167 if (isActive(DumpOriginal)) {
168 delete mOriginalDump;
169 mOriginalDump = nullptr;
170 }
171 if (isActive(DumpGEM)) {
172 delete mGEMDump;
173 mGEMDump = nullptr;
174 }
175 mErrorMap.forEach([](Error error) {
176 LOGP(warning, "{}", error.asString());
177 });
178 });
179 auto stop = [this]() {
181 LOG(info) << "stop GEM";
182 // this->mOutputFile.close();
183 };
184 }
185
186 //_________________________________________________________________________________________________
188 {
190
191 // get the input preclusters and associated digits
192 auto preClusterROFs = pc.inputs().get<gsl::span<ROFRecord>>("preclusterrofs");
193 auto preClusters = pc.inputs().get<gsl::span<PreCluster>>("preclusters");
194 auto digits = pc.inputs().get<gsl::span<Digit>>("digits");
195
196 // LOG(info) << "received time frame with " << preClusterROFs.size() << " interactions";
197
198 // create the output messages for clusters and attached digits
199 auto& clusterROFs = pc.outputs().make<std::vector<ROFRecord>>(OutputRef{"clusterrofs"});
200 auto& clusters = pc.outputs().make<std::vector<Cluster>>(OutputRef{"clusters"});
201 auto& usedDigits = pc.outputs().make<std::vector<Digit>>(OutputRef{"clusterdigits"});
202 uint32_t iPreCluster = 0;
203
204 clusterROFs.reserve(preClusterROFs.size());
205 ErrorMap errorMap; // TODO: use this errorMap to score processing errors
206
207 for (const auto& preClusterROF : preClusterROFs) {
208 // LOG(info) << "processing interaction: time frame " << preClusterROF.getBCData().orbit << "...";
209 // GG infos
210 // uint16_t bc = DummyBC; ///< bunch crossing ID of interaction
211 // uint32_t orbit = DummyOrbit; ///< LHC orbit
212 // clusterize every preclusters
213 uint16_t bCrossing = preClusterROF.getBCData().bc;
214 uint32_t orbit = preClusterROF.getBCData().orbit;
215 std::chrono::duration<double> preClusterDuration{};
216 auto tStart = std::chrono::high_resolution_clock::now();
217
218 // Inv ??? if ( orbit==22 ) {
219 //
220 if (isActive(DoOriginal)) {
221 mClusterFinderOriginal.reset();
222 }
223 if (isActive(DoGEM)) {
224 mClusterFinderGEM.reset();
225 }
226 // Get the starting index for new cluster founds
227 size_t startGEMIdx = mClusterFinderGEM.getClusters().size();
228 size_t startOriginalIdx = mClusterFinderOriginal.getClusters().size();
229 uint16_t nbrClusters(0);
230 // std::cout << "Start index GEM=" << startGEMIdx << ", Original=" << startOriginalIdx << std::endl;
231 for (const auto& preCluster : preClusters.subspan(preClusterROF.getFirstIdx(), preClusterROF.getNEntries())) {
232 auto tPreClusterStart = std::chrono::high_resolution_clock::now();
233 // Inv ??? for (const auto& preCluster : preClusters.subspan(preClusterROF.getFirstIdx(), 1102)) {
234 startGEMIdx = mClusterFinderGEM.getClusters().size();
235 startOriginalIdx = mClusterFinderOriginal.getClusters().size();
236 // Dump preclusters
237 // std::cout << "bCrossing=" << bCrossing << ", orbit=" << orbit << ", iPrecluster" << iPreCluster
238 // << ", PreCluster: digit start=" << preCluster.firstDigit <<" , digit size=" << preCluster.nDigits << std::endl;
239 if (isActive(DumpOriginal)) {
240 mClusterFinderGEM.dumpPreCluster(mOriginalDump, digits.subspan(preCluster.firstDigit, preCluster.nDigits), bCrossing, orbit, iPreCluster);
241 }
242 if (isActive(DumpGEM)) {
243 mClusterFinderGEM.dumpPreCluster(mGEMDump, digits.subspan(preCluster.firstDigit, preCluster.nDigits), bCrossing, orbit, iPreCluster);
244 }
245 // Clusterize
246 if (isActive(DoOriginal)) {
247 mClusterFinderOriginal.findClusters(digits.subspan(preCluster.firstDigit, preCluster.nDigits));
248 nbrClusters = mClusterFinderOriginal.getClusters().size() - startOriginalIdx;
249 }
250 if (isActive(DoGEM)) {
251 mClusterFinderGEM.findClusters(digits.subspan(preCluster.firstDigit, preCluster.nDigits), bCrossing, orbit, iPreCluster);
252 nbrClusters = mClusterFinderGEM.getClusters().size() - startGEMIdx;
253 }
254 // Dump clusters (results)
255 // std::cout << "[Original] total clusters.size=" << mClusterFinderOriginal.getClusters().size() << std::endl;
256 // std::cout << "[GEM ] total clusters.size=" << mClusterFinderGEM.getClusters().size() << std::endl;
257 if (isActive(DumpOriginal)) {
258 mClusterFinderGEM.dumpClusterResults(mOriginalDump, mClusterFinderOriginal.getClusters(), startOriginalIdx, bCrossing, orbit, iPreCluster);
259 }
260 if (isActive(DumpGEM)) {
261 mClusterFinderGEM.dumpClusterResults(mGEMDump, mClusterFinderGEM.getClusters(), startGEMIdx, bCrossing, orbit, iPreCluster);
262 }
263 // Timing Statistics
264 if (isActive(TimingStats)) {
265 auto tPreClusterEnd = std::chrono::high_resolution_clock::now();
266 preClusterDuration = tPreClusterEnd - tPreClusterStart;
267 int16_t nPads = preCluster.nDigits;
268 int16_t DEId = digits[preCluster.firstDigit].getDetID();
269 // double dt = duration_cast<duration<double>>(tPreClusterEnd - tPreClusterStart).count;
270 // std::chrono::duration<double> time_span = std::chrono::duration_cast<duration<double>>(tPreClusterEnd - tPreClusterStart);
271 preClusterDuration = tPreClusterEnd - tPreClusterStart;
272 double dt = preClusterDuration.count();
273 // In second
274 dt = (dt < 1.0e-06) ? 0.0 : dt * 1000;
275 saveStatistics(orbit, bCrossing, iPreCluster, nPads, nbrClusters, DEId, dt);
276 }
277 iPreCluster++;
278 }
279 // } // Inv ??? if ( orbit==22 ) {
280 auto tEnd = std::chrono::high_resolution_clock::now();
281 mTimeClusterFinder += tEnd - tStart;
282
283 // fill the ouput messages
285 clusterROFs.emplace_back(preClusterROF.getBCData(), clusters.size(), mClusterFinderGEM.getClusters().size());
286 } else {
287 clusterROFs.emplace_back(preClusterROF.getBCData(), clusters.size(), mClusterFinderOriginal.getClusters().size());
288 }
289 //
290 writeClusters(clusters, usedDigits);
291 }
292
293 // create the output message for clustering errors
294 auto& clusterErrors = pc.outputs().make<std::vector<Error>>(OutputRef{"clustererrors"});
295 errorMap.forEach([&clusterErrors](Error error) {
296 clusterErrors.emplace_back(error);
297 });
298 mErrorMap.add(errorMap);
299
300 LOGP(info, "Found {:4d} clusters from {:4d} preclusters in {:2d} ROFs",
301 clusters.size(), preClusters.size(), preClusterROFs.size());
302 }
303
304 private:
305 //_________________________________________________________________________________________________
306 void writeClusters(std::vector<Cluster, o2::pmr::polymorphic_allocator<Cluster>>& clusters,
307 std::vector<Digit, o2::pmr::polymorphic_allocator<Digit>>& usedDigits) const
308 {
311 auto clusterOffset = clusters.size();
313 clusters.insert(clusters.end(), mClusterFinderGEM.getClusters().begin(), mClusterFinderGEM.getClusters().end());
314 } else {
315 clusters.insert(clusters.end(), mClusterFinderOriginal.getClusters().begin(), mClusterFinderOriginal.getClusters().end());
316 }
317 auto digitOffset = usedDigits.size();
319 usedDigits.insert(usedDigits.end(), mClusterFinderGEM.getUsedDigits().begin(), mClusterFinderGEM.getUsedDigits().end());
320 } else {
321 usedDigits.insert(usedDigits.end(), mClusterFinderOriginal.getUsedDigits().begin(), mClusterFinderOriginal.getUsedDigits().end());
322 }
323
324 for (auto itCluster = clusters.begin() + clusterOffset; itCluster < clusters.end(); ++itCluster) {
325 itCluster->firstDigit += digitOffset;
326 }
327 }
328
329 ClusterFinderOriginal mClusterFinderOriginal{};
330 ClusterFinderGEM mClusterFinderGEM{};
331 int mode;
332 ClusterDump* mGEMDump;
333 ClusterDump* mOriginalDump;
334 ErrorMap mErrorMap{};
335 std::chrono::duration<double> mTimeClusterFinder{};
336};
337
338//_________________________________________________________________________________________________
340{
341 return DataProcessorSpec{
342 specName,
343 Inputs{InputSpec{"preclusterrofs", "MCH", "PRECLUSTERROFS", 0, Lifetime::Timeframe},
344 InputSpec{"preclusters", "MCH", "PRECLUSTERS", 0, Lifetime::Timeframe},
345 InputSpec{"digits", "MCH", "PRECLUSTERDIGITS", 0, Lifetime::Timeframe}},
346 Outputs{OutputSpec{{"clusterrofs"}, "MCH", "CLUSTERROFS", 0, Lifetime::Timeframe},
347 OutputSpec{{"clusters"}, "MCH", "CLUSTERS", 0, Lifetime::Timeframe},
348 OutputSpec{{"clusterdigits"}, "MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe},
349 OutputSpec{{"clustererrors"}, "MCH", "CLUSTERERRORS", 0, Lifetime::Timeframe}},
350 AlgorithmSpec{adaptFromTask<ClusterFinderGEMTask>()},
351 Options{
352 {"mch-config", VariantType::String, "", {"JSON or INI file with clustering parameters"}},
353 {"run2-config", VariantType::Bool, false, {"Setup for run2 data"}},
354 {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
355 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoOriginal, {"Running mode"}},
356 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
357 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM | ClusterFinderGEMTask::DumpGEM | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
358 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoOriginal | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
359 //{"mode", VariantType::Int, ClusterFinderGEMTask::DoOriginal | ClusterFinderGEMTask::DumpOriginal | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
360 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM, {"Running mode"}},
361
362 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM | ClusterFinderGEMTask::DumpGEM | ClusterFinderGEMTask::GEMOutputStream, {"Running mode"}},
363 // {"mode", VariantType::Int, ClusterFinderGEMTask::DoGEM, {"Running mode"}},
364 }};
365}
366
367} // end namespace mch
368} // end namespace o2
Definition of a data processor to run the GEM 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.
uint64_t orbit
Definition RawEventData.h:6
Definition of the MCH precluster minimal structure.
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.
void init(framework::InitContext &ic)
void run(framework::ProcessingContext &pc)
static constexpr char statFileName[]
void saveStatistics(uint32_t orbit, uint16_t bunchCrossing, uint32_t iPreCluster, uint16_t nPads, uint16_t nbrClusters, uint16_t DEId, double duration)
bool isActive(int selectedMode) const
void findClusters(gsl::span< const Digit > digits, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
void dumpPreCluster(ClusterDump *dumpFile, gsl::span< const Digit > digits, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
const std::vector< Cluster > & getClusters() const
return the list of reconstructed clusters
void init(int mode, bool run2Config)
void dumpClusterResults(ClusterDump *dumpFile, const std::vector< Cluster > &clusters, size_t startIdx, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
const std::vector< Digit > & getUsedDigits() const
return the list of digits used in reconstructed clusters
const std::vector< Digit > & getUsedDigits() const
return the list of digits used in reconstructed clusters
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
A container class to summarize errors encountered during processing.
Definition ErrorMap.h:38
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
GLenum mode
Definition glcorearb.h:266
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
o2::framework::DataProcessorSpec getClusterFinderGEMSpec(const char *specName)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
cluster minimal structure
Definition Cluster.h:31
std::string asString() const
Definition Error.cxx:86
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
std::vector< Digit > digits