10#include <analysis/variables/ECLVariables.h>
13#include <framework/logging/Logger.h>
14#include <framework/database/DBObjPtr.h>
15#include <framework/core/Environment.h>
18#include <analysis/dataobjects/Particle.h>
19#include <analysis/dataobjects/ParticleList.h>
20#include <analysis/dataobjects/ECLEnergyCloseToTrack.h>
21#include <analysis/utility/ReferenceFrame.h>
22#include <analysis/ClusterUtility/ClusterUtils.h>
23#include <analysis/VariableManager/Utility.h>
24#include <analysis/dbobjects/ECLTimingNormalization.h>
27#include <mdst/dataobjects/KlId.h>
28#include <mdst/dataobjects/ECLCluster.h>
29#include <mdst/dataobjects/Track.h>
30#include <mdst/dataobjects/EventLevelClusteringInfo.h>
32#include <Math/Vector4D.h>
45 double distanceToMcKl(
const Particle* particle)
47 if (particle->hasExtraInfo(
"mcdistanceKL")) {
48 return particle->getExtraInfo(
"mcdistanceKL");
50 B2WARNING(
"The extraInfo mcdistanceKL is not registered! \n"
51 "This variable is only available for ECL based lists, and you have to run the function getNeutralHadronGeomMatches to use it");
56 double distanceToMcNeutron(
const Particle* particle)
58 if (particle->hasExtraInfo(
"mcdistanceNeutron")) {
59 return particle->getExtraInfo(
"mcdistanceNeutron");
61 B2WARNING(
"The extraInfo mcdistanceNeutron is not registered! \n"
62 "This variable is only available for ECL based lists, and you have to run the function getNeutralHadronGeomMatches to use it");
67 int mdstIndexMcKl(
const Particle* particle)
69 if (particle->hasExtraInfo(
"mdstIndexTruthKL")) {
70 return int(particle->getExtraInfo(
"mdstIndexTruthKL") + 0.1);
72 B2WARNING(
"The extraInfo mdstIndexTruthKL is not registered! \n"
73 "This variable is only available for ECL based lists, and you have to run the function getNeutralHadronGeomMatches to use it");
78 int mdstIndexMcNeutron(
const Particle* particle)
80 if (particle->hasExtraInfo(
"mdstIndexTruthNeutron")) {
81 return int(particle->getExtraInfo(
"mdstIndexTruthNeutron") + 0.1);
83 B2WARNING(
"The extraInfo mdstIndexTruthNeutron is not registered! \n"
84 "This variable is only available for ECL based lists, and you have to run the function getNeutralHadronGeomMatches to use it");
90 double beamBackgroundSuppression(
const Particle* particle)
92 if (particle->hasExtraInfo(
"beamBackgroundSuppression")) {
93 return particle->getExtraInfo(
"beamBackgroundSuppression");
95 B2WARNING(
"The extraInfo beamBackgroundSuppression is not registered! \n"
96 "This variable is only available for photons, and you either have to use the standard particle lists (stdPhotons or stdPi0s) or run getBeamBackgroundProbability on a photon list.");
101 double fakePhotonSuppression(
const Particle* particle)
103 if (particle->hasExtraInfo(
"fakePhotonSuppression")) {
104 return particle->getExtraInfo(
"fakePhotonSuppression");
106 B2WARNING(
"The extraInfo fakePhotonSuppression is not registered! \n"
107 "This variable is only available for photons, and you either have to use the standard particle lists (stdPhotons or stdPi0s) or run getFakePhotonProbability on a photon list.");
112 double hadronicSplitOffSuppression(
const Particle* particle)
114 B2WARNING(
"This variable has been deprecated since light-2302-genetta and is no longer maintained with up to date weights. Please use the variable fakePhotonSuppression instead.");
115 return fakePhotonSuppression(particle);
118 double eclClusterKlId(
const Particle* particle)
120 const ECLCluster* cluster = particle->getECLCluster();
124 const KlId* klid = cluster->getRelatedTo<KlId>();
128 return klid->getKlId();
131 double eclPulseShapeDiscriminationMVA(
const Particle* particle)
133 const ECLCluster* cluster = particle->getECLCluster();
135 if (eclClusterHasPulseShapeDiscrimination(particle)) {
136 return cluster->getPulseShapeDiscriminationMVA();
144 double eclClusterNumberOfHadronDigits(
const Particle* particle)
147 const ECLCluster* cluster = particle->getECLCluster();
149 if (eclClusterHasPulseShapeDiscrimination(particle)) {
150 return cluster->getNumberOfHadronDigits();
157 double eclClusterDetectionRegion(
const Particle* particle)
160 const ECLCluster* cluster = particle->getECLCluster();
162 return cluster->getDetectorRegion();
167 double eclClusterIsolation(
const Particle* particle)
170 const ECLCluster* cluster = particle->getECLCluster();
172 auto minDist = cluster->getMinTrkDistance();
179 double eclClusterIsolationID(
const Particle* particle)
182 const ECLCluster* cluster = particle->getECLCluster();
184 return cluster->getMinTrkDistanceID();
191 if (arguments.size() > 2 or arguments.size() == 0)
192 B2FATAL(
"Wrong number of arguments (2 required) for meta variable minC2TDistVar");
193 std::string listName =
"pi-:all";
194 std::string variableName = arguments[0];
195 if (arguments.size() == 2)
196 listName = arguments[1];
199 auto func = [listName, variableName](
const Particle * particle) ->
double {
200 StoreObjPtr<ParticleList> particleList(listName);
201 if (!(particleList.isValid()))
203 B2FATAL(
"Invalid Listname " << listName <<
" given to minC2TDistVar!");
206 const ECLCluster* cluster = particle->getECLCluster();
209 auto trackID = cluster->getMinTrkDistanceID();
212 for (
unsigned int i = 0; i < particleList->getListSize(); i++)
214 const Particle* listParticle = particleList->getParticle(i);
215 if (listParticle and listParticle->getTrack() and listParticle->getTrack()->getArrayIndex() == trackID) {
216 result = std::get<double>(var->function(listParticle));
225 double eclClusterConnectedRegionID(
const Particle* particle)
228 const ECLCluster* cluster = particle->getECLCluster();
230 return cluster->getConnectedRegionId();
235 double eclClusterDeltaL(
const Particle* particle)
238 const ECLCluster* cluster = particle->getECLCluster();
240 return cluster->getDeltaL();
245 double eclClusterErrorE(
const Particle* particle)
248 const ECLCluster* cluster = particle->getECLCluster();
251 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
252 return sqrt(fabs(EPhiThetaCov[0][0]));
257 double eclClusterUncorrectedE(
const Particle* particle)
260 const ECLCluster* cluster = particle->getECLCluster();
262 return cluster->getEnergyRaw();
267 double eclClusterE(
const Particle* particle)
271 const ECLCluster* cluster = particle->getECLCluster();
274 ROOT::Math::PxPyPzEVector p4Cluster = clutls.GetCluster4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
276 return frame.getMomentum(p4Cluster).E();
281 double eclClusterHighestE(
const Particle* particle)
284 const ECLCluster* cluster = particle->getECLCluster();
286 return cluster->getEnergyHighestCrystal();
291 double eclClusterCellId(
const Particle* particle)
294 const ECLCluster* cluster = particle->getECLCluster();
296 return cluster->getMaxECellId();
302 const std::array<int, 69> lastCellIDperThetaID{48, 96, 160, 224, 288, 384, 480, 576, 672, 768, 864,
303 1008, 1152, 1296, 1440, 1584, 1728, 1872, 2016, 2160, 2304, 2448,
304 2592, 2736, 2880, 3024, 3168, 3312, 3456, 3600, 3744, 3888, 4032,
305 4176, 4320, 4464, 4608, 4752, 4896, 5040, 5184, 5328, 5472, 5616,
306 5760, 5904, 6048, 6192, 6336, 6480, 6624, 6768, 6912, 7056, 7200,
307 7344, 7488, 7632, 7776, 7920, 8064, 8160, 8256, 8352, 8448, 8544,
310 double eclClusterThetaId(
const Particle* particle)
313 const ECLCluster* cluster = particle->getECLCluster();
315 int cellID = cluster->getMaxECellId();
316 return std::distance(lastCellIDperThetaID.begin(), std::lower_bound(lastCellIDperThetaID.begin(), lastCellIDperThetaID.end(),
322 double eclClusterPhiId(
const Particle* particle)
325 const ECLCluster* cluster = particle->getECLCluster();
327 int cellID = cluster->getMaxECellId();
331 int closestinlist = lastCellIDperThetaID[std::distance(lastCellIDperThetaID.begin(), std::lower_bound(lastCellIDperThetaID.begin(),
332 lastCellIDperThetaID.end(), cellID)) - 1];
333 return cellID - closestinlist - 1;
339 double eclClusterTiming(
const Particle* particle)
342 const ECLCluster* cluster = particle->getECLCluster();
344 return cluster->getTime();
349 double eclClusterHasFailedTiming(
const Particle* particle)
351 const ECLCluster* cluster = particle->getECLCluster();
353 return cluster->hasFailedFitTime();
358 double eclClusterErrorTiming(
const Particle* particle)
361 const ECLCluster* cluster = particle->getECLCluster();
363 return cluster->getDeltaTime99();
368 double eclClusterHasFailedErrorTiming(
const Particle* particle)
370 const ECLCluster* cluster = particle->getECLCluster();
372 return cluster->hasFailedTimeResolution();
377 double eclClusterTheta(
const Particle* particle)
381 const ECLCluster* cluster = particle->getECLCluster();
384 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
386 return frame.getMomentum(p4Cluster).Theta();
391 double eclClusterErrorTheta(
const Particle* particle)
394 const ECLCluster* cluster = particle->getECLCluster();
397 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
398 return sqrt(fabs(EPhiThetaCov[2][2]));
403 double eclClusterErrorPhi(
const Particle* particle)
406 const ECLCluster* cluster = particle->getECLCluster();
409 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
410 return sqrt(fabs(EPhiThetaCov[1][1]));
415 double eclClusterPhi(
const Particle* particle)
419 const ECLCluster* cluster = particle->getECLCluster();
422 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
424 return frame.getMomentum(p4Cluster).Phi();
429 double eclClusterR(
const Particle* particle)
432 const ECLCluster* cluster = particle->getECLCluster();
434 return cluster->getR();
439 double eclClusterE1E9(
const Particle* particle)
442 const ECLCluster* cluster = particle->getECLCluster();
444 return cluster->getE1oE9();
449 double eclClusterE9E21(
const Particle* particle)
452 const ECLCluster* cluster = particle->getECLCluster();
454 return cluster->getE9oE21();
459 double eclClusterAbsZernikeMoment40(
const Particle* particle)
462 const ECLCluster* cluster = particle->getECLCluster();
464 return cluster->getAbsZernike40();
469 double eclClusterAbsZernikeMoment51(
const Particle* particle)
472 const ECLCluster* cluster = particle->getECLCluster();
474 return cluster->getAbsZernike51();
479 double eclClusterZernikeMVA(
const Particle* particle)
482 const ECLCluster* cluster = particle->getECLCluster();
484 return cluster->getZernikeMVA();
489 double eclClusterSecondMoment(
const Particle* particle)
492 const ECLCluster* cluster = particle->getECLCluster();
494 return cluster->getSecondMoment();
499 double eclClusterLAT(
const Particle* particle)
502 const ECLCluster* cluster = particle->getECLCluster();
504 return cluster->getLAT();
509 double eclClusterNHits(
const Particle* particle)
512 const ECLCluster* cluster = particle->getECLCluster();
514 return cluster->getNumberOfCrystals();
519 double eclClusterTrackMatched(
const Particle* particle)
522 const ECLCluster* cluster = particle->getECLCluster();
524 const Track* track = cluster->getRelatedFrom<Track>();
534 double nECLClusterTrackMatches(
const Particle* particle)
537 const ECLCluster* cluster = particle->getECLCluster();
542 size_t out = cluster->getRelationsFrom<Track>().size();
546 double eclClusterId(
const Particle* particle)
548 const ECLCluster* cluster = particle->getECLCluster();
550 return cluster->getClusterId();
555 double eclClusterHasNPhotonsHypothesis(
const Particle* particle)
557 const ECLCluster* cluster = particle->getECLCluster();
564 double eclClusterHasNeutralHadronHypothesis(
const Particle* particle)
566 const ECLCluster* cluster = particle->getECLCluster();
573 double eclClusterHasPulseShapeDiscrimination(
const Particle* particle)
575 const ECLCluster* cluster = particle->getECLCluster();
577 return cluster->hasPulseShapeDiscrimination();
582 double eclExtTheta(
const Particle* particle)
585 const Track* track = particle->getTrack();
588 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
591 return eclinfo->getExtTheta();
593 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
601 double eclExtPhi(
const Particle* particle)
604 const Track* track = particle->getTrack();
607 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
610 return eclinfo->getExtPhi();
612 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
620 double eclExtPhiId(
const Particle* particle)
622 const Track* track = particle->getTrack();
625 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
628 return eclinfo->getExtPhiId();
630 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
638 double weightedAverageECLTime(
const Particle* particle)
640 int nDaughters = particle->getNDaughters();
641 if (nDaughters < 1) {
642 B2WARNING(
"The provided particle has no daughters!");
646 double numer = 0, denom = 0;
647 int numberOfClusterDaughters = 0;
649 auto weightedECLTimeAverage = [&numer, &denom, &numberOfClusterDaughters](
const Particle * p) {
650 const ECLCluster* cluster = p->getECLCluster();
651 if (cluster and not cluster->hasFailedFitTime()) {
652 numberOfClusterDaughters ++;
654 double time = cluster->getTime();
655 B2DEBUG(10,
"time[" << numberOfClusterDaughters <<
"] = " << time);
656 double deltatime = cluster->getDeltaTime99();
657 B2DEBUG(10,
"deltatime[" << numberOfClusterDaughters <<
"] = " << deltatime);
658 numer += time / pow(deltatime, 2);
659 B2DEBUG(11,
"numer[" << numberOfClusterDaughters <<
"] = " << numer);
660 denom += 1 / pow(deltatime, 2);
661 B2DEBUG(11,
"denom[" << numberOfClusterDaughters <<
"] = " << denom);
666 particle->forEachDaughter(weightedECLTimeAverage,
true,
true);
668 if (numberOfClusterDaughters < 1) {
669 B2WARNING(
"There are no clusters or cluster matches amongst the daughters of the provided particle!");
674 B2WARNING(
"The denominator of the weighted mean is zero!");
677 B2DEBUG(10,
"numer/denom = " << numer / denom);
678 return numer / denom;
682 double maxWeightedDistanceFromAverageECLTime(
const Particle* particle)
684 int nDaughters = particle->getNDaughters();
685 if (nDaughters < 1) {
686 B2WARNING(
"The provided particle has no daughters!");
690 double maxTimeDiff = -DBL_MAX;
691 int numberOfClusterDaughters = 0;
693 double averageECLTime = weightedAverageECLTime(particle);
695 auto maxTimeDifference = [&maxTimeDiff, &numberOfClusterDaughters, &averageECLTime](
const Particle * p) {
697 const ECLCluster* cluster = p->getECLCluster();
699 numberOfClusterDaughters ++;
701 double time = cluster->getTime();
702 B2DEBUG(10,
"time[" << numberOfClusterDaughters <<
"] = " << time);
703 double deltatime = cluster->getDeltaTime99();
704 B2DEBUG(10,
"deltatime[" << numberOfClusterDaughters <<
"] = " << deltatime);
705 double maxTimeDiff_temp = fabs((time - averageECLTime) / deltatime);
706 B2DEBUG(11,
"maxTimeDiff_temp[" << numberOfClusterDaughters <<
"] = " << maxTimeDiff_temp);
707 if (maxTimeDiff_temp > maxTimeDiff)
708 maxTimeDiff = maxTimeDiff_temp;
709 B2DEBUG(11,
"maxTimeDiff[" << numberOfClusterDaughters <<
"] = " << maxTimeDiff);
714 particle->forEachDaughter(maxTimeDifference,
true,
true);
716 if (numberOfClusterDaughters < 1) {
717 B2WARNING(
"There are no clusters or cluster matches amongst the daughters of the provided particle!");
721 if (maxTimeDiff < 0) {
722 B2WARNING(
"The max time difference is negative!");
725 B2DEBUG(10,
"maxTimeDiff = " << maxTimeDiff);
730 double eclClusterMdstIndex(
const Particle* particle)
732 const ECLCluster* cluster = particle->getECLCluster();
734 return cluster->getArrayIndex();
740 double eclClusterTimeNorm90(
const Particle* particle)
743 const ECLCluster* cluster = particle->getECLCluster();
744 StoreObjPtr<EventLevelClusteringInfo> elci;
747 std::string payloadName =
"ECLTimingNormalization_data";
749 static DBObjPtr<ECLTimingNormalization> ECLTimingNormalization(payloadName);
750 if (!ECLTimingNormalization.isValid()) {
751 B2FATAL(payloadName <<
" payload is not available");
754 if (elci and cluster) {
758 unsigned short cellID = cluster->getMaxECellId();
759 const unsigned short firstCellID = 161;
760 const unsigned short lastCellID = 8608;
761 const double rawTime = cluster->getTime();
762 double tNorm90 = -99.;
763 if (cellID < firstCellID or cellID > lastCellID) {
764 const double dt99 = cluster->getDeltaTime99();
765 if (dt99 != 0) {tNorm90 = 1.5 * rawTime / dt99;}
768 int iCrys = cellID - 1;
771 const double timingBit = 2000. / 4096.;
772 double tSmear = timingBit * (gRandom->Uniform() - 0.5);
773 double time = rawTime + tSmear;
777 double clusterERaw = cluster->getEnergyRaw();
778 double singleECorrected = cluster->getEnergyHighestCrystal();
779 double singleCrystalE = singleECorrected * clusterERaw / clusterECorrected;
780 double basicEScale = 0.1 / singleCrystalE;
783 const int firstBarrel = 1153;
784 const int lastBarrel = 7776;
785 double ootCrys = elci->getNECLCalDigitsOutOfTimeBarrel();
786 if (cellID < firstBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeFWD();}
787 if (cellID > lastBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeBWD();}
791 const auto& par7 = ECLTimingNormalization->getTimeWalkPar();
792 float EForCor = singleCrystalE;
793 if (EForCor < par7[iCrys][5]) {EForCor = par7[iCrys][5];}
794 if (EForCor > par7[iCrys][6]) {EForCor = par7[iCrys][6];}
795 float dE = EForCor - par7[iCrys][0];
796 double timeWalkCor = par7[iCrys][1] + par7[iCrys][2] * dE;
798 timeWalkCor = par7[iCrys][1] + par7[iCrys][3] * dE + par7[iCrys][4] * dE * dE;
803 const auto& bPar = ECLTimingNormalization->getBackgroundPar();
805 if (oot < bPar[iCrys][3]) {oot = bPar[iCrys][3];}
806 if (oot > bPar[iCrys][4]) {oot = bPar[iCrys][4];}
807 double backgroundNorm = bPar[iCrys][0] + bPar[iCrys][1] * oot + bPar[iCrys][2] * oot * oot;
811 const auto& par7Energy = ECLTimingNormalization->getEnergyPar();
813 EForCor = singleCrystalE;
814 if (EForCor < par7Energy[iCrys][5]) {EForCor = par7Energy[iCrys][5];}
815 if (EForCor > par7Energy[iCrys][6]) {EForCor = par7Energy[iCrys][6];}
816 dE = EForCor - par7Energy[iCrys][0];
817 double energyNorm = par7Energy[iCrys][1] + par7Energy[iCrys][2] * dE;
819 energyNorm = par7Energy[iCrys][1] + par7Energy[iCrys][3] * dE + par7Energy[iCrys][4] * dE * dE;
823 double minTNorm = (double)ECLTimingNormalization->getMinTNormalization();
824 double tNormalization = basicEScale * backgroundNorm * energyNorm;
825 if (tNormalization < minTNorm) {tNormalization = minTNorm;}
826 tNorm90 = (time - timeWalkCor) / tNormalization;
839 double nECLOutOfTimeCrystalsFWDEndcap(
const Particle*)
841 StoreObjPtr<EventLevelClusteringInfo> elci;
843 return (
double)elci->getNECLCalDigitsOutOfTimeFWD();
846 double nECLOutOfTimeCrystalsBarrel(
const Particle*)
848 StoreObjPtr<EventLevelClusteringInfo> elci;
850 return (
double)elci->getNECLCalDigitsOutOfTimeBarrel();
853 double nECLOutOfTimeCrystalsBWDEndcap(
const Particle*)
855 StoreObjPtr<EventLevelClusteringInfo> elci;
857 return (
double)elci->getNECLCalDigitsOutOfTimeBWD();
860 double nECLOutOfTimeCrystals(
const Particle*)
862 StoreObjPtr<EventLevelClusteringInfo> elci;
864 return (
double)elci->getNECLCalDigitsOutOfTime();
867 double nRejectedECLShowersFWDEndcap(
const Particle*)
869 StoreObjPtr<EventLevelClusteringInfo> elci;
871 return (
double)elci->getNECLShowersRejectedFWD();
874 double nRejectedECLShowersBarrel(
const Particle*)
876 StoreObjPtr<EventLevelClusteringInfo> elci;
878 return (
double)elci->getNECLShowersRejectedBarrel();
881 double nRejectedECLShowersBWDEndcap(
const Particle*)
883 StoreObjPtr<EventLevelClusteringInfo> elci;
885 return (
double)elci->getNECLShowersRejectedBWD();
888 double nRejectedECLShowers(
const Particle*)
890 StoreObjPtr<EventLevelClusteringInfo> elci;
892 return (
double) elci->getNECLShowersRejected();
895 double nKLMMultistripHitsFWDEndcap(
const Particle*)
897 StoreObjPtr<EventLevelClusteringInfo> elci;
899 return (
double) elci->getNKLMDigitsMultiStripFWD();
902 double nKLMMultistripHitsBarrel(
const Particle*)
904 StoreObjPtr<EventLevelClusteringInfo> elci;
906 return (
double) elci->getNKLMDigitsMultiStripBarrel();
909 double nKLMMultistripHitsBWDEndcap(
const Particle*)
911 StoreObjPtr<EventLevelClusteringInfo> elci;
913 return (
double) elci->getNKLMDigitsMultiStripBWD();
916 double nKLMMultistripHits(
const Particle*)
918 StoreObjPtr<EventLevelClusteringInfo> elci;
920 return (
double) elci->getNKLMDigitsMultiStrip();
923 double nECLShowersFWDEndcap(
const Particle*)
925 StoreObjPtr<EventLevelClusteringInfo> elci;
927 return (
double) elci->getNECLShowersFWD();
930 double nECLShowersBarrel(
const Particle*)
932 StoreObjPtr<EventLevelClusteringInfo> elci;
934 return (
double) elci->getNECLShowersBarrel();
937 double nECLShowersBWDEndcap(
const Particle*)
939 StoreObjPtr<EventLevelClusteringInfo> elci;
941 return (
double) elci->getNECLShowersBWD();
944 double nECLShowers(
const Particle*)
946 StoreObjPtr<EventLevelClusteringInfo> elci;
948 return (
double) elci->getNECLShowers();
951 double nECLLocalMaximumsFWDEndcap(
const Particle*)
953 StoreObjPtr<EventLevelClusteringInfo> elci;
955 return (
double) elci->getNECLLocalMaximumsFWD();
958 double nECLLocalMaximumsBarrel(
const Particle*)
960 StoreObjPtr<EventLevelClusteringInfo> elci;
962 return (
double) elci->getNECLLocalMaximumsBarrel();
965 double nECLLocalMaximumsBWDEndcap(
const Particle*)
967 StoreObjPtr<EventLevelClusteringInfo> elci;
969 return (
double) elci->getNECLLocalMaximumsBWD();
972 double nECLLocalMaximums(
const Particle*)
974 StoreObjPtr<EventLevelClusteringInfo> elci;
976 return (
double) elci->getNECLLocalMaximums();
979 double nECLTriggerCellsFWDEndcap(
const Particle*)
981 StoreObjPtr<EventLevelClusteringInfo> elci;
983 return (
double) elci->getNECLTriggerCellsFWD();
986 double nECLTriggerCellsBarrel(
const Particle*)
988 StoreObjPtr<EventLevelClusteringInfo> elci;
990 return (
double) elci->getNECLTriggerCellsBarrel();
993 double nECLTriggerCellsBWDEndcap(
const Particle*)
995 StoreObjPtr<EventLevelClusteringInfo> elci;
997 return (
double) elci->getNECLTriggerCellsBWD();
1000 double nECLTriggerCells(
const Particle*)
1002 StoreObjPtr<EventLevelClusteringInfo> elci;
1004 return (
double) elci->getNECLTriggerCells();
1007 double eclClusterEoP(
const Particle* part)
1009 double E = eclClusterE(part);
1010 if (part->hasExtraInfo(
"bremsCorrectedPhotonEnergy")) {
1011 E += part->getExtraInfo(
"bremsCorrectedPhotonEnergy");
1013 const double p = part->getMomentumMagnitude();
1018 double eclClusterOnlyInvariantMass(
const Particle* part)
1020 int nDaughters = part->getNDaughters();
1021 ROOT::Math::PxPyPzEVector sum;
1023 if (nDaughters < 1) {
1024 return part->getMass();
1026 int nClusterDaughters = 0;
1027 std::stack<const Particle*> stacked;
1029 while (!stacked.empty()) {
1030 const Particle* current = stacked.top();
1033 const ECLCluster* cluster = current->getECLCluster();
1036 nClusterDaughters ++;
1037 ClusterUtils clutls;
1038 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, clusterBit);
1041 const std::vector<Particle*> daughters = current->getDaughters();
1042 nDaughters = current->getNDaughters();
1043 for (
int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
1044 stacked.push(daughters[iDaughter]);
1049 if (nClusterDaughters < 1) {
1050 B2WARNING(
"There are no clusters amongst the daughters of the provided particle!");
1053 B2DEBUG(10,
"Number of daughters with cluster associated = " << nClusterDaughters);
1060 std::string cutString =
"";
1061 if (arguments.size() > 0) {
1062 cutString = arguments[0];
1066 std::string photonlistname =
"gamma:all";
1067 if (arguments.size() > 1) {
1068 photonlistname = arguments[1];
1071 std::string tracklistname =
"e-:all";
1072 if (arguments.size() > 2) {
1073 tracklistname = arguments[2];
1076 auto func = [cut, photonlistname, tracklistname](
const Particle * particle) ->
double {
1080 B2WARNING(
"The variable photonHasOverlap is supposed to be calculated for photons. Returning NaN.");
1084 StoreObjPtr<ParticleList> photonlist(photonlistname);
1085 if (!(photonlist.isValid()))
1087 B2WARNING(
"The provided particle list " << photonlistname <<
" does not exist."
1088 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1093 B2WARNING(
"The list " << photonlistname <<
" does not contain photons."
1094 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1098 StoreObjPtr<ParticleList> tracklist(tracklistname);
1099 if (!(tracklist.isValid()))
1101 B2WARNING(
"The provided particle list " << tracklistname <<
" does not exist."
1102 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1107 B2WARNING(
"The list " << tracklistname <<
" does not contain charged final state particles."
1108 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1112 double connectedRegionID = eclClusterConnectedRegionID(particle);
1113 int mdstSource = particle->getMdstSource();
1115 for (
unsigned int i = 0; i < photonlist->getListSize(); i++)
1117 const Particle* part = photonlist->getParticle(i);
1120 if (part->getMdstSource() == mdstSource) {
1125 if (!cut->check(part)) {
1129 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1134 for (
unsigned int i = 0; i < tracklist->getListSize(); i++)
1136 const Particle* part = tracklist->getParticle(i);
1139 if (!cut->check(part)) {
1143 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1153 VARIABLE_GROUP(
"ECL cluster related");
1154 REGISTER_VARIABLE(
"clusterEoP", eclClusterEoP, R
"DOC(
1155Returns ratio of the cluster energy `clusterE` over momentum :math:`p`.
1158 The cluster energy is already corrected for Bremsstrahlung.
1161 REGISTER_VARIABLE("clusterReg", eclClusterDetectionRegion, R
"DOC(
1162Returns an integer code representing the ECL region for the cluster:
1164- 1: forward, 2: barrel, 3: backward
1165- 11: between forward endcap and barrel, 13: between backward endcap and barrel
1166- 0: outside the ECL acceptance region
1169 REGISTER_VARIABLE("clusterDeltaLTemp", eclClusterDeltaL, R
"DOC(
1170Returns the :math:`\Delta L` for the cluster shape as defined below.
1172First, the cluster direction is constructed by calculating the weighted average of the orientation
1173for the crystals in the cluster. The POCA of the vector with this direction originating from the
1174cluster center and an extrapolated track can be used to the calculate the shower
1175depth. :math:`\Delta L` is then defined as the distance between this intersection and the cluster center.
1178 This distance is calculated on the reconstruction level and is temporarily
1179 included in mdst for investigation purposes. If it is found
1180 that it is not crucial for physics analyses then this variable will be removed
1181 in future releases. So keep in mind that this variable might be removed in the future.
1184 Please read `this <importantNoteECL>` first.
1186 - Lower limit: :math:`-250.0`
1187 - Upper limit: :math:`250.0`
1188 - Precision: :math:`10` bit
1191 REGISTER_VARIABLE("minC2TDist", eclClusterIsolation, R"DOC(
1192Returns the distance between the cluster and its nearest track.
1194For all tracks in the event, the distance between each of their extrapolated hits in the ECL and the ECL shower
1195position is calculated, and the overall smallest distance is returned. If there are no extrapolated hits found in the ECL
1196for the event, ``NaN`` will be returned. The track array index of the track that is closest to the cluster can be
1197retrieved using `minC2TDistID`.
1200 Please read `this <importantNoteECL>` first.
1202 - Lower limit: :math:`0.0`
1203 - Upper limit: :math:`250.0`
1204 - Precision: :math:`10` bit
1207 REGISTER_VARIABLE("minC2TDistID", eclClusterIsolationID, R"DOC(
1208Returns the track array index of the nearest track to the cluster. The nearest track is calculated
1209using the `minC2TDist` variable.
1212 REGISTER_METAVARIABLE("minC2TDistVar(variable,particleList='pi-:all')", eclClusterIsolationVar, R
"DOC(
1213Returns the value of your chosen variable for the track nearest to the given cluster as calculated by
1216The first parameter ``variable`` is the variable name e.g. `nCDCHits`, while the second (optional) parameter ``particleList``
1217is the particle list name which will be used in the calculation of `minC2TDist`. The default particle list used
1220)DOC", Manager::VariableDataType::c_double);
1221 REGISTER_VARIABLE("clusterE", eclClusterE, R
"DOC(
1222Returns the cluster energy corrected for leakage and background.
1225 We only store clusters with :math:`E > 20\,` MeV.
1227.. topic:: Calculating Photon Energy
1229 The raw photon energy is given by the weighted sum of all crystal energies within the cluster.
1230 The weights per crystals are :math:`\leq 1` after cluster energy splitting in the case of overlapping
1231 clusters. The number of crystals that are included in the sum depends on a initial energy estimation
1232 and local beam background levels for the highest energy crystal. The crystal number is optimized to minimize
1233 the resolution of photons. Photon energy distributions always show a low energy tail
1234 due to unavoidable longitudinal and transverse leakage. The peak position of the photon energy distributions are
1235 corrected to match the true photon energy in MC. The corrections applied include:
1237 - Leakage correction: using MC samples of mono-energetic single photon, a correction factor
1238 :math:`f` as function of the reconstructed detector position, photon energy and beam background level
1239 is determined via :math:`f = \frac{\text{peak_reconstructed}}{\text{energy_true}}`
1241 - Cluster energy calibration (data only): to reach the target precision of :math:`< 1.8\%` energy
1242 resolution for high energetic photons, the remaining difference between MC and data is calibrated
1243 using kinematically fits to muon pairs
1245 It is important to note that after perfect leakage corrections and cluster energy calibrations,
1246 the :math:`\pi^{0}` mass peak will be shifted slightly to smaller values than the PDG average
1247 due to the low energy tails of photons.
1250 Please read `this <importantNoteECL>` first.
1252 - Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV in the lab frame)
1253 - Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV in the lab frame)
1254 - Precision: :math:`18` bit
1257 REGISTER_VARIABLE("clusterErrorE", eclClusterErrorE, R"DOC(
1258Returns the uncertainty on the cluster energy. It is derived from
1259a background level and energy-dependent error tabulation.
1262 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1263 a directly-reconstructed quantity. For more information please see the
1264 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1268 REGISTER_VARIABLE("clusterErrorPhi", eclClusterErrorPhi, R"DOC(
1269Returns the uncertainty on the phi angle of the cluster. It is derived from
1270a background level and energy-dependent error tabulation.
1273 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1274 a directly-reconstructed quantity. For more information please see the
1275 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1279 REGISTER_VARIABLE("clusterErrorTheta", eclClusterErrorTheta, R"DOC(
1280Returns the uncertainty on the theta angle of the cluster. It is derived from
1281a background level and energy-dependent error tabulation.
1284 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1285 a directly-reconstructed quantity. For more information please see the
1286 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1290 REGISTER_VARIABLE("clusterR", eclClusterR, R"DOC(
1291Returns the distance of the cluster centroid from :math:`(0,0,0)`.
1294 This variable is not recommended for use in analyses as they are difficult to interpret. For more information please see the
1295 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1299 REGISTER_VARIABLE("clusterPhi", eclClusterPhi, R"DOC(
1300Returns the azimuthal angle :math:`\phi` of the cluster. This is generally not equal
1301to the azimuthal angle of the photon.
1303.. topic:: Calculating Cluster Direction
1305 The direction of a cluster is given by the connecting line from :math:`\,(0,0,0)\,` to
1306 cluster centroid position in the ECL. The centroid position is calculated using up to 21 crystals
1307 (as 5x5 grid excluding corners) after the crystal energies are split in the case of overlapping clusters.
1308 The centroid position is the logarithmically weighted average of all crystals evaluated at the
1309 crystal centers. The centroid is generally biased towards the centers of the highest energetic
1310 crystal. This effect is larger for low energy photons. Beam backgrounds slightly decrease the
1311 position resolution, and mainly effects the low energy photons.
1313 Unlike for charged tracks, the uncertainty (covariance) of the photon direction is not determined
1314 based on individual cluster properties but taken from MC-based parametrizations of the resolution
1315 as function of true photon energy, true photon direction and beam background level.
1318 Please read `this <importantNoteECL>` first.
1320 - Lower limit: :math:`-\pi`
1321 - Upper limit: :math:`\pi`
1322 - Precision: :math:`16` bit
1325 REGISTER_VARIABLE("clusterConnectedRegionID", eclClusterConnectedRegionID, R"DOC(
1326Returns connected region ID for the cluster.
1328 REGISTER_VARIABLE("clusterTheta", eclClusterTheta, R
"DOC(
1329Returns the polar angle :math:`\theta` of the cluster. This is generally not equal
1330to the polar angle of the photon.
1332.. topic:: Calculating Cluster Direction
1334 The direction of a cluster is given by the connecting line from :math:`\,(0,0,0)\,` to
1335 cluster centroid position in the ECL. The centroid position is calculated using up to 21 crystals
1336 (as 5x5 grid excluding corners) after the crystal energies are split in the case of overlapping clusters.
1337 The centroid position is the logarithmically weighted average of all crystals evaluated at the
1338 crystal centers. The centroid is generally biased towards the centers of the highest energetic
1339 crystal. This effect is larger for low energy photons. Beam backgrounds slightly decrease the
1340 position resolution, and mainly effects the low energy photons.
1342 Unlike for charged tracks, the uncertainty (covariance) of the photon direction is not determined
1343 based on individual cluster properties but taken from MC-based parametrizations of the resolution
1344 as function of true photon energy, true photon direction and beam background level.
1347 Please read `this <importantNoteECL>` first.
1349 - Lower limit: :math:`0.0`
1350 - Upper limit: :math:`\pi`
1351 - Precision: :math:`16` bit
1354 REGISTER_VARIABLE("clusterTiming", eclClusterTiming, R"DOC(
1355Returns the time of the cluster. This is calculated **differently** in Belle and Belle II. Please
1356read their definitions below.
1358.. topic:: In Belle II
1360 It is calculated as the cluster time minus the `eventT0`. The cluster time is obtained by a fit to
1361 the recorded waveform of the highest energy crystal in the cluster. For a cluster produced by a
1362 particle from the IP, the cluster time should be consistent with `eventT0` within the uncertainties
1363 following all calibrations and corrections. For MC, note that the calibrations and corrections are not
1364 fully simulated. In order to see if the waveform fit fails, see `clusterHasFailedTiming`.
1367 Please read `this <importantNoteECL>` first.
1369 - Lower limit: :math:`-1000.0`
1370 - Upper limit: :math:`1000.0`
1371 - Precision: :math:`12` bit
1375 It is equal to the trigger cell (TC) time corresponding to the cluster. This information is only
1376 available in Belle data since experiment 31, and not available in Belle MC. Clusters produced at the IP
1377 in time with the event have a TC time in the range of 9000 - 11000. More information can be found in the
1378 Appendix of Belle note 831.
1381 In case this variable is obtained from Belle data that is stored in Belle II mdst/udst format, it will be truncated to:
1383 - Lower limit: :math:`-1000.0`
1384 - Upper limit: :math:`1000.0`
1385 - Precision: :math:`12` bit
1388 REGISTER_VARIABLE("clusterHasFailedTiming", eclClusterHasFailedTiming, R"DOC(
1389Status bit indicating if the waveform fit for the `clusterTiming` calculation has failed.
1391 REGISTER_VARIABLE("clusterErrorTiming", eclClusterErrorTiming, R
"DOC(
1392Returns the cluster timing uncertainty which is equal to the :math:`dt99` value as defined below. Very large
1393values of :math:`dt99` are an indication of a failed waveform fit for the cluster.
1395The timing distribution for each cluster is non-Gaussian and so the value :math:`dt99` is stored where
1396:math:`|\text{timing}| / \text{dt99} < 1` is designed to give a :math:`99\%` timing efficiency for
1397true photons from the IP. (This definition results in an efficiency that is approximately flat in energy
1398and independent of the beam background level). The :math:`dt99` value stored is determined using MC with a
1399parametrisation that depends on the true energy deposition in the highest energetic crystal and the
1400local beam background level in that crystal.
1403 This variable should should only be used for relative timing selections as it is not
1404 a directly-reconstructed quantity. For more information please see the
1405 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1409 Please read `this <importantNoteECL>` first.
1411 - Lower limit: :math:`0.0`
1412 - Upper limit: :math:`1000.0`
1413 - Precision: :math:`12` bit
1416 REGISTER_VARIABLE("clusterHasFailedErrorTiming", eclClusterHasFailedErrorTiming, R"DOC(
1417Status bit indicating if the calculation of `clusterErrorTiming` has failed due to a failed
1420 REGISTER_VARIABLE("clusterHighestE", eclClusterHighestE, R
"DOC(
1421Returns the energy of the highest energetic crystal in the cluster after reweighting.
1424 This variable is not recommended for use in analyses as they are difficult to interpret. For more information please see the
1425 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1429 Please read `this <importantNoteECL>` first.
1431 - Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV)
1432 - Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV)
1433 - Precision: :math:`18` bit
1436 REGISTER_VARIABLE("clusterCellID", eclClusterCellId,
1437 "Returns the cell ID of the crystal with highest energy in the cluster.");
1438 REGISTER_VARIABLE("clusterThetaID", eclClusterThetaId, R"DOC(
1439Returns the :math:`\theta` ID of the crystal with highest energy in the cluster. There are
144069 :math:`\theta` IDs in total covering the entire ECL acceptance. The mapping between cell ID number
1441and :math:`\theta` ID can be found in the source code linked to the right of this variable description.
1443 REGISTER_VARIABLE("clusterPhiID", eclClusterPhiId, R
"DOC(
1444Returns the :math:`\phi` ID of the crystal with highest energy in the cluster.
1445While :math:`\theta` ID indicates the specific ring of the calorimeter,
1446:math:`\phi` ID indicates a position of a crystal in that ring. When facing
1447towards the direction of an electron beam, :math:`\phi` IDs go clockwise, with
14480 corresponding to the crystal closest to the outer side of the main ring tunnel.
1450.. admonition:: Diagram
1451 :class: dropdown xhint stacked
1453 .. code-block:: text
1455 phi_id = (nring/4) phi_id = (nring/4) - 1
1458 .... . . ││.. .. . .
1459 .. . . .... ││ ..... . . . .
1467 nring/2 ───── (towards the ───── phi_id = 0
1468 nring/2 - 1 ───── electron beam) ───── phi_id = (nring - 1)
1476 ... . . . .. ││. .. . .... .
1477 . . . . .││ ... ... .
1480 phi_id = (nring*3/4) - 1 phi_id = (nring/4) - 1
1482 The number of crystals per ring can be found see the `code <https://software.belle2.org/development/doxygen/classBelle2_1_1ECL_1_1ECLNeighbours.html#a4d5f886765986da6afb0559fb398106b>`_.
1485 REGISTER_VARIABLE("clusterE1E9", eclClusterE1E9, R
"DOC(
1486Returns the ratio of the energy in the central crystal (:math:`E_1`) to the total energy in the
14873x3 crystal grid around the central crystal (:math:`E_9`). Since :math:`E_1 \leq E_9`, this ratio is
1488:math:`\leq 1` and tends towards larger values for photons and smaller values for hadrons.
1491 Please read `this <importantNoteECL>` first.
1493 - Lower limit: :math:`0.0`
1494 - Upper limit: :math:`1.0`
1495 - Precision: :math:`10` bit
1498 REGISTER_VARIABLE("clusterE9E25", eclClusterE9E25, R
"DOC(
1499Returns `clusterE9E21`. This variable is kept for backwards compatibility.
1501 REGISTER_VARIABLE("clusterE9E21", eclClusterE9E21, R
"DOC(
1502Returns the ratio of the total energy in the 3x3 crystal grid around the central
1503crystal (:math:`E_9`) to the total energy in the 5x5 crystal grid around the central crystal
1504excluding the corners (:math:`E_{21}`). Since :math:`E_9 \leq E_{21}`, this ratio is :math:`\leq 1` and tends towards larger
1505values for photons and smaller values for hadrons.
1508 Please read `this <importantNoteECL>` first.
1510 - Lower limit: :math:`0.0`
1511 - Upper limit: :math:`1.0`
1512 - Precision: :math:`10` bit
1515 REGISTER_VARIABLE("clusterAbsZernikeMoment40", eclClusterAbsZernikeMoment40, R
"DOC(
1516Returns absolute value of the 40th Zernike moment :math:`|Z_{40}|`. An explanation on this shower
1517shape variable is in the description for the `clusterZernikeMVA` variable.
1520 Please read `this <importantNoteECL>` first.
1522 - Lower limit: :math:`0.0`
1523 - Upper limit: :math:`1.7`
1524 - Precision: :math:`10` bit
1527 REGISTER_VARIABLE("clusterAbsZernikeMoment51", eclClusterAbsZernikeMoment51, R
"DOC(
1528Returns absolute value of the 51st Zernike moment :math:`|Z_{51}|`. An explanation on this shower
1529shape variable is in the description for the `clusterZernikeMVA` variable.
1532 Please read `this <importantNoteECL>` first.
1534 - Lower limit: :math:`0.0`
1535 - Upper limit: :math:`1.2`
1536 - Precision: :math:`10` bit
1539 REGISTER_VARIABLE("clusterZernikeMVA", eclClusterZernikeMVA, R
"DOC(
1540Returns output of an MVA trained to use eleven Zernike moments of the cluster.
1542Zernike moments are calculated for each shower in the plane perpendicular to
1543the shower direction via
1546 |Z_{nm}| = \frac{n+1}{\pi} \frac{1}{\sum_{i} w_{i} E_{i}} \left|\sum_{i} R_{nm}(\rho_{i}) e^{-im\alpha_{i}} w_{i} E_{i} \right|
1548where :math:`n, m` are the integers, :math:`i` runs over each crystal in the shower,
1549:math:`E_{i}` is the energy of the i-th crystal in the shower,
1550:math:`R_{nm}` is a polynomial of degree :math:`n`,
1551:math:`\rho_{i}` is the radial distance of the :math:`i`-th crystal in the perpendicular plane,
1552and :math:`\alpha_{i}` is the polar angle of the :math:`i`-th crystal in the perpendicular plane.
1553As a crystal can be related to more than one shower, :math:`w_{i}` is the fraction of the
1554energy of the :math:`i`-th crystal associated with the shower.
1557 This variable is sensitive to other nearby particles and so cluster isolation properties shoud
1558 always be checked. For more information please see the
1559 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1563 - More details about the implementation can be found in `BELLE2-NOTE-TE-2017-001 <https://docs.belle2.org/record/454?ln=en>`_ .
1564 - More details about Zernike polynomials can be found on `Wikipedia <https://en.wikipedia.org/wiki/Zernike_polynomials>`_ .
1567 Please read `this <importantNoteECL>` first.
1569 - Lower limit: :math:`0.0`
1570 - Upper limit: :math:`1.0`
1571 - Precision: :math:`10` bit
1574 REGISTER_VARIABLE("clusterSecondMoment", eclClusterSecondMoment, R
"DOC(
1575Returns the second moment :math:`S` of the cluster. This is mainly implemented for reconstructing high a
1576energy :math:`\pi^0` originating from merged clusters.
1581 S = \frac{1}{S_{0}(\theta)}\frac{\sum_{i=0}^{n} w_{i} E_{i} r^2_{i}}{\sum_{i=0}^{n} w_{i} E_{i}}
1583where :math:`E_{i} = (E_0, E_1, ...)` are the crystal energies sorted by descending energy, :math:`w_{i}` is
1584the fraction of the crystal energy associated with the shower, and :math:`r_{i}` is the distance of
1585the :math:`i`-th digit to the shower center projected onto a plane perpendicular to the
1586shower axis. :math:`S_{0}(\theta)` normalizes :math:`S` to 1 for isolated photons.
1589 Please read `this <importantNoteECL>` first.
1591 - Lower limit: :math:`0.0`
1592 - Upper limit: :math:`40.0`
1593 - Precision: :math:`10` bit
1595)DOC","dimensionless");
1596 REGISTER_VARIABLE("clusterLAT", eclClusterLAT, R"DOC(
1597Returns lateral energy distribution of the shower. For radially-symmetric electromagnetic showers, this
1598variable peaks at :math:`\approx 0.3`. It is larger for hadronic particles and electrons with a nearby relative
1599or Bremsstrahlung photon.
1601It is defined as following:
1604 S = \frac{\sum_{i=2}^{n} w_{i} E_{i} r^2_{i}}{(w_{0} E_{0} + w_{1} E_{1}) r^2_{0} + \sum_{i=2}^{n} w_{i} E_{i} r^2_{i}}
1606where :math:`E_{i} = (E_0, E_1, ...)` are the crystal energies sorted by descending energy, :math:`w_{i}` is
1607the fraction of the crystal energy associated with the shower, :math:`r_{i}` is the distance of
1608the :math:`i`-th digit to the shower center projected onto a plane perpendicular to the shower axis,
1609and :math:`r_{0} \approx 5\,cm` is the average distance between two crystal centres.
1612 This variable peaks around 0.3 for symmetrical electromagnetic showers and is larger for hadronic
1613 showers and electrons with a close-by radiative or Bremsstrahlung photon.
1616 Please read `this <importantNoteECL>` first.
1618 - Lower limit: :math:`0.0`
1619 - Upper limit: :math:`1.0`
1620 - Precision: :math:`10` bit
1623 REGISTER_VARIABLE("clusterNHits", eclClusterNHits, R
"DOC(
1624Returns sum of weights :math:`w_{i}` (:math:`w_{i} \leq 1`) of all crystals in the cluster.
1625For non-overlapping clusters this is equal to the number of crystals in the cluster. However, in the case
1626of overlapping clusters where individual crystal energies are split among them, this can be a non-integer value.
1629 If fractional weights are not of interest, this value should be cast to the nearest `int`
1632 Please read `this <importantNoteECL>` first.
1634 - Lower limit: :math:`0.0`
1635 - Upper limit: :math:`200.0`
1636 - Precision: :math:`10` bit
1639 REGISTER_VARIABLE("clusterTrackMatch", eclClusterTrackMatched, R
"DOC(
1640Returns 1.0 if at least one reconstructed charged track is matched to the cluster. Track-cluster
1641matching is briefly described below.
1643Every reconstructed track is extrapolated to the ECL. Every ECL crystal that is crossed by
1644the extrapolated track is marked. Following this, every cluster that contains a marked crystal
1645becomes associated with the original track. The current algorithm matches only one cluster to a
1646track but can match multiple tracks to the same cluster. In the latter case, all tracks matched
1647to the same cluster will return the same cluster variables e.g. all will have the same `clusterE`.
1649 REGISTER_VARIABLE("nECLClusterTrackMatches", nECLClusterTrackMatches, R
"DOC(
1650Returns the number of tracks matched to the cluster. For more information on track-cluster matching
1651please see the description for `clusterTrackMatch`.
1653For the clusters of neutral particles, this should always return 0. If there is no cluster ``NaN`` is
1656 REGISTER_VARIABLE("clusterHasPulseShapeDiscrimination", eclClusterHasPulseShapeDiscrimination, R
"DOC(
1657Status bit to indicate if the waveforms from the cluster pass the requirements for computing pulse
1658shape discrimination variables such as `clusterPulseShapeDiscriminationMVA`.
1660.. topic:: Pulse Shape Information Requirements
1662 The exact requirements for a cluster have pulse shape information are as follows:
1663 - there is at least one crystal with energy above 30 MeV for phase 2 data or 50 MeV for phase 3 data
1664 (this is the energy threshold requirement for saving waveforms offline)
1665 - one of the waveforms for the cluster must have a good :math:`\chi^2` fit
1668 REGISTER_VARIABLE("beamBackgroundSuppression", beamBackgroundSuppression, R
"DOC(
1669Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from beam background clusters.
1670Class 1 is for true photon clusters while class 0 is for beam background clusters.
1672The MVA has been trained using MC and the features used, in decreasing importance, are:
1675- `clusterPulseShapeDiscriminationMVA`
1678- `clusterZernikeMVA` (this has been removed starting from the MC16 training)
1682 For the correct usage, please see
1683 the `Performance Recommendations Webpage <https://belle2.pages.desy.de/performance/recommendations/>`_.
1687 Please cite `this proceeding <https://inspirehep.net/literature/2785196>`_ if using this tool.
1689 REGISTER_VARIABLE("fakePhotonSuppression", fakePhotonSuppression, R
"DOC(
1690Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from fake photon clusters.
1691Class 1 is for true photon clusters while class 0 is for fake photon clusters.
1693The MVA has been trained using MC and the features, in decreasing importance, are:
1695- `clusterPulseShapeDiscriminationMVA`
1700- `clusterZernikeMVA` (this has been removed starting from the MC16 training)
1703 For the correct usage, please see
1704 the `Performance Recommendations Webpage <https://belle2.pages.desy.de/performance/recommendations/>`_.
1707 Please cite `this proceeding <https://inspirehep.net/literature/2785196>`_ if using this tool.
1710 REGISTER_VARIABLE("hadronicSplitOffSuppression", hadronicSplitOffSuppression, R
"DOC(
1711Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from hadronic splitoff clusters.
1714- 1 for true photon clusters
1715- 0 for hadronic splitoff clusters
1717The MVA has been trained using samples of signal photons and hadronic splitoff photons coming from MC.
1718The features used are (in decreasing order of significance):
1720- `clusterPulseShapeDiscriminationMVA`
1722- `clusterZernikeMVA`
1726- `clusterSecondMoment`
1729 MAKE_DEPRECATED("hadronicSplitOffSuppression",
true,
"light-2302-genetta", R
"DOC(
1730 Use the variable `fakePhotonSuppression` instead which is maintained and uses the latest weight files.
1732 REGISTER_VARIABLE("clusterKlId", eclClusterKlId, R
"DOC(
1733Returns MVA classifier that uses ECL clusters variables to discriminate Klong clusters from em background.
1742 REGISTER_VARIABLE("clusterPulseShapeDiscriminationMVA", eclPulseShapeDiscriminationMVA, R
"DOC(
1743Returns the output of an MVA classifier that uses pulse shape information to discriminate between electromagnetic
1744and hadronic showers. Class 1 is for electromagnetic showers while class 0 is for hadronic showers.
1747 Please cite `this paper <https://inspirehep.net/literature/1807894>`_ if using this tool.
1750 REGISTER_VARIABLE("clusterNumberOfHadronDigits", eclClusterNumberOfHadronDigits, R
"DOC(
1751Returns the number of hadron digits in the cluster based on pulse shape information. This is the weight sum of cluster digits
1752that have :math:`> 3\,` MeV for the hadronic scintillation component. The digits must have pulse shape information available
1753(see `clusterHasPulseShapeDiscrimination` for more information).
1756 This is a purely technical flag and should not be used for any physics-level selection
1759 Please read `this <importantNoteECL>` first.
1761 - Lower limit: :math:`0.0`
1762 - Upper limit: :math:`255.0`
1763 - Precision: :math:`18` bit
1766 REGISTER_VARIABLE("clusterClusterID", eclClusterId, R
"DOC(
1767Returns the ID the cluster within the connected region to which it belongs.
1769 REGISTER_VARIABLE("clusterHasNPhotons", eclClusterHasNPhotonsHypothesis, R
"DOC(
1770Returns 1.0 if the cluster has the "N photons" hypothesis (historically called "N1"),
17710.0 if not, and ``NaN`` if no cluster is associated to the particle.
1773 REGISTER_VARIABLE("clusterHasNeutralHadron", eclClusterHasNeutralHadronHypothesis, R
"DOC(
1774Returns 1.0 if the cluster has the "neutral hadrons" hypothesis (historically called "N2"),
17750.0 if not, and ``NaN`` if no cluster is associated to the particle.
1777 REGISTER_VARIABLE("eclExtTheta", eclExtTheta, R
"DOC(
1778Returns the :math:`\theta` angle of the extrapolated track associated to the cluster (if any).
1781 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1784 REGISTER_VARIABLE("eclExtPhi", eclExtPhi, R"DOC(
1785Returns the :math:`\phi` angle of the extrapolated track associated to the cluster (if any).
1788 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1791 REGISTER_VARIABLE("eclExtPhiId", eclExtPhiId, R"DOC(
1792Returns the :math:`\phi` ID of the extrapolated track associated to the cluster (if any).
1795 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1798 REGISTER_VARIABLE("weightedAverageECLTime", weightedAverageECLTime, R
"DOC(
1799Returns the weighted average time of all clusters corresponding to daughter particles of the provided particle.
1802 REGISTER_VARIABLE(
"maxWeightedDistanceFromAverageECLTime", maxWeightedDistanceFromAverageECLTime, R
"DOC(
1803Returns maximum weighted distance between time of the cluster of a photon and the ECL average time, amongst
1804the clusters (neutrals) and matched clusters (charged) of daughters (of all generations) of the provided particle.
1807 REGISTER_VARIABLE(
"clusterMdstIndex", eclClusterMdstIndex, R
"DOC(
1808Returns the ``StoreArray`` index of the cluster mDST object. This can be useful for track-based particles that are matched to an cluster.
1811 REGISTER_VARIABLE("nECLOutOfTimeCrystals", nECLOutOfTimeCrystals, R
"DOC(
1812**[Eventbased]** Returns the number of crystals that are out of time with the `eventT0` by more than 110.0 ns. Only crystals with an energy greater than
18137 MeV are are counted.
1816 REGISTER_VARIABLE("nECLOutOfTimeCrystalsFWDEndcap", nECLOutOfTimeCrystalsFWDEndcap, R
"DOC(
1817**[Eventbased]** Returns the number of crystals in the forward endcap that are out of time with the `eventT0` by more than 110.0 ns. Only crystals with an energy greater than
18187 MeV are are counted.
1821 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBarrel", nECLOutOfTimeCrystalsBarrel, R
"DOC(
1822**[Eventbased]** Returns the number of crystals in the barrel that are out of time with the `eventT0` by more than 110.0 ns. Only crystals with an energy greater than
18237 MeV are are counted.
1826 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBWDEndcap", nECLOutOfTimeCrystalsBWDEndcap, R
"DOC(
1827**[Eventbased]** Returns the number of crystals in the backward endcap that are out of time with the `eventT0` by more than 110.0 ns. Only crystals with an energy greater than
18287 MeV are are counted.
1831 REGISTER_VARIABLE("nRejectedECLShowers", nRejectedECLShowers, R
"DOC(
1832**[Eventbased]** Returns the number of ECL showers that do not become clusters. If the number exceeds 255, the variable is set to 255.
1835 REGISTER_VARIABLE("nRejectedECLShowersFWDEndcap", nRejectedECLShowersFWDEndcap, R
"DOC(
1836**[Eventbased]** Returns the number of ECL showers in the forward endcap that do not become clusters.
1837If the number exceeds 255, the variable is set to 255.
1840 REGISTER_VARIABLE("nRejectedECLShowersBarrel", nRejectedECLShowersBarrel, R
"DOC(
1841**[Eventbased]** Returns the number of ECL showers in the barrel that do not become clusters.
1842If the number exceeds 255, the variable is set to 255.
1845 REGISTER_VARIABLE("nRejectedECLShowersBWDEndcap", nRejectedECLShowersBWDEndcap, R
"DOC(
1846**[Eventbased]** Returns the number of ECL showers in the backward endcap that do not become clusters.
1847If the number exceeds 255, the variable is set to 255.
1850 REGISTER_VARIABLE("nKLMMultistripHitsFWDEndcap", nKLMMultistripHitsFWDEndcap, R
"DOC(
1851**[Eventbased]** Returns the number of multi-strip hits in the KLM forward endcap associated with the ECL cluster.
1854 REGISTER_VARIABLE("nKLMMultistripHitsBarrel", nKLMMultistripHitsBarrel, R
"DOC(
1855**[Eventbased]** Returns the number of multi-strip hits in the KLM barrel associated with the ECL cluster.
1858 REGISTER_VARIABLE("nKLMMultistripHitsBWDEndcap", nKLMMultistripHitsBWDEndcap, R
"DOC(
1859**[Eventbased]** Returns the number of multi-strip hits in the KLM backward endcap associated with the ECL cluster.
1862 REGISTER_VARIABLE("nKLMMultistripHits", nKLMMultistripHits, R
"DOC(
1863**[Eventbased]** Returns the number of multi-strip hits in the KLM associated with the ECL cluster.
1866 REGISTER_VARIABLE("nECLShowersFWDEndcap", nECLShowersFWDEndcap, R
"DOC(
1867**[Eventbased]** Returns the number of ECL showers in the forward endcap.
1870 REGISTER_VARIABLE("nECLShowersBarrel", nECLShowersBarrel, R
"DOC(
1871**[Eventbased]** Returns the number of ECL showers in the barrel.
1874 REGISTER_VARIABLE("nECLShowersBWDEndcap", nECLShowersBWDEndcap, R
"DOC(
1875**[Eventbased]** Returns the number of ECL showers in the backward endcap.
1878 REGISTER_VARIABLE("nECLShowers", nECLShowers, R
"DOC(
1879**[Eventbased]** Returns the number of ECL showers.
1882 REGISTER_VARIABLE("nECLLocalMaximumsFWDEndcap", nECLLocalMaximumsFWDEndcap, R
"DOC(
1883**[Eventbased]** Returns the number of Local Maximums in the ECL forward endcap.
1886 REGISTER_VARIABLE("nECLLocalMaximumsBarrel", nECLLocalMaximumsBarrel, R
"DOC(
1887**[Eventbased]** Returns the number of Local Maximums in the ECL barrel.
1890 REGISTER_VARIABLE("nECLLocalMaximumsBWDEndcap", nECLLocalMaximumsBWDEndcap, R
"DOC(
1891**[Eventbased]** Returns the number of Local Maximums in the ECL backward endcap.
1894 REGISTER_VARIABLE("nECLLocalMaximums", nECLLocalMaximums, R
"DOC(
1895**[Eventbased]** Returns the number of Local Maximums in the ECL.
1898 REGISTER_VARIABLE("nECLTriggerCellsFWDEndcap", nECLTriggerCellsFWDEndcap, R
"DOC(
1899**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the forward endcap.
1902 REGISTER_VARIABLE("nECLTriggerCellsBarrel", nECLTriggerCellsBarrel, R
"DOC(
1903**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the barrel.
1906 REGISTER_VARIABLE("nECLTriggerCellsBWDEndcap", nECLTriggerCellsBWDEndcap, R
"DOC(
1907**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the backward endcap.
1910 REGISTER_VARIABLE("nECLTriggerCells", nECLTriggerCells, R
"DOC(
1911**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV.
1914 REGISTER_VARIABLE("eclClusterOnlyInvariantMass", eclClusterOnlyInvariantMass, R
"DOC(
1915Returns the invariant mass calculated from all neutral and track-matched cluster daughters using the cluster 4-momenta.
1916This is primarily used for ECL-based dark sector physics and debugging track-cluster matching.
1918)DOC","GeV/:math:`\\text{c}^2`");
1920 REGISTER_METAVARIABLE("photonHasOverlap(cutString, photonlistname, tracklistname)", photonHasOverlap, R"DOC(
1921Returns ``True`` if the connection region of the cluster is shared by another cluster. Both neutral and track-matched clusters
1924A ``cutString`` can be provided in order to ignore clusters that do not satisfy a given criteria. By default, the particle lists
1925``gamma:all`` and ``e-:all`` are used to check for neutral and track-matched clusters respectively. However, this can be customised
1926by using the ``photonlistname`` and ``tracklistname`` parameters. If ``gamma:all`` or ``e-:all`` does not exist or if this variable is applied
1927to a particle that is not a photon, ``NaN`` will be returned.
1928)DOC", Manager::VariableDataType::c_double);
1930 REGISTER_VARIABLE("clusterUncorrE", eclClusterUncorrectedE, R
"DOC(
1931Returns the uncorrected energy of the cluster.
1934 This variable should not be used for any physics analysis but only for ECL or calibration studies.
1938 REGISTER_VARIABLE("distanceToMcKl",distanceToMcKl,R"DOC(
1939Returns the distance to the nearest truth-matched :math:`K_L^0` particle that has been extrapolated to the cluster.
1942 This requires the `getNeutralHadronGeomMatches` function to be used.
1946 REGISTER_VARIABLE(
"distanceToMcNeutron",distanceToMcNeutron,R
"DOC(
1947Returns the distance to the nearest truth-matched (anti)neutron particle that has been extrapolated to the cluster.
1950 This requires the `getNeutralHadronGeomMatches` function to be used.
1954 REGISTER_VARIABLE(
"mdstIndexMcKl",mdstIndexMcKl,R
"DOC(
1955Returns the ``StoreArray`` index of the mDST object corresponding to the nearest truth-matched :math:`K_L^0` particle as determined
1956during the calculation of the `distanceToMcKl` variable.
1959 This requires the `getNeutralHadronGeomMatches` function to be used.
1963 REGISTER_VARIABLE("mdstIndexMcNeutron",mdstIndexMcNeutron,R
"DOC(
1964Returns the ``StoreArray`` index of the mDST object corresponding to the nearest truth-matched (anti)neutron particle as determined
1965during the calculation of the `distanceToMcKl` variable.
1968 This requires the `getNeutralHadronGeomMatches` function to be used.
1970 REGISTER_VARIABLE("clusterTimeNorm90", eclClusterTimeNorm90,R
"DOC(
1971Returns a normalised version of `clusterTiming` such that :math:`90\%` of real photons will
1972have :math:`|\text{timing normalised}| < 1`.
1974This is calculated only for crystals within the CDC acceptance (:math:`161 \leq` `clusterCellID` :math:`\leq 8608`). Outside
1975this region, :math:`1.5 \times` `clusterTiming` / `clusterErrorTiming` is returned. The normalisation depends on the photon
1976energy, beam background level and cell ID. It also differs for data and MC.
1979 A typical requirement for this variable is :math:`|\text{clusterTimeNorm90}| < 3`
1982 The required payloads for this variable are stored in the Neutrals global tag. The recommended global tag to use can be
1983 found on the `Performance Recommendations Webpage <https://belle2.pages.desy.de/performance/recommendations/>`_.
1985)DOC", "dimensionless");
int getPDGCode() const
PDG code.
static const ParticleSet chargedStableSet
set of charged stable particles
static const double doubleNaN
quiet_NaN
static const ParticleType photon
photon particle
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
@ c_nPhotons
CR is split into n photons (N1)
@ c_neutralHadron
CR is reconstructed as a neutral hadron (N2)
static Environment & Instance()
Static method to get a reference to the Environment instance.
static std::unique_ptr< GeneralCut > compile(const std::string &cut)
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.