30template <
class InputType>
33 setContainer(clustersContainer, inputsContainer, cellsIndices);
36template <
class InputType>
39 mClustersContainer = gsl::span<const o2::emcal::Cluster>();
40 mInputsContainer = gsl::span<const InputType>();
41 mCellsIndices = gsl::span<int>();
43 mCellLabelContainer = gsl::span<const o2::emcal::CellLabel>();
49template <
class InputType>
52 if (clusterIndex >= mClustersContainer.size()) {
60 clusterAnalysis.
setID(clusterIndex);
62 int firstCellIndex = mClustersContainer[clusterIndex].getCellIndexFirst();
63 int nCells = mClustersContainer[clusterIndex].getNCells();
65 gsl::span<const int> inputsIndices = gsl::span<const int>(&mCellsIndices[firstCellIndex], nCells);
70 auto [inputIndMax, inputEnergyMax, cellAmp, shared] = getMaximalEnergyIndex(inputsIndices);
72 short towerId = mInputsContainer[inputIndMax].getTower();
74 float exoticTime = mInputsContainer[inputIndMax].getTimeStamp();
79 clusterAnalysis.
setIsExotic(isExoticCell(towerId, inputEnergyMax, exoticTime, fCross));
87 clusterAnalysis.
setE(cellAmp);
89 mSuperModuleNumber = mGeomPtr->GetSuperModuleNumber(towerId);
91 clusterAnalysis.
setNCells(inputsIndices.size());
93 std::vector<unsigned short> cellsIdices;
95 bool addClusterLabels = ((clusterLabel !=
nullptr) && (mCellLabelContainer.size() > 0));
96 for (
auto cellIndex : inputsIndices) {
97 cellsIdices.push_back(cellIndex);
98 if (addClusterLabels) {
99 for (
size_t iLabel = 0; iLabel < mCellLabelContainer[cellIndex].GetLabelSize(); iLabel++) {
100 if (mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) <= 0.f) {
103 clusterLabel->
addValue(mCellLabelContainer[cellIndex].GetLabel(iLabel),
104 mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) * mInputsContainer[cellIndex].getEnergy());
108 if (addClusterLabels) {
116 evalGlobalPosition(inputsIndices, clusterAnalysis);
117 evalLocalPosition(inputsIndices, clusterAnalysis);
120 evalElipsAxis(inputsIndices, clusterAnalysis);
121 evalDispersion(inputsIndices, clusterAnalysis);
124 evalNExMax(inputsIndices, clusterAnalysis);
126 evalCoreEnergy(inputsIndices, clusterAnalysis);
127 evalTime(inputsIndices, clusterAnalysis);
139 return clusterAnalysis;
146template <
class InputType>
149 double d = 0., wtot = 0.;
153 double etaMean = 0.0, phiMean = 0.0;
156 for (
auto iInput : inputsIndices) {
158 if (clusterAnalysis.
E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
159 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
160 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
164 if (mSharedCluster && nSupMod % 2) {
168 double etai = (double)ieta;
169 double phii = (double)iphi;
170 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
184 LOG(error) << Form(
"Wrong weight %f\n", wtot);
188 for (
auto iInput : inputsIndices) {
190 if (clusterAnalysis.
E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
191 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
192 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
196 if (mSharedCluster && nSupMod % 2) {
200 double etai = (double)ieta;
201 double phii = (double)iphi;
202 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
206 d +=
w * ((etai - etaMean) * (etai - etaMean) + (phii - phiMean) * (phii - phiMean));
211 if (wtot > 0 && nstat > 1) {
223template <
class InputType>
229 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
231 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, xyzi[3], wtot = 0.,
w = 0.;
233 for (
auto iInput : inputsIndices) {
236 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
243 if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
247 if (mLogWeight > 0.0) {
248 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
250 w = mInputsContainer[iInput].getEnergy();
257 for (
int i = 0;
i < 3;
i++) {
258 clXYZ[
i] += (
w * xyzi[
i]);
259 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
268 for (
int i = 0;
i < 3;
i++) {
272 clRmsXYZ[
i] /= (wtot * wtot);
273 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
275 if (clRmsXYZ[
i] > 0.0) {
276 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
285 for (
int i = 0;
i < 3;
i++) {
286 clXYZ[
i] = clRmsXYZ[
i] = -1.;
296template <
class InputType>
300 int i = 0, nstat = 0;
302 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
304 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, lxyzi[3], xyzi[3], wtot = 0.,
w = 0.;
306 for (
auto iInput : inputsIndices) {
310 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(lxyzi[0], lxyzi[1], lxyzi[2]);
317 mGeomPtr->GetGlobal(lxyzi, xyzi, mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower()));
319 if (mLogWeight > 0.0) {
320 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
322 w = mInputsContainer[iInput].getEnergy();
329 for (
i = 0;
i < 3;
i++) {
330 clXYZ[
i] += (
w * xyzi[
i]);
331 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
340 for (
i = 0;
i < 3;
i++) {
344 clRmsXYZ[
i] /= (wtot * wtot);
345 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
347 if (clRmsXYZ[
i] > 0.0) {
348 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
357 for (
i = 0;
i < 3;
i++) {
358 clXYZ[
i] = clRmsXYZ[
i] = -1.;
368template <
class InputType>
370 double phiSlope, gsl::span<const int> inputsIndices,
AnalysisCluster& clusterAnalysis)
const
372 int i = 0, nstat = 0;
373 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, xyzi[3], wtot = 0.,
w = 0.;
375 for (
auto iInput : inputsIndices) {
378 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), deff).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
384 if (mLogWeight > 0.0) {
385 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
387 w = mInputsContainer[iInput].getEnergy();
394 for (
i = 0;
i < 3;
i++) {
395 clXYZ[
i] += (
w * xyzi[
i]);
396 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
405 for (
i = 0;
i < 3;
i++) {
409 clRmsXYZ[
i] /= (wtot * wtot);
410 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
412 if (clRmsXYZ[
i] > 0.0) {
413 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
422 for (
i = 0;
i < 3;
i++) {
423 clXYZ[
i] = clRmsXYZ[
i] = -1.;
429 if (phiSlope != 0.0 && mLogWeight > 0.0 && wtot) {
432 double ycorr = clXYZ[1] * (1. + phiSlope);
446template <
class InputType>
450 const double kdp0 = 9.25147, kdp1 = 1.16700;
451 const double kwp0 = 4.83713, kwp1 = -2.77970e-01, kwp2 = 4.41116;
454 e = esum < 0.5 ? 0.5 : esum;
455 e = e > 100. ? 100. : e;
457 deff = kdp0 + kdp1 * TMath::Log(e);
458 w0 = kwp0 / (1. + TMath::Exp(kwp1 * (e + kwp2)));
469template <
class InputType>
473 float coreEnergy = 0.;
476 evalLocalPosition(inputsIndices, clusterAnalysis);
481 for (
auto iInput : inputsIndices) {
483 auto [eta, phi] = mGeomPtr->EtaPhiFromIndex(mInputsContainer[iInput].getTower());
484 phi = phi * TMath::DegToRad();
486 double distance = TMath::Sqrt((eta - etaPoint) * (eta - etaPoint) + (phi - phiPoint) * (phi - phiPoint));
489 coreEnergy += mInputsContainer[iInput].getEnergy();
498template <
class InputType>
502 const size_t n = inputsIndices.size();
503 std::vector<short>
rows;
504 std::vector<short> columns;
505 std::vector<double> energies;
511 for (
auto iInput : inputsIndices) {
512 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
516 const auto [
row, column] = mGeomPtr->GetTopologicalRowColumn(nSupMod, nModule, nIphi, nIeta);
519 columns.push_back(column);
520 energies.push_back(mInputsContainer[iInput].getEnergy());
525 for (
size_t i = 0;
i <
n;
i++) {
530 for (
size_t j = 0;
j <
n;
j++) {
536 std::abs(columns[
i] - columns[
j]) <= 1) {
539 if (energies[
j] > energies[
i]) {
556template <
class InputType>
566 std::array<float, 2> lambda;
568 for (
auto iInput : inputsIndices) {
570 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
571 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
575 if (mSharedCluster && nSupMod % 2) {
579 double etai = (double)ieta;
580 double phii = (double)iphi;
582 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
587 dxx +=
w * etai * etai;
589 dzz +=
w * phii * phii;
592 dxz +=
w * etai * phii;
607 lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
610 lambda[0] = TMath::Sqrt(lambda[0]);
615 lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
618 lambda[1] = TMath::Sqrt(lambda[1]);
627 clusterAnalysis.
setM02(lambda[0] * lambda[0]);
628 clusterAnalysis.
setM20(lambda[1] * lambda[1]);
634template <
class InputType>
643 for (
auto iInput : inputsIndices) {
644 if (iInput >= mInputsContainer.size()) {
647 cellAmp += mInputsContainer[iInput].getEnergy();
648 if (iSupMod0 == -1) {
649 iSupMod0 = mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower());
650 }
else if (iSupMod0 != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
653 if (mInputsContainer[iInput].getEnergy() > energy) {
654 energy = mInputsContainer[iInput].getEnergy();
659 return std::make_tuple(mid, energy, cellAmp, shared);
665template <
class InputType>
668 if (ecell < mExoticCellMinAmplitude) {
673 if (!getLookUpInit()) {
677 float eCross = getECross(towerId, ecell, exoticTime);
678 fCross = 1.f - eCross / ecell;
680 if (fCross > mExoticCellFraction) {
681 LOG(
debug) <<
"EXOTIC CELL id " << towerId <<
", eCell " << ecell <<
", eCross " << eCross <<
", 1-eCross/eCell " << 1 - eCross / ecell;
691template <
class InputType>
694 auto [iSM, iMod, iIphi, iIeta] = mGeomPtr->GetCellIndex(towerId);
695 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta);
704 towerId1 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta);
711 towerId2 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta);
724 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM + 1, iphi, 0);
729 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
733 }
else if (ieta == 0 && iSM % 2) {
735 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
747 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
754 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
761 LOG(
debug) <<
"iSM " << iSM <<
", towerId " << towerId <<
", a " << towerId1 <<
", b " << towerId2 <<
", c " << towerId3 <<
", e " << towerId3;
763 short index1 = (towerId1 > -1) ? mLoolUpTowerToIndex.at(towerId1) : -1;
764 short index2 = (towerId2 > -1) ? mLoolUpTowerToIndex.at(towerId2) : -1;
765 short index3 = (towerId3 > -1) ? mLoolUpTowerToIndex.at(towerId3) : -1;
766 short index4 = (towerId4 > -1) ? mLoolUpTowerToIndex.at(towerId4) : -1;
768 std::array<std::pair<float, float>, 4> cellData = {
769 {{(index1 > -1) ? mInputsContainer[index1].getEnergy() : 0., (index1 > -1) ? mInputsContainer[index1].getTimeStamp() : 0.},
770 {(index2 > -1) ? mInputsContainer[index2].getEnergy() : 0., (index2 > -1) ? mInputsContainer[index2].getTimeStamp() : 0.},
771 {(index3 > -1) ? mInputsContainer[index3].getEnergy() : 0., (index3 > -1) ? mInputsContainer[index3].getTimeStamp() : 0.},
772 {(index4 > -1) ? mInputsContainer[index4].getEnergy() : 0., (index4 > -1) ? mInputsContainer[index4].getTimeStamp() : 0.}}};
774 for (
auto& cell : cellData) {
775 if (std::abs(exoticTime - cell.second) > mExoticCellDiffTime) {
780 float w1 = 1, w2 = 1, w3 = 1, w4 = 1;
781 if (mUseWeightExotic) {
782 w1 = GetCellWeight(cellData[0].
first, energy);
783 w2 = GetCellWeight(cellData[1].
first, energy);
784 w3 = GetCellWeight(cellData[2].
first, energy);
785 w4 = GetCellWeight(cellData[3].
first, energy);
788 if (cellData[0].
first < mExoticCellInCrossMinAmplitude || w1 <= 0) {
789 cellData[0].first = 0;
791 if (cellData[1].
first < mExoticCellInCrossMinAmplitude || w2 <= 0) {
792 cellData[1].first = 0;
794 if (cellData[2].
first < mExoticCellInCrossMinAmplitude || w3 <= 0) {
795 cellData[2].first = 0;
797 if (cellData[3].
first < mExoticCellInCrossMinAmplitude || w4 <= 0) {
798 cellData[3].first = 0;
801 return cellData[0].first + cellData[1].first + cellData[2].first + cellData[3].first;
807template <
class InputType>
810 if (eCell > 0 && eCluster > 0) {
811 if (mLogWeight > 0) {
812 return std::max(0.f, mLogWeight + std::log(eCell / eCluster));
814 return std::log(eCluster / eCell);
824template <
class InputType>
828 for (
auto iInput : inputsIndices) {
829 if (mInputsContainer[iInput].getEnergy() > H * clusterAnalysis.
E()) {
840template <
class InputType>
844 unsigned short maxAt = 0;
845 for (
auto iInput : inputsIndices) {
846 if (mInputsContainer[iInput].getEnergy() > maxE) {
847 maxE = mInputsContainer[iInput].getEnergy();
852 clusterAnalysis.
setClusterTime(mInputsContainer[maxAt].getTimeStamp());
859template <
class InputType>
862 const double ca = 4.82;
865 const double x0 = 1.31;
868 tmax = TMath::Log(e) + ca;
883template <
class InputType>
886 return (2. * TMath::ATan(TMath::Exp(-arg)));
892template <
class InputType>
895 return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
898template <
class InputType>
901 mClusterID(clusterIndex),
904 mCurrentCluster = mClusterFactory.
buildCluster(mClusterID);
907template <
class InputType>
910 return &mClusterFactory == &rhs.mClusterFactory && mClusterID == rhs.mClusterID && mForward == rhs.mForward;
913template <
class InputType>
921 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
925template <
class InputType>
933template <
class InputType>
941 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
945template <
class InputType>
Cluster class for kinematic cluster parametersported from AliVCluster in AliRoot.
void setNExMax(unsigned char nExMax)
void setGlobalPosition(math_utils::Point3D< float > x)
Set the cluster global position.
void setFCross(float fCross)
void setCoreEnergy(float energy)
math_utils::Point3D< float > getLocalPosition() const
void setCellsIndices(const std::vector< unsigned short > &array)
Set the array of cell indices.
void setDispersion(float disp)
void setIndMaxInput(const int ind)
void setClusterTime(float time)
void setLocalPosition(math_utils::Point3D< float > x)
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.
std::tuple< int, float, float, bool > getMaximalEnergyIndex(gsl::span< const int > inputsIndices) const
Finds the maximum energy in the cluster and computes the Summed amplitude of digits/cells.
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 evalNExMax(gsl::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Calculate the number of local maxima in the cluster.
float getECross(short absID, float energy, float const exoticTime) const
Calculate the energy in the cross around the energy of a given cell.
void evalGlobalPosition(gsl::span< const int > inputsIndices, AnalysisCluster &cluster) const
Calculates the center of gravity in the global ALICE coordinates.
void evalLocalPosition(gsl::span< const int > inputsIndices, AnalysisCluster &cluster) const
Calculates the center of gravity in the local EMCAL-module coordinates.
Double_t tMaxInCm(const Double_t e=0.0, const int key=0) const
static void getDeffW0(const Double_t esum, Double_t &deff, Double_t &w0)
void evalTime(gsl::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Time is set to the time of the digit with the maximum energy.
int getMultiplicityAtLevel(float level, gsl::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
Calculates the multiplicity of digits/cells with energy larger than level*energy.
ClusterFactory()=default
Dummy constructor.
void evalLocalPositionFit(Double_t deff, Double_t w0, Double_t phiSlope, gsl::span< const int > inputsIndices, AnalysisCluster &cluster) const
evaluates local position of clusters in SM
void evalElipsAxis(gsl::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
void evalCoreEnergy(gsl::span< const int > inputsIndices, AnalysisCluster &clusterAnalysis) const
void evalDispersion(gsl::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.
AnalysisCluster buildCluster(int index, o2::emcal::ClusterLabel *clusterLabel=nullptr) const
evaluates cluster parameters: position, shower shape, primaries ...
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