Project
Loading...
Searching...
No Matches
ClusterFactory.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
21#include "EMCALBase/Geometry.h"
22// #include "MathUtils/Cartesian.h"
23
24#include <Rtypes.h>
25
26#include <array>
27#include <span>
28
29using namespace o2::emcal;
30
31template <class InputType>
32ClusterFactory<InputType>::ClusterFactory(std::span<const o2::emcal::Cluster> clustersContainer, std::span<const InputType> inputsContainer, std::span<const int> cellsIndices)
33{
34 setContainer(clustersContainer, inputsContainer, cellsIndices);
35}
36
37template <class InputType>
39{
40 mClustersContainer = std::span<const o2::emcal::Cluster>();
41 mInputsContainer = std::span<const InputType>();
42 mCellsIndices = std::span<int>();
43 mLookUpInit = false;
44 mCellLabelContainer = std::span<const o2::emcal::CellLabel>();
45}
46
49//____________________________________________________________________________
50template <class InputType>
52{
53 if (clusterIndex >= mClustersContainer.size()) {
54 throw ClusterRangeException(clusterIndex, mClustersContainer.size());
55 }
56 if (!mGeomPtr) {
58 }
59
60 o2::emcal::AnalysisCluster clusterAnalysis;
61 clusterAnalysis.setID(clusterIndex);
62
63 int firstCellIndex = mClustersContainer[clusterIndex].getCellIndexFirst();
64 int nCells = mClustersContainer[clusterIndex].getNCells();
65
66 std::span<const int> inputsIndices = std::span<const int>(&mCellsIndices[firstCellIndex], nCells);
67
68 // First calculate the index of input with maximum amplitude and get
69 // the supermodule number where it sits.
70
71 auto [inputIndMax, inputEnergyMax, cellAmp, shared] = getMaximalEnergyIndex(inputsIndices);
72
73 short towerId = mInputsContainer[inputIndMax].getTower();
74
75 float exoticTime = mInputsContainer[inputIndMax].getTimeStamp();
76
77 float fCross = 0.;
78
79 try {
80 clusterAnalysis.setIsExotic(isExoticCell(towerId, inputEnergyMax, exoticTime, fCross));
81 clusterAnalysis.setFCross(fCross);
82 } catch (UninitLookUpTableException& e) {
83 LOG(error) << e.what();
84 }
85
86 clusterAnalysis.setIndMaxInput(inputIndMax);
87
88 clusterAnalysis.setE(cellAmp);
89
90 mSuperModuleNumber = mGeomPtr->GetSuperModuleNumber(towerId);
91
92 clusterAnalysis.setNCells(inputsIndices.size());
93
94 std::vector<unsigned short> cellsIdices;
95
96 bool addClusterLabels = ((clusterLabel != nullptr) && (mCellLabelContainer.size() > 0));
97 for (auto cellIndex : inputsIndices) {
98 cellsIdices.push_back(cellIndex);
99 if (addClusterLabels) {
100 for (size_t iLabel = 0; iLabel < mCellLabelContainer[cellIndex].GetLabelSize(); iLabel++) {
101 if (mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) <= 0.f) {
102 continue; // skip 0 entries
103 }
104 clusterLabel->addValue(mCellLabelContainer[cellIndex].GetLabel(iLabel),
105 mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) * mInputsContainer[cellIndex].getEnergy());
106 }
107 }
108 }
109 if (addClusterLabels) {
110 clusterLabel->orderLabels();
111 clusterLabel->normalize(cellAmp);
112 }
113
114 clusterAnalysis.setCellsIndices(cellsIdices);
115
116 // evaluate global and local position
117 evalGlobalPosition(inputsIndices, clusterAnalysis);
118 evalLocalPosition(inputsIndices, clusterAnalysis);
119
120 // evaluate shower parameters
121 evalElipsAxis(inputsIndices, clusterAnalysis);
122 evalDispersion(inputsIndices, clusterAnalysis);
123
124 // evaluate number of local maxima
125 evalNExMax(inputsIndices, clusterAnalysis);
126
127 evalCoreEnergy(inputsIndices, clusterAnalysis);
128 evalTime(inputsIndices, clusterAnalysis);
129
130 // TODO to be added at a later stage
131 // evalPrimaries(inputsIndices, clusterAnalysis);
132 // evalParents(inputsIndices, clusterAnalysis);
133
134 // TODO to be added at a later stage
135 // Called last because it sets the global position of the cluster?
136 // Do not call it when recalculating clusters out of standard reconstruction
137 // if (!mJustCluster)
138 // evalLocal2TrackingCSTransform();
139
140 return clusterAnalysis;
141}
142
146//____________________________________________________________________________
147template <class InputType>
148void ClusterFactory<InputType>::evalDispersion(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
149{
150 double d = 0., wtot = 0.;
151 int nstat = 0;
152
153 // Calculates the dispersion in cell units
154 double etaMean = 0.0, phiMean = 0.0;
155
156 // Calculate mean values
157 for (auto iInput : inputsIndices) {
158
159 if (clusterAnalysis.E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
160 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
161 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
162
163 // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
164 // C Side impair SM, nSupMod%2=1; A side pair SM nSupMod%2=0
165 if (mSharedCluster && nSupMod % 2) {
166 ieta += EMCAL_COLS;
167 }
168
169 auto etai = static_cast<double>(ieta);
170 auto phii = static_cast<double>(iphi);
171 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
172
173 if (w > 0.0) {
174 phiMean += phii * w;
175 etaMean += etai * w;
176 wtot += w;
177 }
178 }
179 }
180
181 if (wtot > 0) {
182 phiMean /= wtot;
183 etaMean /= wtot;
184 } else {
185 LOG(error) << Form("Wrong weight %f\n", wtot);
186 }
187
188 // Calculate dispersion
189 for (auto iInput : inputsIndices) {
190
191 if (clusterAnalysis.E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
192 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
193 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
194
195 // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
196 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
197 if (mSharedCluster && nSupMod % 2) {
198 ieta += EMCAL_COLS;
199 }
200
201 auto etai = static_cast<double>(ieta);
202 auto phii = static_cast<double>(iphi);
203 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
204
205 if (w > 0.0) {
206 nstat++;
207 d += w * ((etai - etaMean) * (etai - etaMean) + (phii - phiMean) * (phii - phiMean));
208 }
209 }
210 }
211
212 if (wtot > 0 && nstat > 1) {
213 d /= wtot;
214 } else {
215 d = 0.;
216 }
217
218 clusterAnalysis.setDispersion(TMath::Sqrt(d));
219}
220
223//____________________________________________________________________________
224template <class InputType>
225void ClusterFactory<InputType>::evalLocalPosition(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
226{
227
228 int nstat = 0;
229
230 double dist = tMaxInCm(double(clusterAnalysis.E()));
231
232 std::array<double, 3> clXYZ = {0., 0., 0.}, clRmsXYZ = {0., 0., 0.}, xyzi{};
233 double wtot = 0., w = 0.;
234
235 for (auto iInput : inputsIndices) {
236
237 try {
238 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
239 } catch (InvalidCellIDException& e) {
240 LOG(error) << e.what();
241 continue;
242 }
243
244 // Temporal patch, due to mapping problem, need to swap "y" in one of the 2 SM, although no effect in position calculation. GCB 05/2010
245 if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
246 xyzi[1] *= -1;
247 }
248
249 if (mLogWeight > 0.0) {
250 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
251 } else {
252 w = mInputsContainer[iInput].getEnergy(); // just energy
253 }
254
255 if (w > 0.0) {
256 wtot += w;
257 nstat++;
258
259 for (int i = 0; i < 3; i++) {
260 clXYZ[i] += (w * xyzi[i]);
261 clRmsXYZ[i] += (w * xyzi[i] * xyzi[i]);
262 }
263 } // w > 0
264 } // dig loop
265
266 // cout << " wtot " << wtot << endl;
267
268 if (wtot > 0) {
269 // xRMS = TMath::Sqrt(x2m - xMean*xMean);
270 for (int i = 0; i < 3; i++) {
271 clXYZ[i] /= wtot;
272
273 if (nstat > 1) {
274 clRmsXYZ[i] /= (wtot * wtot);
275 clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i];
276
277 if (clRmsXYZ[i] > 0.0) {
278 clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]);
279 } else {
280 clRmsXYZ[i] = 0;
281 }
282 } else {
283 clRmsXYZ[i] = 0;
284 }
285 }
286 } else {
287 for (int i = 0; i < 3; i++) {
288 clXYZ[i] = clRmsXYZ[i] = -1.;
289 }
290 }
291
292 clusterAnalysis.setLocalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2]));
293}
294
297//____________________________________________________________________________
298template <class InputType>
299void ClusterFactory<InputType>::evalGlobalPosition(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
300{
301
302 int i = 0, nstat = 0;
303
304 double dist = tMaxInCm(double(clusterAnalysis.E()));
305
306 std::array<double, 3> clXYZ = {0., 0., 0.}, clRmsXYZ = {0., 0., 0.}, lxyzi{}, xyzi{};
307 double wtot = 0., w = 0.;
308
309 for (auto iInput : inputsIndices) {
310
311 // get the local coordinates of the cell
312 try {
313 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(lxyzi[0], lxyzi[1], lxyzi[2]);
314 } catch (InvalidCellIDException& e) {
315 LOG(error) << e.what();
316 continue;
317 }
318
319 // Now get the global coordinate
320 mGeomPtr->GetGlobal(lxyzi, xyzi, mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower()));
321
322 if (mLogWeight > 0.0) {
323 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
324 } else {
325 w = mInputsContainer[iInput].getEnergy(); // just energy
326 }
327
328 if (w > 0.0) {
329 wtot += w;
330 nstat++;
331
332 for (i = 0; i < 3; i++) {
333 clXYZ[i] += (w * xyzi[i]);
334 clRmsXYZ[i] += (w * xyzi[i] * xyzi[i]);
335 }
336 }
337 }
338
339 // cout << " wtot " << wtot << endl;
340
341 if (wtot > 0) {
342 // xRMS = TMath::Sqrt(x2m - xMean*xMean);
343 for (i = 0; i < 3; i++) {
344 clXYZ[i] /= wtot;
345
346 if (nstat > 1) {
347 clRmsXYZ[i] /= (wtot * wtot);
348 clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i];
349
350 if (clRmsXYZ[i] > 0.0) {
351 clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]);
352 } else {
353 clRmsXYZ[i] = 0;
354 }
355 } else {
356 clRmsXYZ[i] = 0;
357 }
358 }
359 } else {
360 for (i = 0; i < 3; i++) {
361 clXYZ[i] = clRmsXYZ[i] = -1.;
362 }
363 }
364
365 clusterAnalysis.setGlobalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2]));
366}
367
370//____________________________________________________________________________
371template <class InputType>
372void ClusterFactory<InputType>::evalLocalPositionFit(double deff, double mLogWeight,
373 double phiSlope, std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
374{
375 int i = 0, nstat = 0;
376 std::array<double, 3> clXYZ = {0., 0., 0.}, clRmsXYZ = {0., 0., 0.}, xyzi{};
377 double wtot = 0., w = 0.;
378
379 for (auto iInput : inputsIndices) {
380
381 try {
382 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), deff).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
383 } catch (InvalidCellIDException& e) {
384 LOG(error) << e.what();
385 continue;
386 }
387
388 if (mLogWeight > 0.0) {
389 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
390 } else {
391 w = mInputsContainer[iInput].getEnergy(); // just energy
392 }
393
394 if (w > 0.0) {
395 wtot += w;
396 nstat++;
397
398 for (i = 0; i < 3; i++) {
399 clXYZ[i] += (w * xyzi[i]);
400 clRmsXYZ[i] += (w * xyzi[i] * xyzi[i]);
401 }
402 }
403 } // loop
404
405 // cout << " wtot " << wtot << endl;
406
407 if (wtot > 0) {
408 // xRMS = TMath::Sqrt(x2m - xMean*xMean);
409 for (i = 0; i < 3; i++) {
410 clXYZ[i] /= wtot;
411
412 if (nstat > 1) {
413 clRmsXYZ[i] /= (wtot * wtot);
414 clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i];
415
416 if (clRmsXYZ[i] > 0.0) {
417 clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]);
418 } else {
419 clRmsXYZ[i] = 0;
420 }
421 } else {
422 clRmsXYZ[i] = 0;
423 }
424 }
425 } else {
426 for (i = 0; i < 3; i++) {
427 clXYZ[i] = clRmsXYZ[i] = -1.;
428 }
429 }
430
431 // clRmsXYZ[i] ??
432
433 if (phiSlope != 0.0 && mLogWeight > 0.0 && wtot != 0.0) {
434 // Correction in phi direction (y - coords here); Aug 16;
435 // May be put to global level or seperate method
436 double ycorr = clXYZ[1] * (1. + phiSlope);
437
438 // printf(" y %f : ycorr %f : slope %f \n", clXYZ[1], ycorr, phiSlope);
439 clXYZ[1] = ycorr;
440 }
441
442 clusterAnalysis.setLocalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2]));
443}
444
449//_____________________________________________________________________________
450template <class InputType>
451void ClusterFactory<InputType>::getDeffW0(const double esum, double& deff, double& w0)
452{
453 double e = 0.0;
454 const double kdp0 = 9.25147, kdp1 = 1.16700; // Hard coded now
455 const double kwp0 = 4.83713, kwp1 = -2.77970e-01, kwp2 = 4.41116;
456
457 // No extrapolation here
458 e = esum < 0.5 ? 0.5 : esum;
459 e = e > 100. ? 100. : e;
460
461 deff = kdp0 + kdp1 * TMath::Log(e);
462 w0 = kwp0 / (1. + TMath::Exp(kwp1 * (e + kwp2)));
463}
464
472//______________________________________________________________________________
473template <class InputType>
474void ClusterFactory<InputType>::evalCoreEnergy(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
475{
476
477 float coreEnergy = 0.;
478
479 if (clusterAnalysis.getLocalPosition().Mag2() > 0.) {
480 evalLocalPosition(inputsIndices, clusterAnalysis);
481 }
482
483 double phiPoint = clusterAnalysis.getLocalPosition().Phi();
484 double etaPoint = clusterAnalysis.getLocalPosition().Eta();
485 for (auto iInput : inputsIndices) {
486
487 auto [eta, phi] = mGeomPtr->EtaPhiFromIndex(mInputsContainer[iInput].getTower());
488 phi = phi * TMath::DegToRad();
489
490 double distance = TMath::Sqrt((eta - etaPoint) * (eta - etaPoint) + (phi - phiPoint) * (phi - phiPoint));
491
492 if (distance < mCoreRadius) {
493 coreEnergy += mInputsContainer[iInput].getEnergy();
494 }
495 }
496 clusterAnalysis.setCoreEnergy(coreEnergy);
497}
498
501//____________________________________________________________________________
502template <class InputType>
503void ClusterFactory<InputType>::evalNExMax(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
504{
505 // Pre-compute cell indices and energies for all cells in cluster to avoid multiple expensive geometry lookups
506 const size_t n = inputsIndices.size();
507 std::vector<short> rows;
508 std::vector<short> columns;
509 std::vector<double> energies;
510
511 rows.reserve(n);
512 columns.reserve(n);
513 energies.reserve(n);
514
515 for (auto iInput : inputsIndices) {
516 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
517
518 // get a nice topological indexing that is done in exactly the same way as used by the clusterizer
519 // this way we can handle the shared cluster cases correctly
520 const auto [row, column] = mGeomPtr->GetTopologicalRowColumn(nSupMod, nModule, nIphi, nIeta);
521
522 rows.push_back(row);
523 columns.push_back(column);
524 energies.push_back(mInputsContainer[iInput].getEnergy());
525 }
526
527 // Now find local maxima using pre-computed data
528 int nExMax = 0;
529 for (size_t i = 0; i < n; i++) {
530 // this cell is assumed to be local maximum unless we find a higher energy cell in the neighborhood
531 bool isExMax = true;
532
533 // loop over all other cells in cluster
534 for (size_t j = 0; j < n; j++) {
535 if (i == j) {
536 continue;
537 }
538
539 // adjacent cell is any cell with adjacent phi or eta index
540 if (std::abs(rows[i] - rows[j]) <= 1 &&
541 std::abs(columns[i] - columns[j]) <= 1) {
542
543 // if there is a cell with higher energy than the current cell, it is not a local maximum
544 if (energies[j] > energies[i]) {
545 isExMax = false;
546 break;
547 }
548 }
549 }
550 if (isExMax) {
551 nExMax++;
552 }
553 }
554 clusterAnalysis.setNExMax(nExMax);
555}
556
560//____________________________________________________________________________
561template <class InputType>
562void ClusterFactory<InputType>::evalElipsAxis(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
563{
564 double wtot = 0.;
565 double x = 0.;
566 double z = 0.;
567 double dxx = 0.;
568 double dzz = 0.;
569 double dxz = 0.;
570
571 std::array<float, 2> lambda{};
572
573 for (auto iInput : inputsIndices) {
574
575 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
576 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
577
578 // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
579 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
580 if (mSharedCluster && nSupMod % 2) {
581 ieta += EMCAL_COLS;
582 }
583
584 auto etai = static_cast<double>(ieta);
585 auto phii = static_cast<double>(iphi);
586
587 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E()));
588 // clusterAnalysis.E() summed amplitude of inputs, i.e. energy of cluster
589 // Gives smaller value of lambda than log weight
590 // w = mEnergyList[iInput] / clusterAnalysis.E(); // Nov 16, 2006 - try just energy
591
592 dxx += w * etai * etai;
593 x += w * etai;
594 dzz += w * phii * phii;
595 z += w * phii;
596
597 dxz += w * etai * phii;
598
599 wtot += w;
600 }
601
602 if (wtot > 0) {
603 dxx /= wtot;
604 x /= wtot;
605 dxx -= x * x;
606 dzz /= wtot;
607 z /= wtot;
608 dzz -= z * z;
609 dxz /= wtot;
610 dxz -= x * z;
611
612 lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
613
614 if (lambda[0] > 0) {
615 lambda[0] = TMath::Sqrt(lambda[0]);
616 } else {
617 lambda[0] = 0;
618 }
619
620 lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
621
622 if (lambda[1] > 0) { // To avoid exception if numerical errors lead to negative lambda.
623 lambda[1] = TMath::Sqrt(lambda[1]);
624 } else {
625 lambda[1] = 0.;
626 }
627 } else {
628 lambda[0] = 0.;
629 lambda[1] = 0.;
630 }
631
632 clusterAnalysis.setM02(lambda[0] * lambda[0]);
633 clusterAnalysis.setM20(lambda[1] * lambda[1]);
634}
635
638//____________________________________________________________________________
639template <class InputType>
640std::tuple<int, float, float, bool> ClusterFactory<InputType>::getMaximalEnergyIndex(std::span<const int> inputsIndices) const
641{
642
643 float energy = 0.;
644 int mid = 0;
645 float cellAmp = 0;
646 int iSupMod0 = -1;
647 bool shared = false;
648 for (auto iInput : inputsIndices) {
649 if (iInput >= mInputsContainer.size()) {
650 throw CellIndexRangeException(iInput, mInputsContainer.size());
651 }
652 cellAmp += mInputsContainer[iInput].getEnergy();
653 if (iSupMod0 == -1) {
654 iSupMod0 = mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower());
655 } else if (iSupMod0 != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
656 shared = true;
657 }
658 if (mInputsContainer[iInput].getEnergy() > energy) {
659 energy = mInputsContainer[iInput].getEnergy();
660 mid = iInput;
661 }
662 } // loop on cluster inputs
663
664 return std::make_tuple(mid, energy, cellAmp, shared);
665}
666
669//____________________________________________________________________________
670template <class InputType>
671bool ClusterFactory<InputType>::isExoticCell(short towerId, float ecell, float const exoticTime, float& fCross) const
672{
673 if (ecell < mExoticCellMinAmplitude) {
674 return false; // do not reject low energy cells
675 }
676
677 // if the look up table is not set yet (mostly due to a reset call) then set it up now.
678 if (!getLookUpInit()) {
680 }
681
682 float eCross = getECross(towerId, ecell, exoticTime);
683 fCross = 1.f - eCross / ecell;
684
685 if (fCross > mExoticCellFraction) {
686 LOG(debug) << "EXOTIC CELL id " << towerId << ", eCell " << ecell << ", eCross " << eCross << ", 1-eCross/eCell " << 1 - eCross / ecell;
687 return true;
688 }
689
690 return false;
691}
692
695//____________________________________________________________________________
696template <class InputType>
697float ClusterFactory<InputType>::getECross(short absID, float energy, float const exoticTime) const
698{
699 auto [iSM, iMod, iIphi, iIeta] = mGeomPtr->GetCellIndex(absID);
700 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta);
701
702 // Get close cells index, energy and time, not in corners
703
704 short towerId1 = -1;
705 short towerId2 = -1;
706
707 if (iphi < o2::emcal::EMCAL_ROWS - 1) {
708 try {
709 towerId1 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta);
710 } catch (InvalidCellIDException& e) {
711 towerId1 = -1 * e.getCellID();
712 }
713 }
714 if (iphi > 0) {
715 try {
716 towerId2 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta);
717 } catch (InvalidCellIDException& e) {
718 towerId2 = -1 * e.getCellID();
719 }
720 }
721
722 // In case of cell in eta = 0 border, depending on SM shift the cross cell index
723
724 short towerId3 = -1;
725 short towerId4 = -1;
726
727 if (ieta == o2::emcal::EMCAL_COLS - 1 && (iSM % 2) == 0) {
728 try {
729 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM + 1, iphi, 0);
730 } catch (InvalidCellIDException& e) {
731 towerId3 = -1 * e.getCellID();
732 }
733 try {
734 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
735 } catch (InvalidCellIDException& e) {
736 towerId4 = -1 * e.getCellID();
737 }
738 } else if (ieta == 0 && (iSM % 2) != 0) {
739 try {
740 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
741 } catch (InvalidCellIDException& e) {
742 towerId3 = -1 * e.getCellID();
743 }
744 try {
745 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM - 1, iphi, o2::emcal::EMCAL_COLS - 1);
746 } catch (InvalidCellIDException& e) {
747 towerId4 = -1 * e.getCellID();
748 }
749 } else {
750 if (ieta < o2::emcal::EMCAL_COLS - 1) {
751 try {
752 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
753 } catch (InvalidCellIDException& e) {
754 towerId3 = -1 * e.getCellID();
755 }
756 }
757 if (ieta > 0) {
758 try {
759 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
760 } catch (InvalidCellIDException& e) {
761 towerId4 = -1 * e.getCellID();
762 }
763 }
764 }
765
766 LOG(debug) << "iSM " << iSM << ", absID " << absID << ", a " << towerId1 << ", b " << towerId2 << ", c " << towerId3 << ", e " << towerId3;
767
768 short index1 = (towerId1 > -1) ? mLoolUpTowerToIndex.at(towerId1) : -1;
769 short index2 = (towerId2 > -1) ? mLoolUpTowerToIndex.at(towerId2) : -1;
770 short index3 = (towerId3 > -1) ? mLoolUpTowerToIndex.at(towerId3) : -1;
771 short index4 = (towerId4 > -1) ? mLoolUpTowerToIndex.at(towerId4) : -1;
772
773 std::array<std::pair<float, float>, 4> cellData = {
774 {{(index1 > -1) ? mInputsContainer[index1].getEnergy() : 0., (index1 > -1) ? mInputsContainer[index1].getTimeStamp() : 0.},
775 {(index2 > -1) ? mInputsContainer[index2].getEnergy() : 0., (index2 > -1) ? mInputsContainer[index2].getTimeStamp() : 0.},
776 {(index3 > -1) ? mInputsContainer[index3].getEnergy() : 0., (index3 > -1) ? mInputsContainer[index3].getTimeStamp() : 0.},
777 {(index4 > -1) ? mInputsContainer[index4].getEnergy() : 0., (index4 > -1) ? mInputsContainer[index4].getTimeStamp() : 0.}}};
778
779 for (auto& cell : cellData) {
780 if (std::abs(exoticTime - cell.second) > mExoticCellDiffTime) {
781 cell.first = 0;
782 }
783 }
784
785 float w1 = 1, w2 = 1, w3 = 1, w4 = 1;
786 if (mUseWeightExotic) {
787 w1 = GetCellWeight(cellData[0].first, energy);
788 w2 = GetCellWeight(cellData[1].first, energy);
789 w3 = GetCellWeight(cellData[2].first, energy);
790 w4 = GetCellWeight(cellData[3].first, energy);
791 }
792
793 if (cellData[0].first < mExoticCellInCrossMinAmplitude || w1 <= 0) {
794 cellData[0].first = 0;
795 }
796 if (cellData[1].first < mExoticCellInCrossMinAmplitude || w2 <= 0) {
797 cellData[1].first = 0;
798 }
799 if (cellData[2].first < mExoticCellInCrossMinAmplitude || w3 <= 0) {
800 cellData[2].first = 0;
801 }
802 if (cellData[3].first < mExoticCellInCrossMinAmplitude || w4 <= 0) {
803 cellData[3].first = 0;
804 }
805
806 return cellData[0].first + cellData[1].first + cellData[2].first + cellData[3].first;
807}
808
811//____________________________________________________________________________
812template <class InputType>
813float ClusterFactory<InputType>::GetCellWeight(float eCell, float eCluster) const
814{
815 if (eCell > 0 && eCluster > 0) {
816 if (mLogWeight > 0) {
817 return std::max(0.f, mLogWeight + std::log(eCell / eCluster));
818 }
819 return std::log(eCluster / eCell);
820 }
821 return 0.;
822}
823
826//____________________________________________________________________________
827template <class InputType>
828int ClusterFactory<InputType>::getMultiplicityAtLevel(float level, std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
829{
830 int multipl = 0;
831 for (auto iInput : inputsIndices) {
832 if (mInputsContainer[iInput].getEnergy() > level * clusterAnalysis.E()) {
833 multipl++;
834 }
835 }
836
837 return multipl;
838}
839
842//____________________________________________________________________________
843template <class InputType>
844void ClusterFactory<InputType>::evalTime(std::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const
845{
846 float maxE = 0;
847 unsigned short maxAt = 0;
848 for (auto iInput : inputsIndices) {
849 if (mInputsContainer[iInput].getEnergy() > maxE) {
850 maxE = mInputsContainer[iInput].getEnergy();
851 maxAt = iInput;
852 }
853 }
854
855 clusterAnalysis.setClusterTime(mInputsContainer[maxAt].getTimeStamp());
856}
857
861//_____________________________________________________________________
862template <class InputType>
863double ClusterFactory<InputType>::tMaxInCm(const double e, const int key) const
864{
865 const double ca = 4.82; // shower max parameter - first guess; ca=TMath::Log(1000./8.07)
866 double tmax = 0.; // position of electromagnetic shower max in cm
867
868 const double x0 = 1.31; // radiation lenght (cm)
869
870 if (e > 0.1) {
871 tmax = TMath::Log(e) + ca;
872 if (key == 0) {
873 tmax += 0.5;
874 } else {
875 tmax -= 0.5;
876 }
877 tmax *= x0; // convert to cm
878 }
879
880 return tmax;
881}
882
885//______________________________________________________________________________
886template <class InputType>
888{
889 return (2. * TMath::ATan(TMath::Exp(-arg)));
890}
891
894//______________________________________________________________________________
895template <class InputType>
897{
898 return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
899}
900
901template <class InputType>
902ClusterFactory<InputType>::ClusterIterator::ClusterIterator(const ClusterFactory& factory, int clusterIndex, bool forward) : mClusterFactory(&factory),
903 mCurrentCluster(mClusterFactory->buildCluster(clusterIndex)),
904 mClusterID(clusterIndex),
905 mForward(forward)
906{
907}
908
909template <class InputType>
911{
912 return mClusterFactory == rhs.mClusterFactory && mClusterID == rhs.mClusterID && mForward == rhs.mForward;
913}
914
915template <class InputType>
917{
918 if (mForward) {
919 mClusterID++;
920 } else {
921 mClusterID--;
922 }
923 mCurrentCluster = mClusterFactory->buildCluster(mClusterID);
924 return *this;
925}
926
927template <class InputType>
929{
930 auto tmp = *this;
931 ++(*this);
932 return tmp;
933}
934
935template <class InputType>
937{
938 if (mForward) {
939 mClusterID--;
940 } else {
941 mClusterID++;
942 }
943 mCurrentCluster = mClusterFactory->buildCluster(mClusterID);
944 return *this;
945}
946
947template <class InputType>
949{
950 auto tmp = *this;
951 --(*this);
952 return tmp;
953}
954
std::ostringstream debug
int32_t i
uint32_t j
Definition RawData.h:0
StringRef key
Cluster class for kinematic cluster parametersported from AliVCluster in AliRoot.
void setNExMax(unsigned char nExMax)
void setFCross(float fCross)
void setCoreEnergy(float energy)
math_utils::Point3D< float > getLocalPosition() const
void setGlobalPosition(const math_utils::Point3D< float > &x)
Set the cluster global position.
void setCellsIndices(const std::vector< unsigned short > &array)
Set the array of cell indices.
void setLocalPosition(const math_utils::Point3D< float > &x)
void setIndMaxInput(const int ind)
void setClusterTime(float time)
ClusterIterator & operator--()
Prefix decrementation operator.
ClusterIterator(const ClusterFactory &factory, int clusterIndex, bool forward)
Constructor, initializing the iterator.
bool operator==(const ClusterIterator &rhs) const
Check for equalness.
ClusterIterator & operator++()
Prefix incrementation operator.
Exception handling uninitialized look up table.
const char * what() const noexcept final
Access to error message of the exception.
EMCal clusters factory Ported from class AliEMCALcluster.
void reset()
Reset containers.
float GetCellWeight(float eCell, float eCluster) const
return weight of cell for shower shape calculation
float thetaToEta(float arg) const
Converts Theta (Radians) to Eta (Radians)
void evalGlobalPosition(std::span< const int > inputsIndices, AnalysisCluster &cluster) const
Calculates the center of gravity in the global ALICE coordinates.
std::tuple< int, float, float, bool > getMaximalEnergyIndex(std::span< const int > inputsIndices) const
Finds the maximum energy in the cluster and computes the Summed amplitude of digits/cells.
float getECross(short absID, float energy, float const exoticTime) const
Calculate the energy in the cross around the energy of a given cell.
int getMultiplicityAtLevel(float level, std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Calculates the multiplicity of digits/cells with energy larger than level*energy.
Double_t tMaxInCm(const Double_t e=0.0, const int key=0) const
void evalTime(std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Time is set to the time of the digit with the maximum energy.
void evalLocalPosition(std::span< const int > inputsIndices, AnalysisCluster &cluster) const
Calculates the center of gravity in the local EMCAL-module coordinates.
static void getDeffW0(const Double_t esum, Double_t &deff, Double_t &w0)
ClusterFactory()=default
Dummy constructor.
void evalLocalPositionFit(double deff, double mLogWeight, double phiSlope, std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
evaluates local position of clusters in SM
void evalCoreEnergy(std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
void evalDispersion(std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
float etaToTheta(float arg) const
Converts Eta (Radians) to Theta (Radians)
bool isExoticCell(short towerId, float ecell, float const exoticTime, float &fCross) const
Look to cell neighbourhood and reject if it seems exotic.
void evalElipsAxis(std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
AnalysisCluster buildCluster(int index, o2::emcal::ClusterLabel *clusterLabel=nullptr) const
evaluates cluster parameters: position, shower shape, primaries ...
void evalNExMax(std::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Calculate the number of local maxima in the cluster.
cluster class for MC particle IDs and their respective energy fraction
void orderLabels()
Sort the labels and energy fraction in descending order (largest energy fraction to smallest)
void normalize(float factor)
Normalize the energy fraction.
void addValue(int label, float energyFraction)
Add label and energy fraction to the.
Exception handling non-existing cell IDs.
int getCellID() const noexcept
Access to cell ID raising the exception.
const char * what() const noexcept final
Access to error message of the exception.
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizei GLsizei GLfloat distance
Definition glcorearb.h:5506
GLuint GLfloat x0
Definition glcorearb.h:5034
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
@ EMCAL_ROWS
Number of rows per module for EMCAL.
Definition Constants.h:25
@ EMCAL_COLS
Number of columns per module for EMCAL.
Definition Constants.h:26
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row
std::vector< ReadoutWindowData > rows