31template <
class InputType>
34 setContainer(clustersContainer, inputsContainer, cellsIndices);
37template <
class InputType>
40 mClustersContainer = std::span<const o2::emcal::Cluster>();
41 mInputsContainer = std::span<const InputType>();
42 mCellsIndices = std::span<int>();
44 mCellLabelContainer = std::span<const o2::emcal::CellLabel>();
50template <
class InputType>
53 if (clusterIndex >= mClustersContainer.size()) {
61 clusterAnalysis.
setID(clusterIndex);
63 int firstCellIndex = mClustersContainer[clusterIndex].getCellIndexFirst();
64 int nCells = mClustersContainer[clusterIndex].getNCells();
66 std::span<const int> inputsIndices = std::span<const int>(&mCellsIndices[firstCellIndex], nCells);
71 auto [inputIndMax, inputEnergyMax, cellAmp, shared] = getMaximalEnergyIndex(inputsIndices);
73 short towerId = mInputsContainer[inputIndMax].getTower();
75 float exoticTime = mInputsContainer[inputIndMax].getTimeStamp();
80 clusterAnalysis.
setIsExotic(isExoticCell(towerId, inputEnergyMax, exoticTime, fCross));
88 clusterAnalysis.
setE(cellAmp);
90 mSuperModuleNumber = mGeomPtr->GetSuperModuleNumber(towerId);
92 clusterAnalysis.
setNCells(inputsIndices.size());
94 std::vector<unsigned short> cellsIdices;
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) {
104 clusterLabel->
addValue(mCellLabelContainer[cellIndex].GetLabel(iLabel),
105 mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) * mInputsContainer[cellIndex].getEnergy());
109 if (addClusterLabels) {
117 evalGlobalPosition(inputsIndices, clusterAnalysis);
118 evalLocalPosition(inputsIndices, clusterAnalysis);
121 evalElipsAxis(inputsIndices, clusterAnalysis);
122 evalDispersion(inputsIndices, clusterAnalysis);
125 evalNExMax(inputsIndices, clusterAnalysis);
127 evalCoreEnergy(inputsIndices, clusterAnalysis);
128 evalTime(inputsIndices, clusterAnalysis);
140 return clusterAnalysis;
147template <
class InputType>
150 double d = 0., wtot = 0.;
154 double etaMean = 0.0, phiMean = 0.0;
157 for (
auto iInput : inputsIndices) {
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);
165 if (mSharedCluster && nSupMod % 2) {
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()));
185 LOG(error) << Form(
"Wrong weight %f\n", wtot);
189 for (
auto iInput : inputsIndices) {
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);
197 if (mSharedCluster && nSupMod % 2) {
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()));
207 d +=
w * ((etai - etaMean) * (etai - etaMean) + (phii - phiMean) * (phii - phiMean));
212 if (wtot > 0 && nstat > 1) {
224template <
class InputType>
230 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
232 std::array<double, 3> clXYZ = {0., 0., 0.}, clRmsXYZ = {0., 0., 0.}, xyzi{};
233 double wtot = 0.,
w = 0.;
235 for (
auto iInput : inputsIndices) {
238 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
245 if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
249 if (mLogWeight > 0.0) {
250 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
252 w = mInputsContainer[iInput].getEnergy();
259 for (
int i = 0;
i < 3;
i++) {
260 clXYZ[
i] += (
w * xyzi[
i]);
261 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
270 for (
int i = 0;
i < 3;
i++) {
274 clRmsXYZ[
i] /= (wtot * wtot);
275 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
277 if (clRmsXYZ[
i] > 0.0) {
278 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
287 for (
int i = 0;
i < 3;
i++) {
288 clXYZ[
i] = clRmsXYZ[
i] = -1.;
298template <
class InputType>
302 int i = 0, nstat = 0;
304 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
306 std::array<double, 3> clXYZ = {0., 0., 0.}, clRmsXYZ = {0., 0., 0.}, lxyzi{}, xyzi{};
307 double wtot = 0.,
w = 0.;
309 for (
auto iInput : inputsIndices) {
313 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(lxyzi[0], lxyzi[1], lxyzi[2]);
320 mGeomPtr->GetGlobal(lxyzi, xyzi, mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower()));
322 if (mLogWeight > 0.0) {
323 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
325 w = mInputsContainer[iInput].getEnergy();
332 for (
i = 0;
i < 3;
i++) {
333 clXYZ[
i] += (
w * xyzi[
i]);
334 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
343 for (
i = 0;
i < 3;
i++) {
347 clRmsXYZ[
i] /= (wtot * wtot);
348 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
350 if (clRmsXYZ[
i] > 0.0) {
351 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
360 for (
i = 0;
i < 3;
i++) {
361 clXYZ[
i] = clRmsXYZ[
i] = -1.;
371template <
class InputType>
373 double phiSlope, std::span<const int> inputsIndices,
AnalysisCluster& clusterAnalysis)
const
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.;
379 for (
auto iInput : inputsIndices) {
382 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), deff).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
388 if (mLogWeight > 0.0) {
389 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
391 w = mInputsContainer[iInput].getEnergy();
398 for (
i = 0;
i < 3;
i++) {
399 clXYZ[
i] += (
w * xyzi[
i]);
400 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
409 for (
i = 0;
i < 3;
i++) {
413 clRmsXYZ[
i] /= (wtot * wtot);
414 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
416 if (clRmsXYZ[
i] > 0.0) {
417 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
426 for (
i = 0;
i < 3;
i++) {
427 clXYZ[
i] = clRmsXYZ[
i] = -1.;
433 if (phiSlope != 0.0 && mLogWeight > 0.0 && wtot != 0.0) {
436 double ycorr = clXYZ[1] * (1. + phiSlope);
450template <
class InputType>
454 const double kdp0 = 9.25147, kdp1 = 1.16700;
455 const double kwp0 = 4.83713, kwp1 = -2.77970e-01, kwp2 = 4.41116;
458 e = esum < 0.5 ? 0.5 : esum;
459 e = e > 100. ? 100. : e;
461 deff = kdp0 + kdp1 * TMath::Log(e);
462 w0 = kwp0 / (1. + TMath::Exp(kwp1 * (e + kwp2)));
473template <
class InputType>
477 float coreEnergy = 0.;
480 evalLocalPosition(inputsIndices, clusterAnalysis);
485 for (
auto iInput : inputsIndices) {
487 auto [eta, phi] = mGeomPtr->EtaPhiFromIndex(mInputsContainer[iInput].getTower());
488 phi = phi * TMath::DegToRad();
490 double distance = TMath::Sqrt((eta - etaPoint) * (eta - etaPoint) + (phi - phiPoint) * (phi - phiPoint));
493 coreEnergy += mInputsContainer[iInput].getEnergy();
502template <
class InputType>
506 const size_t n = inputsIndices.size();
507 std::vector<short>
rows;
508 std::vector<short> columns;
509 std::vector<double> energies;
515 for (
auto iInput : inputsIndices) {
516 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
520 const auto [
row, column] = mGeomPtr->GetTopologicalRowColumn(nSupMod, nModule, nIphi, nIeta);
523 columns.push_back(column);
524 energies.push_back(mInputsContainer[iInput].getEnergy());
529 for (
size_t i = 0;
i <
n;
i++) {
534 for (
size_t j = 0;
j <
n;
j++) {
541 std::abs(columns[
i] - columns[
j]) <= 1) {
544 if (energies[
j] > energies[
i]) {
561template <
class InputType>
571 std::array<float, 2> lambda{};
573 for (
auto iInput : inputsIndices) {
575 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
576 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
580 if (mSharedCluster && nSupMod % 2) {
584 auto etai =
static_cast<double>(ieta);
585 auto phii =
static_cast<double>(iphi);
587 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
592 dxx +=
w * etai * etai;
594 dzz +=
w * phii * phii;
597 dxz +=
w * etai * phii;
612 lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
615 lambda[0] = TMath::Sqrt(lambda[0]);
620 lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
623 lambda[1] = TMath::Sqrt(lambda[1]);
632 clusterAnalysis.
setM02(lambda[0] * lambda[0]);
633 clusterAnalysis.
setM20(lambda[1] * lambda[1]);
639template <
class InputType>
648 for (
auto iInput : inputsIndices) {
649 if (iInput >= mInputsContainer.size()) {
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())) {
658 if (mInputsContainer[iInput].getEnergy() > energy) {
659 energy = mInputsContainer[iInput].getEnergy();
664 return std::make_tuple(mid, energy, cellAmp, shared);
670template <
class InputType>
673 if (ecell < mExoticCellMinAmplitude) {
678 if (!getLookUpInit()) {
682 float eCross = getECross(towerId, ecell, exoticTime);
683 fCross = 1.f - eCross / ecell;
685 if (fCross > mExoticCellFraction) {
686 LOG(
debug) <<
"EXOTIC CELL id " << towerId <<
", eCell " << ecell <<
", eCross " << eCross <<
", 1-eCross/eCell " << 1 - eCross / ecell;
696template <
class InputType>
699 auto [iSM, iMod, iIphi, iIeta] = mGeomPtr->GetCellIndex(absID);
700 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta);
709 towerId1 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta);
716 towerId2 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta);
729 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM + 1, iphi, 0);
734 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
738 }
else if (ieta == 0 && (iSM % 2) != 0) {
740 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
752 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
759 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
766 LOG(
debug) <<
"iSM " << iSM <<
", absID " << absID <<
", a " << towerId1 <<
", b " << towerId2 <<
", c " << towerId3 <<
", e " << towerId3;
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;
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.}}};
779 for (
auto& cell : cellData) {
780 if (std::abs(exoticTime - cell.second) > mExoticCellDiffTime) {
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);
793 if (cellData[0].
first < mExoticCellInCrossMinAmplitude || w1 <= 0) {
794 cellData[0].first = 0;
796 if (cellData[1].
first < mExoticCellInCrossMinAmplitude || w2 <= 0) {
797 cellData[1].first = 0;
799 if (cellData[2].
first < mExoticCellInCrossMinAmplitude || w3 <= 0) {
800 cellData[2].first = 0;
802 if (cellData[3].
first < mExoticCellInCrossMinAmplitude || w4 <= 0) {
803 cellData[3].first = 0;
806 return cellData[0].first + cellData[1].first + cellData[2].first + cellData[3].first;
812template <
class InputType>
815 if (eCell > 0 && eCluster > 0) {
816 if (mLogWeight > 0) {
817 return std::max(0.f, mLogWeight + std::log(eCell / eCluster));
819 return std::log(eCluster / eCell);
827template <
class InputType>
831 for (
auto iInput : inputsIndices) {
832 if (mInputsContainer[iInput].getEnergy() >
level * clusterAnalysis.
E()) {
843template <
class InputType>
847 unsigned short maxAt = 0;
848 for (
auto iInput : inputsIndices) {
849 if (mInputsContainer[iInput].getEnergy() > maxE) {
850 maxE = mInputsContainer[iInput].getEnergy();
855 clusterAnalysis.
setClusterTime(mInputsContainer[maxAt].getTimeStamp());
862template <
class InputType>
865 const double ca = 4.82;
868 const double x0 = 1.31;
871 tmax = TMath::Log(e) + ca;
886template <
class InputType>
889 return (2. * TMath::ATan(TMath::Exp(-arg)));
895template <
class InputType>
898 return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
901template <
class InputType>
903 mCurrentCluster(mClusterFactory->buildCluster(clusterIndex)),
904 mClusterID(clusterIndex),
909template <
class InputType>
912 return mClusterFactory == rhs.mClusterFactory && mClusterID == rhs.mClusterID && mForward == rhs.mForward;
915template <
class InputType>
923 mCurrentCluster = mClusterFactory->buildCluster(mClusterID);
927template <
class InputType>
935template <
class InputType>
943 mCurrentCluster = mClusterFactory->buildCluster(mClusterID);
947template <
class InputType>
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 setDispersion(float disp)
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.
GLsizei GLsizei GLfloat distance
GLubyte GLubyte GLubyte GLubyte w
GLdouble GLdouble GLdouble z
@ EMCAL_ROWS
Number of rows per module for EMCAL.
@ EMCAL_COLS
Number of columns per module for EMCAL.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< ReadoutWindowData > rows