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();
77 clusterAnalysis.
setIsExotic(isExoticCell(towerId, inputEnergyMax, exoticTime));
84 clusterAnalysis.
setE(cellAmp);
86 mSuperModuleNumber = mGeomPtr->GetSuperModuleNumber(towerId);
88 clusterAnalysis.
setNCells(inputsIndices.size());
90 std::vector<unsigned short> cellsIdices;
92 bool addClusterLabels = ((clusterLabel !=
nullptr) && (mCellLabelContainer.size() > 0));
93 for (
auto cellIndex : inputsIndices) {
94 cellsIdices.push_back(cellIndex);
95 if (addClusterLabels) {
96 for (
size_t iLabel = 0; iLabel < mCellLabelContainer[cellIndex].GetLabelSize(); iLabel++) {
97 if (mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) <= 0.f) {
100 clusterLabel->
addValue(mCellLabelContainer[cellIndex].GetLabel(iLabel),
101 mCellLabelContainer[cellIndex].GetAmplitudeFraction(iLabel) * mInputsContainer[cellIndex].getEnergy());
105 if (addClusterLabels) {
113 evalGlobalPosition(inputsIndices, clusterAnalysis);
114 evalLocalPosition(inputsIndices, clusterAnalysis);
117 evalElipsAxis(inputsIndices, clusterAnalysis);
118 evalDispersion(inputsIndices, clusterAnalysis);
120 evalCoreEnergy(inputsIndices, clusterAnalysis);
121 evalTime(inputsIndices, clusterAnalysis);
133 return clusterAnalysis;
140template <
class InputType>
143 double d = 0., wtot = 0.;
147 double etaMean = 0.0, phiMean = 0.0;
150 for (
auto iInput : inputsIndices) {
152 if (clusterAnalysis.
E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
153 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
154 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
158 if (mSharedCluster && nSupMod % 2) {
162 double etai = (double)ieta;
163 double phii = (double)iphi;
164 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
178 LOG(error) << Form(
"Wrong weight %f\n", wtot);
182 for (
auto iInput : inputsIndices) {
184 if (clusterAnalysis.
E() > 0 && mInputsContainer[iInput].getEnergy() > 0) {
185 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
186 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
190 if (mSharedCluster && nSupMod % 2) {
194 double etai = (double)ieta;
195 double phii = (double)iphi;
196 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
200 d +=
w * ((etai - etaMean) * (etai - etaMean) + (phii - phiMean) * (phii - phiMean));
205 if (wtot > 0 && nstat > 1) {
217template <
class InputType>
223 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
225 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, xyzi[3], wtot = 0.,
w = 0.;
227 for (
auto iInput : inputsIndices) {
230 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
237 if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
241 if (mLogWeight > 0.0) {
242 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
244 w = mInputsContainer[iInput].getEnergy();
251 for (
int i = 0;
i < 3;
i++) {
252 clXYZ[
i] += (
w * xyzi[
i]);
253 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
262 for (
int i = 0;
i < 3;
i++) {
266 clRmsXYZ[
i] /= (wtot * wtot);
267 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
269 if (clRmsXYZ[
i] > 0.0) {
270 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
279 for (
int i = 0;
i < 3;
i++) {
280 clXYZ[
i] = clRmsXYZ[
i] = -1.;
290template <
class InputType>
294 int i = 0, nstat = 0;
296 double dist = tMaxInCm(
double(clusterAnalysis.
E()));
298 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, lxyzi[3], xyzi[3], wtot = 0.,
w = 0.;
300 for (
auto iInput : inputsIndices) {
304 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), dist).GetCoordinates(lxyzi[0], lxyzi[1], lxyzi[2]);
311 mGeomPtr->GetGlobal(lxyzi, xyzi, mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower()));
313 if (mLogWeight > 0.0) {
314 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
316 w = mInputsContainer[iInput].getEnergy();
323 for (
i = 0;
i < 3;
i++) {
324 clXYZ[
i] += (
w * xyzi[
i]);
325 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
334 for (
i = 0;
i < 3;
i++) {
338 clRmsXYZ[
i] /= (wtot * wtot);
339 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
341 if (clRmsXYZ[
i] > 0.0) {
342 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
351 for (
i = 0;
i < 3;
i++) {
352 clXYZ[
i] = clRmsXYZ[
i] = -1.;
362template <
class InputType>
364 double phiSlope, gsl::span<const int> inputsIndices,
AnalysisCluster& clusterAnalysis)
const
366 int i = 0, nstat = 0;
367 double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, xyzi[3], wtot = 0.,
w = 0.;
369 for (
auto iInput : inputsIndices) {
372 mGeomPtr->RelPosCellInSModule(mInputsContainer[iInput].getTower(), deff).GetCoordinates(xyzi[0], xyzi[1], xyzi[2]);
378 if (mLogWeight > 0.0) {
379 w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
381 w = mInputsContainer[iInput].getEnergy();
388 for (
i = 0;
i < 3;
i++) {
389 clXYZ[
i] += (
w * xyzi[
i]);
390 clRmsXYZ[
i] += (
w * xyzi[
i] * xyzi[
i]);
399 for (
i = 0;
i < 3;
i++) {
403 clRmsXYZ[
i] /= (wtot * wtot);
404 clRmsXYZ[
i] = clRmsXYZ[
i] - clXYZ[
i] * clXYZ[
i];
406 if (clRmsXYZ[
i] > 0.0) {
407 clRmsXYZ[
i] = TMath::Sqrt(clRmsXYZ[
i]);
416 for (
i = 0;
i < 3;
i++) {
417 clXYZ[
i] = clRmsXYZ[
i] = -1.;
423 if (phiSlope != 0.0 && mLogWeight > 0.0 && wtot) {
426 double ycorr = clXYZ[1] * (1. + phiSlope);
440template <
class InputType>
444 const double kdp0 = 9.25147, kdp1 = 1.16700;
445 const double kwp0 = 4.83713, kwp1 = -2.77970e-01, kwp2 = 4.41116;
448 e = esum < 0.5 ? 0.5 : esum;
449 e = e > 100. ? 100. : e;
451 deff = kdp0 + kdp1 * TMath::Log(e);
452 w0 = kwp0 / (1. + TMath::Exp(kwp1 * (e + kwp2)));
463template <
class InputType>
467 float coreEnergy = 0.;
470 evalLocalPosition(inputsIndices, clusterAnalysis);
475 for (
auto iInput : inputsIndices) {
477 auto [eta, phi] = mGeomPtr->EtaPhiFromIndex(mInputsContainer[iInput].getTower());
478 phi = phi * TMath::DegToRad();
480 double distance = TMath::Sqrt((eta - etaPoint) * (eta - etaPoint) + (phi - phiPoint) * (phi - phiPoint));
483 coreEnergy += mInputsContainer[iInput].getEnergy();
493template <
class InputType>
503 std::array<float, 2> lambda;
505 for (
auto iInput : inputsIndices) {
507 auto [nSupMod, nModule, nIphi, nIeta] = mGeomPtr->GetCellIndex(mInputsContainer[iInput].getTower());
508 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta);
512 if (mSharedCluster && nSupMod % 2) {
516 double etai = (double)ieta;
517 double phii = (double)iphi;
519 double w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.
E()));
524 dxx +=
w * etai * etai;
526 dzz +=
w * phii * phii;
529 dxz +=
w * etai * phii;
544 lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
547 lambda[0] = TMath::Sqrt(lambda[0]);
552 lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz);
555 lambda[1] = TMath::Sqrt(lambda[1]);
564 clusterAnalysis.
setM02(lambda[0] * lambda[0]);
565 clusterAnalysis.
setM20(lambda[1] * lambda[1]);
571template <
class InputType>
580 for (
auto iInput : inputsIndices) {
581 if (iInput >= mInputsContainer.size()) {
584 cellAmp += mInputsContainer[iInput].getEnergy();
585 if (iSupMod0 == -1) {
586 iSupMod0 = mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower());
587 }
else if (iSupMod0 != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) {
590 if (mInputsContainer[iInput].getEnergy() > energy) {
591 energy = mInputsContainer[iInput].getEnergy();
596 return std::make_tuple(mid, energy, cellAmp, shared);
602template <
class InputType>
605 if (ecell < mExoticCellMinAmplitude) {
610 if (!getLookUpInit()) {
614 float eCross = getECross(towerId, ecell, exoticTime);
616 if (1 - eCross / ecell > mExoticCellFraction) {
617 LOG(
debug) <<
"EXOTIC CELL id " << towerId <<
", eCell " << ecell <<
", eCross " << eCross <<
", 1-eCross/eCell " << 1 - eCross / ecell;
627template <
class InputType>
630 auto [iSM, iMod, iIphi, iIeta] = mGeomPtr->GetCellIndex(towerId);
631 auto [iphi, ieta] = mGeomPtr->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta);
640 towerId1 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta);
647 towerId2 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta);
660 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM + 1, iphi, 0);
665 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
669 }
else if (ieta == 0 && iSM % 2) {
671 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
683 towerId3 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + 1);
690 towerId4 = mGeomPtr->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta - 1);
697 LOG(
debug) <<
"iSM " << iSM <<
", towerId " << towerId <<
", a " << towerId1 <<
", b " << towerId2 <<
", c " << towerId3 <<
", e " << towerId3;
699 short index1 = (towerId1 > -1) ? mLoolUpTowerToIndex.at(towerId1) : -1;
700 short index2 = (towerId2 > -1) ? mLoolUpTowerToIndex.at(towerId2) : -1;
701 short index3 = (towerId3 > -1) ? mLoolUpTowerToIndex.at(towerId3) : -1;
702 short index4 = (towerId4 > -1) ? mLoolUpTowerToIndex.at(towerId4) : -1;
704 std::array<std::pair<float, float>, 4> cellData = {
705 {{(index1 > -1) ? mInputsContainer[index1].getEnergy() : 0., (index1 > -1) ? mInputsContainer[index1].getTimeStamp() : 0.},
706 {(index2 > -1) ? mInputsContainer[index2].getEnergy() : 0., (index2 > -1) ? mInputsContainer[index2].getTimeStamp() : 0.},
707 {(index3 > -1) ? mInputsContainer[index3].getEnergy() : 0., (index3 > -1) ? mInputsContainer[index3].getTimeStamp() : 0.},
708 {(index4 > -1) ? mInputsContainer[index4].getEnergy() : 0., (index4 > -1) ? mInputsContainer[index4].getTimeStamp() : 0.}}};
710 for (
auto& cell : cellData) {
711 if (std::abs(exoticTime - cell.second) > mExoticCellDiffTime) {
716 float w1 = 1, w2 = 1, w3 = 1, w4 = 1;
717 if (mUseWeightExotic) {
718 w1 = GetCellWeight(cellData[0].
first, energy);
719 w2 = GetCellWeight(cellData[1].
first, energy);
720 w3 = GetCellWeight(cellData[2].
first, energy);
721 w4 = GetCellWeight(cellData[3].
first, energy);
724 if (cellData[0].
first < mExoticCellInCrossMinAmplitude || w1 <= 0) {
725 cellData[0].first = 0;
727 if (cellData[1].
first < mExoticCellInCrossMinAmplitude || w2 <= 0) {
728 cellData[1].first = 0;
730 if (cellData[2].
first < mExoticCellInCrossMinAmplitude || w3 <= 0) {
731 cellData[2].first = 0;
733 if (cellData[3].
first < mExoticCellInCrossMinAmplitude || w4 <= 0) {
734 cellData[3].first = 0;
737 return cellData[0].first + cellData[1].first + cellData[2].first + cellData[3].first;
743template <
class InputType>
746 if (eCell > 0 && eCluster > 0) {
747 if (mLogWeight > 0) {
748 return std::max(0.f, mLogWeight + std::log(eCell / eCluster));
750 return std::log(eCluster / eCell);
760template <
class InputType>
764 for (
auto iInput : inputsIndices) {
765 if (mInputsContainer[iInput].getEnergy() > H * clusterAnalysis.
E()) {
776template <
class InputType>
780 unsigned short maxAt = 0;
781 for (
auto iInput : inputsIndices) {
782 if (mInputsContainer[iInput].getEnergy() > maxE) {
783 maxE = mInputsContainer[iInput].getEnergy();
788 clusterAnalysis.
setClusterTime(mInputsContainer[maxAt].getTimeStamp());
795template <
class InputType>
798 const double ca = 4.82;
801 const double x0 = 1.31;
804 tmax = TMath::Log(e) + ca;
819template <
class InputType>
822 return (2. * TMath::ATan(TMath::Exp(-arg)));
828template <
class InputType>
831 return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
834template <
class InputType>
837 mClusterID(clusterIndex),
840 mCurrentCluster = mClusterFactory.
buildCluster(mClusterID);
843template <
class InputType>
846 return &mClusterFactory == &rhs.mClusterFactory && mClusterID == rhs.mClusterID && mForward == rhs.mForward;
849template <
class InputType>
857 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
861template <
class InputType>
869template <
class InputType>
877 mCurrentCluster = mClusterFactory.buildCluster(mClusterID);
881template <
class InputType>
Cluster class for kinematic cluster parametersported from AliVCluster in AliRoot.
void setGlobalPosition(math_utils::Point3D< float > x)
Set the cluster global position.
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)
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.
bool isExoticCell(short towerId, float ecell, float const exoticTime) const
Look to cell neighbourhood and reject if it seems exotic.
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)
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"