Project
Loading...
Searching...
No Matches
ClusterFinderGEM.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
19
21
22#include <algorithm>
23#include <cstring>
24#include <iterator>
25#include <limits>
26#include <numeric>
27#include <set>
28#include <stdexcept>
29#include <string>
30
31#include <TH2I.h>
32#include <TAxis.h>
33#include <TMath.h>
34#include <TRandom.h>
35
36// GG
37#include "PadOriginal.h"
38#include "ClusterOriginal.h"
40// ??? <<<<<<< HEAD
42// #include "mathiesonFit.h"
43// =======
44// #include "MathiesonOriginal.h"
47#include "mathUtil.h"
48#include "mathieson.h"
49#include "InspectModel.h"
50// >>>>>>> 12c0a2e670... High-level Refactoring
51
52#define VERBOSE 1
53
54namespace o2
55{
56namespace mch
57{
58
59extern ClusterConfig clusterConfig;
60
61//_________________________________________________________________________________________________
63 : mMathiesons(std::make_unique<MathiesonOriginal[]>(2)), mPreCluster(std::make_unique<ClusterOriginal>())
64{
66
67 // Mathieson function for station 1
68 mMathiesons[0].setPitch(0.21);
69 mMathiesons[0].setSqrtKx3AndDeriveKx2Kx4(0.7000);
70 mMathiesons[0].setSqrtKy3AndDeriveKy2Ky4(0.7550);
71
72 // Mathieson function for other stations
73 mMathiesons[1].setPitch(0.25);
74 mMathiesons[1].setSqrtKx3AndDeriveKx2Kx4(0.7131);
75 mMathiesons[1].setSqrtKy3AndDeriveKy2Ky4(0.7642);
76 // GG
77 // init Mathieson
79 nPads = 0;
80 xyDxy = nullptr;
81 cathode = nullptr;
82 saturated = nullptr;
83 padCharge = nullptr;
84 DEId = -1;
85 currentBC = 0xFFFFFFFF;
86 currentOrbit = 0xFFFFFFFF;
87 currentPreClusterID = 0;
88}
89
90//_________________________________________________________________________________________________
91void ClusterFinderGEM::init(int _mode, bool run2Config)
92{
94 // ??? Not used
95 mode = _mode;
96 // Run 2 case (default)
97 // 4.f * 0.22875f;
101 //
102 // ClusterResolution
107 if (!run2Config) {
108 // Run 3 case
111 //
112 // Cluster resolution (for the tracking)
117 }
118 // Inv ??? LOG(info) << "Init lowestPadCharge = " << clusterConfig.minChargeOfPads ;
119}
120//_________________________________________________________________________________________________
122{
123 // std::cout << " [GEM] deinit " << std::endl;
125}
126
127//_________________________________________________________________________________________________
128
130
131/* Trace
132ClusterFinderGEM::~ClusterFinderGEM()
133{
134 std::cout << " [ClusterFinderGEM] Delete " << std::endl;
135}
136*/
137
138//_________________________________________________________________________________________________
140{
141
142 // std::cout << " [GEM] Reset hits/mClusters.size=" << mClusters.size() << std::endl;
143
144 // GEM part
146 // Inv ??? freeMemoryPadProcessing();
147 mClusters.clear();
148 mUsedDigits.clear();
149}
150
152{
153 nPads = 0;
154 DEId = -1;
155 if (xyDxy != nullptr) {
156 delete[] xyDxy;
157 xyDxy = nullptr;
158 };
159 if (cathode != nullptr) {
160 delete[] cathode;
161 cathode = nullptr;
162 };
163 if (padCharge != nullptr) {
164 delete[] padCharge;
165 padCharge = nullptr;
166 };
167 if (saturated != nullptr) {
168 delete[] saturated;
169 saturated = nullptr;
170 };
171}
172
173//_________________________________________________________________________________________________
174void ClusterFinderGEM::dumpPreCluster(ClusterDump* dumpFile, gsl::span<const Digit> digits, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
175{
177 // GG mPrecluster defined in other MCHPreClustering/PreClusterFinder.h
178 mSegmentation = &mapping::segmentation(digits[0].getDetID());
179
180 // GG
181 // Allocation
182 nPads = digits.size();
183 double xyDxy[nPads * 4];
184 Mask_t saturated[nPads];
185 Mask_t cathode[nPads];
186 double padCharge[nPads];
187 // use to store in the dump file
188 uint32_t padADC[nPads];
189 DEId = digits[0].getDetID();
190 double* xPad = getX(xyDxy, nPads);
191 double* yPad = getY(xyDxy, nPads);
192 double* dxPad = getDX(xyDxy, nPads);
193 double* dyPad = getDY(xyDxy, nPads);
194
195 for (int iDigit = 0; iDigit < digits.size(); ++iDigit) {
196 const auto& digit = digits[iDigit];
197 int padID = digit.getPadID();
198
199 double x = mSegmentation->padPositionX(padID);
200 double y = mSegmentation->padPositionY(padID);
201 double dx = mSegmentation->padSizeX(padID) / 2.;
202 double dy = mSegmentation->padSizeY(padID) / 2.;
203 uint32_t adc = digit.getADC();
204 double charge = mADCToCharge(adc);
205 bool isSaturated = digit.isSaturated();
206 int plane = mSegmentation->isBendingPad(padID) ? 0 : 1;
207
208 if (charge <= 0.) {
209 throw std::runtime_error("The precluster contains a digit with charge <= 0");
210 }
211
212 // GG
213 // Initialisation for GEM processing
214 xPad[iDigit] = x;
215 yPad[iDigit] = y;
216 dxPad[iDigit] = dx;
217 dyPad[iDigit] = dy;
218 padCharge[iDigit] = charge;
219 saturated[iDigit] = isSaturated;
220 cathode[iDigit] = plane;
221 padADC[iDigit] = adc;
222 }
223 // GG Store in dump file
224 uint32_t N = digits.size();
225 // std::cout << " [GEM] Dump PreCluster " << dumpFile->getName() << ", size=" << N << std::endl;
226
227 if ((N != 0)) {
228 // Replace 0, by 0xFFFFFFFF
229 uint32_t header[6] = {(uint32_t)(bunchCrossing), (orbit), iPreCluster, (0), N, (uint32_t)(DEId)};
230 dumpFile->dumpUInt32(0, 6, header);
231 dumpFile->dumpFloat64(0, N, xPad);
232 dumpFile->dumpFloat64(0, N, yPad);
233 dumpFile->dumpFloat64(0, N, dxPad);
234 dumpFile->dumpFloat64(0, N, dyPad);
235 dumpFile->dumpFloat64(0, N, padCharge);
236 dumpFile->dumpInt16(0, N, saturated);
237 dumpFile->dumpInt16(0, N, cathode);
238 dumpFile->dumpUInt32(0, N, padADC);
239 }
240}
241
242//_________________________________________________________________________________________________
243void ClusterFinderGEM::dumpClusterResults(ClusterDump* dumpFile, const std::vector<Cluster>& clusters, size_t startIdx, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
244{
245 // Dump result
246 // Dump hits from iNewCluster to mClusters.size()
247 uint32_t N = clusters.size() - startIdx;
248 // struct ClusterStruct {
249 // float x; ///< cluster position along x
250 // float y; ///< cluster position along y
251 // float z; ///< cluster position along z
252 // float ex; ///< cluster resolution along x
253 // float ey; ///< cluster resolution along y
254 // uint32_t uid; ///< cluster unique ID
255 // uint32_t firstDigit; ///< index of first associated digit in the ordered vector of digits
256 // uint32_t nDigits; ///< number of digits attached to this cluster
257 //
258 // Header
259 // std::cout << " [GEM] Dump Cluster " << dumpFile->getName() << ", size=" << N << " start=" << startIdx << std::endl;
260
261 uint32_t header[6] = {(uint32_t)(bunchCrossing), (orbit), iPreCluster, (0), N, 0};
262 dumpFile->dumpUInt32(0, 6, header);
263 //
264 double x[N], y[N];
265 double ex[N], ey[N];
266 uint32_t uid[N];
267 uint32_t firstDigit[N], nDigits[N];
268 int i = 0;
269 for (int n = startIdx; n < clusters.size(); ++n, i++) {
270 Cluster hit = clusters[n];
271 x[i] = hit.x;
272 y[i] = hit.y;
273 ex[i] = hit.ex;
274 ey[i] = hit.ey;
275 uid[i] = hit.uid;
276 firstDigit[i] = hit.firstDigit;
277 nDigits[i] = hit.nDigits;
278 }
279 if (N > 0) {
280 dumpFile->dumpFloat64(0, N, x);
281 dumpFile->dumpFloat64(0, N, y);
282 dumpFile->dumpFloat64(0, N, ex);
283 dumpFile->dumpFloat64(0, N, ey);
284 dumpFile->dumpUInt32(0, N, uid);
285 dumpFile->dumpUInt32(0, N, firstDigit);
286 dumpFile->dumpUInt32(0, N, nDigits);
287 // dumpFile->flush();
288 }
289}
290
291/* Invalid
292//_________________________________________________________________________________________________
293// void ClusterFinderGEM::saveStatistics(ClusterDump* dumpFile, gsl::span<const Digit> digits, const std::vector<Cluster>& clusters, size_t startIdx, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
294void ClusterFinderGEM::saveStatistics(uint32_t orbit, uint16_t bunchCrossing, uint32_t iPreCluster, uint16_t nPads, uint16_t nbrClusters, uint16_t DEId, double duration)
295{
296 statStream << iPreCluster << " " << bunchCrossing << " " << orbit << " "
297 << nPads << " " << nbrClusters << " " << DEId << " " << duration << std::endl;
298}
299*/
300
301//_________________________________________________________________________________________________
302void ClusterFinderGEM::fillGEMInputData(gsl::span<const Digit>& digits, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
303{
305 // GG mPrecluster defined in other MCHPreClustering/PreClusterFinder.h
306 mPreCluster->clear();
307 mSegmentation = &mapping::segmentation(digits[0].getDetID());
308
309 // GG
310 // Allocation
311 nPads = digits.size();
312 xyDxy = new double[nPads * 4];
313 saturated = new Mask_t[nPads];
314 cathode = new Mask_t[nPads];
315 padCharge = new double[nPads];
316 // use to store in the dump file
317 uint32_t padADC[nPads];
318 DEId = digits[0].getDetID();
319 double* xPad = getX(xyDxy, nPads);
320 double* yPad = getY(xyDxy, nPads);
321 double* dxPad = getDX(xyDxy, nPads);
322 double* dyPad = getDY(xyDxy, nPads);
323
324 for (int iDigit = 0; iDigit < digits.size(); ++iDigit) {
325 const auto& digit = digits[iDigit];
326 int padID = digit.getPadID();
327
328 double x = mSegmentation->padPositionX(padID);
329 double y = mSegmentation->padPositionY(padID);
330 double dx = mSegmentation->padSizeX(padID) / 2.;
331 double dy = mSegmentation->padSizeY(padID) / 2.;
332 uint32_t adc = digit.getADC();
333 // float charge(0.);
334 // std::memcpy(&charge, &adc, sizeof(adc));
335 double charge = mADCToCharge(adc);
336 bool isSaturated = digit.isSaturated();
337 int plane = mSegmentation->isBendingPad(padID) ? 0 : 1;
338
339 if (charge <= 0.) {
340 throw std::runtime_error("The precluster contains a digit with charge <= 0");
341 }
342 // std::cout << x << ", " << y << ", " << dx << ", " << dy << ", " << charge << ", " << isSaturated << std::endl;
343 mPreCluster->addPad(x, y, dx, dy, charge, isSaturated, plane, iDigit, PadOriginal::kZero);
344 // GG
345 // Initialisation for GEM processing
346 xPad[iDigit] = x;
347 yPad[iDigit] = y;
348 dxPad[iDigit] = dx;
349 dyPad[iDigit] = dy;
350 padCharge[iDigit] = charge;
351 saturated[iDigit] = isSaturated;
352 cathode[iDigit] = plane;
353 padADC[iDigit] = adc;
354 }
355}
356
357//_________________________________________________________________________________________________
358void ClusterFinderGEM::setClusterResolution(Cluster& cluster) const
359{
362
363 if (cluster.getChamberId() < 4) {
364
365 // do not consider mono-cathode clusters in stations 1 and 2
368 } else {
369
370 // find pads below the cluster
371 int padIDNB(-1), padIDB(-1);
372 bool padsFound = mSegmentation->findPadPairByPosition(cluster.x, cluster.y, padIDB, padIDNB);
373
374 // look for these pads (if any) in the list of digits associated to this cluster
375 auto itPadNB = mUsedDigits.end();
376 if (padsFound || mSegmentation->isValid(padIDNB)) {
377 itPadNB = std::find_if(mUsedDigits.begin() + cluster.firstDigit, mUsedDigits.end(),
378 [padIDNB](const Digit& digit) { return digit.getPadID() == padIDNB; });
379 }
380 auto itPadB = mUsedDigits.end();
381 if (padsFound || mSegmentation->isValid(padIDB)) {
382 itPadB = std::find_if(mUsedDigits.begin() + cluster.firstDigit, mUsedDigits.end(),
383 [padIDB](const Digit& digit) { return digit.getPadID() == padIDB; });
384 }
385
386 // set the cluster resolution accordingly
387 cluster.ex = (itPadNB == mUsedDigits.end()) ? clusterConfig.SBadClusterResolutionX
388 : clusterConfig.SDefaultClusterResolutionX;
389 cluster.ey = (itPadB == mUsedDigits.end()) ? clusterConfig.SBadClusterResolutionY
390 : clusterConfig.SDefaultClusterResolutionY;
391 }
392}
393
394//_________________________________________________________________________________________________
395void ClusterFinderGEM::findClusters(gsl::span<const Digit> digits,
396 uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
397{
400 // std::cout << " [GEM] preCluster digit size=" << digits.size() << std::endl;
401 // skip preclusters with only 1 digit
402 if (digits.size() < 2) {
403 return;
404 }
405 uint32_t nPreviousCluster = mClusters.size();
407 printf("----------------------------------------\n");
408 std::cout << " [GEM] PreCluster BC=" << bunchCrossing
409 << ", orbit = " << orbit
410 << ", iPreCluster, = " << iPreCluster
411 << std::endl;
412 printf("----------------------------------------\n");
413 }
414 // std::cout << " [GEM] hits/mClusters.size=" << mClusters.size() << std::endl;
415
416 // set the Mathieson function to be used
417 // GG Inv mMathieson = (digits[0].getDetID() < 300) ? &mMathiesons[0] : &mMathiesons[1];
418
419 // reset the current precluster being processed
420 // GG Set the Precluster (pads , ....)
421 fillGEMInputData(digits, bunchCrossing, orbit, iPreCluster);
422
423 // GG process clusters
424 int chId = DEId / 100;
425 int nbrOfHits = ::clusterProcess(xyDxy, cathode, saturated, padCharge, chId, nPads);
426 double theta[nbrOfHits * 5];
427 Groups_t thetaToGroup[nbrOfHits];
429 collectSeeds(theta, thetaToGroup, nbrOfHits);
430 // std::cout << " [GEM] Seeds found by GEM " << nbrOfHits << " / nPads = " << nPads << std::endl;
431 double* muX = getMuX(theta, nbrOfHits);
432 double* muY = getMuY(theta, nbrOfHits);
433 double* w = getW(theta, nbrOfHits);
434 // Find subClusters with there seeds
435 //
437 Groups_t padToCathGrp[nPads];
438 collectGroupMapping(padToCathGrp, nPads);
439 // vectorPrintShort( "padToCathGrp ???", padToCathGrp, nPads);
440 // Take care the number of groups can be !=
441 // between thetaToGroup
442 Groups_t nCathGrp = vectorMaxShort(padToCathGrp, nPads);
443 int nPadStored = 0;
444 // Index of the first store digit of the group
445 uint32_t firstDigit;
446 // For all the cath groups
447 for (int g = 1; g < (nCathGrp + 1); g++) {
448 int i = 0;
449 firstDigit = mUsedDigits.size();
450 for (const auto& pad : *mPreCluster) {
451 // Store the pad belonging to the cath-group
452 if (padToCathGrp[i] == g) {
453 mUsedDigits.emplace_back(digits[pad.digitIndex()]);
454 nPadStored++;
455 }
456 i++;
457 }
458 // n digits for the considered group
459 uint32_t nDigits = mUsedDigits.size() - firstDigit;
460 // For all the seeds or hits
461 for (int s = 0; s < nbrOfHits; s++) {
462 // Store the hit belonging to the cath-group
463 if (thetaToGroup[s] == g) {
464 double x = muX[s];
465 double y = muY[s];
466 /*
467 // ??? Do something for the mathieson factors
468 double dx, dy;
469 // ??? value of chID
470 // ??? To do later
471 if (chId <= 4) {
472 dx = SDefaultClusterResolutionX;
473 dy = SDefaultClusterResolutionY;
474 } else {
475 // Find the associated pads
476 // set the cluster resolution accordingly
477 // cluster.ex = (NBPad) ? SBadClusterResolutionX : SDefaultClusterResolutionX;
478 // cluster.ey = (BPad) ? SBadClusterResolutionY : SDefaultClusterResolutionY;
479 // ???
480 dx = SDefaultClusterResolutionX;
481 dy = SDefaultClusterResolutionY;
482 }
483 */
484 // ??? uint32_t uid = Cluster::buildUniqueId(digits[0].getDetID() / 100 - 1, digits[0].getDetID(), thetaToGroup[s]);
485 uint32_t uid = Cluster::buildUniqueId(digits[0].getDetID() / 100 - 1, digits[0].getDetID(), nPreviousCluster + s);
486 // Debug
487 /*
488 std::cout << "nPreviousCluster=" << nPreviousCluster << ", s=" << ", uid=" << uid << std::endl;
489 */
490 mClusters.push_back({
491 static_cast<float>(x), static_cast<float>(y), 0.0, // x, y, z
492 static_cast<float>(0), static_cast<float>(0), // x, y resolution
493 uid, // uid
494 firstDigit, nDigits // firstDigit, nDigits
495 });
496 setClusterResolution(mClusters[mClusters.size() - 1]);
497 // Debug
498 int iNewCluster = mClusters.size() - 1;
499 /*
500 std::cout << "iNewCluster=" << iNewCluster << ", DEId=" << digits[0].getDetID()
501 << ", x" << mClusters[iNewCluster].x << ", y" << mClusters[iNewCluster].y << ", z" << mClusters[iNewCluster].z
502 << "uid=" << mClusters[iNewCluster].uid << std::endl;
503 */
504 }
505 }
506 }
507
508 // std::cout << " [GEM] Finished preCluster " << digits.size() << std::endl;
511}
512
513} // namespace mch
514} // namespace o2
Clustering and fifting parameters.
Definition of the cluster used by the original cluster finder algorithm.
Configurable parameters for MCH clustering.
int16_t charge
Definition RawEventData.h:5
uint64_t orbit
Definition RawEventData.h:6
int32_t i
Original definition of the Mathieson function.
Definition of the pad used by the original cluster finder algorithm.
void dumpInt16(int ifile, long size, const int16_t *data)
void dumpUInt32(int ifile, long size, const uint32_t *data)
void dumpFloat64(int ifile, long size, const double_t *data)
void fillGEMInputData(gsl::span< const Digit > &digits, uint16_t bunchCrossing, uint32_t orbit, uint32_t iPreCluster)
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)
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)
cluster for internal use
Original Mathieson function.
@ kZero
pad "basic" state
Definition PadOriginal.h:36
double padPositionX(int dePadIndex) const
double padSizeY(int dePadIndex) const
bool findPadPairByPosition(double x, double y, int &bpad, int &nbpad) const
bool isBendingPad(int dePadIndex) const
double padPositionY(int dePadIndex) const
double padSizeX(int dePadIndex) const
bool isValid(int dePadIndex) const
int clusterProcess(const double *xyDxyi, const o2::mch::Mask_t *cathi, const o2::mch::Mask_t *saturated, const double *zi, int chId, int nPads)
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum mode
Definition glcorearb.h:266
GLint y
Definition glcorearb.h:270
GLboolean GLboolean g
Definition glcorearb.h:1233
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
void initMathieson(int useSpline_, int useCache_)
Definition mathieson.cxx:73
double * getMuY(double *theta, int K)
double * getDX(double *xyDxy, int N)
void collectSeeds(double *theta, o2::mch::Groups_t *thetaToGroup, int K)
void cleanClusterResults()
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
void initClusterConfig()
double * getMuX(double *theta, int K)
double * getW(double *theta, int K)
double * getDY(double *xyDxy, int N)
ClusterConfig clusterConfig
void collectGroupMapping(Mask_t *padToMGrp, int nPads)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
float SBadClusterResolutionX
bad (e.g. mono-cathode) cluster resolution in x direction (cm)
float SBadClusterResolutionY
bad (e.g. mono-cathode) cluster resolution in y direction (cm)
@ info
Describes main steps and high level behaviors.
float SDefaultClusterResolutionY
default cluster resolution in y direction (cm)
float SDefaultClusterResolutionX
default cluster resolution in x direction (cm)
cluster minimal structure
Definition Cluster.h:31
float ey
cluster resolution along y
Definition Cluster.h:36
int getChamberId() const
Return the chamber ID (0..), part of the unique ID.
Definition Cluster.h:60
uint32_t firstDigit
index of first associated digit in the ordered vector of digits
Definition Cluster.h:38
uint32_t uid
cluster unique ID
Definition Cluster.h:37
uint32_t nDigits
number of digits attached to this cluster
Definition Cluster.h:39
float y
cluster position along y
Definition Cluster.h:33
float x
cluster position along x
Definition Cluster.h:32
float ex
cluster resolution along x
Definition Cluster.h:35
std::vector< Cluster > clusters
std::vector< Digit > digits
ArrayADC adc