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++) {
537 std::abs(columns[
i] - columns[
j]) <= 1) {
540 if (energies[
j] > energies[
i]) {
557template <
class InputType>
567 std::array<float, 2> lambda;
569 for (
auto iInput : inputsIndices) {
571 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
572 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
576 if (mSharedCluster && nSupMod % 2) {
580 double etai = (double)ieta;
581 double phii = (double)iphi;
583 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
588 dxx +=
w * etai * etai;
590 dzz +=
w * phii * phii;
593 dxz +=
w * etai * phii;
608 lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
611 lambda[0] = TMath::Sqrt(lambda[0]);
616 lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
619 lambda[1] = TMath::Sqrt(lambda[1]);
628 clusterAnalysis.
setM02(lambda[0] * lambda[0]);
629 clusterAnalysis.
setM20(lambda[1] * lambda[1]);
635template <
class InputType>
644 for (
auto iInput : inputsIndices) {
645 if (iInput >= mInputsContainer.size()) {
648 cellAmp += mInputsContainer[iInput].getEnergy();
649 if (iSupMod0 == -1) {
650 iSupMod0 = mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower());
651 }
else if (iSupMod0 != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
654 if (mInputsContainer[iInput].getEnergy() > energy) {
655 energy = mInputsContainer[iInput].getEnergy();
660 return std::make_tuple(mid, energy, cellAmp, shared);
666template <
class InputType>
669 if (ecell < mExoticCellMinAmplitude) {
674 if (!getLookUpInit()) {
678 float eCross = getECross(towerId, ecell, exoticTime);
679 fCross = 1.f - eCross / ecell;
681 if (fCross > mExoticCellFraction) {
682 LOG(
debug) <<
"EXOTIC CELL id " << towerId <<
", eCell " << ecell <<
", eCross " << eCross <<
", 1-eCross/eCell " << 1 - eCross / ecell;
692template <
class InputType>
695 auto [iSM, iMod, iIphi, iIeta] = mGeomPtr->GetCellIndex(towerId);
696 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta);
705 towerId1 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta);
712 towerId2 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta);
725 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM + 1, iphi, 0);
730 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
734 }
else if (ieta == 0 && iSM % 2) {
736 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
748 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
755 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
762 LOG(
debug) <<
"iSM " << iSM <<
", towerId " << towerId <<
", a " << towerId1 <<
", b " << towerId2 <<
", c " << towerId3 <<
", e " << towerId3;
764 short index1 = (towerId1 > -1) ? mLoolUpTowerToIndex.at(towerId1) : -1;
765 short index2 = (towerId2 > -1) ? mLoolUpTowerToIndex.at(towerId2) : -1;
766 short index3 = (towerId3 > -1) ? mLoolUpTowerToIndex.at(towerId3) : -1;
767 short index4 = (towerId4 > -1) ? mLoolUpTowerToIndex.at(towerId4) : -1;
769 std::array<std::pair<float, float>, 4> cellData = {
770 {{(index1 > -1) ? mInputsContainer[index1].getEnergy() : 0., (index1 > -1) ? mInputsContainer[index1].getTimeStamp() : 0.},
771 {(index2 > -1) ? mInputsContainer[index2].getEnergy() : 0., (index2 > -1) ? mInputsContainer[index2].getTimeStamp() : 0.},
772 {(index3 > -1) ? mInputsContainer[index3].getEnergy() : 0., (index3 > -1) ? mInputsContainer[index3].getTimeStamp() : 0.},
773 {(index4 > -1) ? mInputsContainer[index4].getEnergy() : 0., (index4 > -1) ? mInputsContainer[index4].getTimeStamp() : 0.}}};
775 for (
auto& cell : cellData) {
776 if (std::abs(exoticTime - cell.second) > mExoticCellDiffTime) {
781 float w1 = 1, w2 = 1, w3 = 1, w4 = 1;
782 if (mUseWeightExotic) {
783 w1 = GetCellWeight(cellData[0].
first, energy);
784 w2 = GetCellWeight(cellData[1].
first, energy);
785 w3 = GetCellWeight(cellData[2].
first, energy);
786 w4 = GetCellWeight(cellData[3].
first, energy);
789 if (cellData[0].
first < mExoticCellInCrossMinAmplitude || w1 <= 0) {
790 cellData[0].first = 0;
792 if (cellData[1].
first < mExoticCellInCrossMinAmplitude || w2 <= 0) {
793 cellData[1].first = 0;
795 if (cellData[2].
first < mExoticCellInCrossMinAmplitude || w3 <= 0) {
796 cellData[2].first = 0;
798 if (cellData[3].
first < mExoticCellInCrossMinAmplitude || w4 <= 0) {
799 cellData[3].first = 0;
802 return cellData[0].first + cellData[1].first + cellData[2].first + cellData[3].first;
808template <
class InputType>
811 if (eCell > 0 && eCluster > 0) {
812 if (mLogWeight > 0) {
813 return std::max(0.f, mLogWeight + std::log(eCell / eCluster));
815 return std::log(eCluster / eCell);
825template <
class InputType>
829 for (
auto iInput : inputsIndices) {
830 if (mInputsContainer[iInput].getEnergy() > H * clusterAnalysis.
E()) {
841template <
class InputType>
845 unsigned short maxAt = 0;
846 for (
auto iInput : inputsIndices) {
847 if (mInputsContainer[iInput].getEnergy() > maxE) {
848 maxE = mInputsContainer[iInput].getEnergy();
853 clusterAnalysis.
setClusterTime(mInputsContainer[maxAt].getTimeStamp());
860template <
class InputType>
863 const double ca = 4.82;
866 const double x0 = 1.31;
869 tmax = TMath::Log(e) + ca;
884template <
class InputType>
887 return (2. * TMath::ATan(TMath::Exp(-arg)));
893template <
class InputType>
896 return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
899template <
class InputType>
902 mClusterID(clusterIndex),
905 mCurrentCluster = mClusterFactory.
buildCluster(mClusterID);
908template <
class InputType>
911 return &mClusterFactory == &rhs.mClusterFactory && mClusterID == rhs.mClusterID && mForward == rhs.mForward;
914template <
class InputType>
922 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
926template <
class InputType>
934template <
class InputType>
942 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
946template <
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