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) {
757 unsigned short cellID = cluster->getMaxECellId();
758 const unsigned short firstCellID = 161;
759 const unsigned short lastCellID = 8608;
761 int iCrys = cellID - 1;
764 double rawTime = cluster->getTime();
765 const double timingBit = 2000. / 4096.;
766 double tSmear = timingBit * (gRandom->Uniform() - 0.5);
767 double time = rawTime + tSmear;
771 double clusterERaw = cluster->getEnergyRaw();
772 double singleECorrected = cluster->getEnergyHighestCrystal();
773 double singleCrystalE = singleECorrected * clusterERaw / clusterECorrected;
774 double basicEScale = 0.1 / singleCrystalE;
777 const int firstBarrel = 1153;
778 const int lastBarrel = 7776;
779 double ootCrys = elci->getNECLCalDigitsOutOfTimeBarrel();
780 if (cellID < firstBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeFWD();}
781 if (cellID > lastBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeBWD();}
785 const auto& par7 = ECLTimingNormalization->getTimeWalkPar();
786 float EForCor = singleCrystalE;
787 if (EForCor < par7[iCrys][5]) {EForCor = par7[iCrys][5];}
788 if (EForCor > par7[iCrys][6]) {EForCor = par7[iCrys][6];}
789 float dE = EForCor - par7[iCrys][0];
790 double timeWalkCor = par7[iCrys][1] + par7[iCrys][2] * dE;
792 timeWalkCor = par7[iCrys][1] + par7[iCrys][3] * dE + par7[iCrys][4] * dE * dE;
797 const auto& bPar = ECLTimingNormalization->getBackgroundPar();
799 if (oot < bPar[iCrys][3]) {oot = bPar[iCrys][3];}
800 if (oot > bPar[iCrys][4]) {oot = bPar[iCrys][4];}
801 double backgroundNorm = bPar[iCrys][0] + bPar[iCrys][1] * oot + bPar[iCrys][2] * oot * oot;
805 const auto& par7Energy = ECLTimingNormalization->getEnergyPar();
807 EForCor = singleCrystalE;
808 if (EForCor < par7Energy[iCrys][5]) {EForCor = par7Energy[iCrys][5];}
809 if (EForCor > par7Energy[iCrys][6]) {EForCor = par7Energy[iCrys][6];}
810 dE = EForCor - par7Energy[iCrys][0];
811 double energyNorm = par7Energy[iCrys][1] + par7Energy[iCrys][2] * dE;
813 energyNorm = par7Energy[iCrys][1] + par7Energy[iCrys][3] * dE + par7Energy[iCrys][4] * dE * dE;
817 double minTNorm = (double)ECLTimingNormalization->getMinTNormalization();
818 double tNormalization = basicEScale * backgroundNorm * energyNorm;
819 if (tNormalization < minTNorm) {tNormalization = minTNorm;}
820 double tNorm90 = (time - timeWalkCor) / tNormalization;
833 double nECLOutOfTimeCrystalsFWDEndcap(
const Particle*)
835 StoreObjPtr<EventLevelClusteringInfo> elci;
837 return (
double)elci->getNECLCalDigitsOutOfTimeFWD();
840 double nECLOutOfTimeCrystalsBarrel(
const Particle*)
842 StoreObjPtr<EventLevelClusteringInfo> elci;
844 return (
double)elci->getNECLCalDigitsOutOfTimeBarrel();
847 double nECLOutOfTimeCrystalsBWDEndcap(
const Particle*)
849 StoreObjPtr<EventLevelClusteringInfo> elci;
851 return (
double)elci->getNECLCalDigitsOutOfTimeBWD();
854 double nECLOutOfTimeCrystals(
const Particle*)
856 StoreObjPtr<EventLevelClusteringInfo> elci;
858 return (
double)elci->getNECLCalDigitsOutOfTime();
861 double nRejectedECLShowersFWDEndcap(
const Particle*)
863 StoreObjPtr<EventLevelClusteringInfo> elci;
865 return (
double)elci->getNECLShowersRejectedFWD();
868 double nRejectedECLShowersBarrel(
const Particle*)
870 StoreObjPtr<EventLevelClusteringInfo> elci;
872 return (
double)elci->getNECLShowersRejectedBarrel();
875 double nRejectedECLShowersBWDEndcap(
const Particle*)
877 StoreObjPtr<EventLevelClusteringInfo> elci;
879 return (
double)elci->getNECLShowersRejectedBWD();
882 double nRejectedECLShowers(
const Particle*)
884 StoreObjPtr<EventLevelClusteringInfo> elci;
886 return (
double) elci->getNECLShowersRejected();
889 double nKLMMultistripHitsFWDEndcap(
const Particle*)
891 StoreObjPtr<EventLevelClusteringInfo> elci;
893 return (
double) elci->getNKLMDigitsMultiStripFWD();
896 double nKLMMultistripHitsBarrel(
const Particle*)
898 StoreObjPtr<EventLevelClusteringInfo> elci;
900 return (
double) elci->getNKLMDigitsMultiStripBarrel();
903 double nKLMMultistripHitsBWDEndcap(
const Particle*)
905 StoreObjPtr<EventLevelClusteringInfo> elci;
907 return (
double) elci->getNKLMDigitsMultiStripBWD();
910 double nKLMMultistripHits(
const Particle*)
912 StoreObjPtr<EventLevelClusteringInfo> elci;
914 return (
double) elci->getNKLMDigitsMultiStrip();
917 double nECLShowersFWDEndcap(
const Particle*)
919 StoreObjPtr<EventLevelClusteringInfo> elci;
921 return (
double) elci->getNECLShowersFWD();
924 double nECLShowersBarrel(
const Particle*)
926 StoreObjPtr<EventLevelClusteringInfo> elci;
928 return (
double) elci->getNECLShowersBarrel();
931 double nECLShowersBWDEndcap(
const Particle*)
933 StoreObjPtr<EventLevelClusteringInfo> elci;
935 return (
double) elci->getNECLShowersBWD();
938 double nECLShowers(
const Particle*)
940 StoreObjPtr<EventLevelClusteringInfo> elci;
942 return (
double) elci->getNECLShowers();
945 double nECLLocalMaximumsFWDEndcap(
const Particle*)
947 StoreObjPtr<EventLevelClusteringInfo> elci;
949 return (
double) elci->getNECLLocalMaximumsFWD();
952 double nECLLocalMaximumsBarrel(
const Particle*)
954 StoreObjPtr<EventLevelClusteringInfo> elci;
956 return (
double) elci->getNECLLocalMaximumsBarrel();
959 double nECLLocalMaximumsBWDEndcap(
const Particle*)
961 StoreObjPtr<EventLevelClusteringInfo> elci;
963 return (
double) elci->getNECLLocalMaximumsBWD();
966 double nECLLocalMaximums(
const Particle*)
968 StoreObjPtr<EventLevelClusteringInfo> elci;
970 return (
double) elci->getNECLLocalMaximums();
973 double nECLTriggerCellsFWDEndcap(
const Particle*)
975 StoreObjPtr<EventLevelClusteringInfo> elci;
977 return (
double) elci->getNECLTriggerCellsFWD();
980 double nECLTriggerCellsBarrel(
const Particle*)
982 StoreObjPtr<EventLevelClusteringInfo> elci;
984 return (
double) elci->getNECLTriggerCellsBarrel();
987 double nECLTriggerCellsBWDEndcap(
const Particle*)
989 StoreObjPtr<EventLevelClusteringInfo> elci;
991 return (
double) elci->getNECLTriggerCellsBWD();
994 double nECLTriggerCells(
const Particle*)
996 StoreObjPtr<EventLevelClusteringInfo> elci;
998 return (
double) elci->getNECLTriggerCells();
1001 double eclClusterEoP(
const Particle* part)
1003 double E = eclClusterE(part);
1004 if (part->hasExtraInfo(
"bremsCorrectedPhotonEnergy")) {
1005 E += part->getExtraInfo(
"bremsCorrectedPhotonEnergy");
1007 const double p = part->getMomentumMagnitude();
1012 double eclClusterOnlyInvariantMass(
const Particle* part)
1014 int nDaughters = part->getNDaughters();
1015 ROOT::Math::PxPyPzEVector sum;
1017 if (nDaughters < 1) {
1018 return part->getMass();
1020 int nClusterDaughters = 0;
1021 std::stack<const Particle*> stacked;
1023 while (!stacked.empty()) {
1024 const Particle* current = stacked.top();
1027 const ECLCluster* cluster = current->getECLCluster();
1030 nClusterDaughters ++;
1031 ClusterUtils clutls;
1032 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, clusterBit);
1035 const std::vector<Particle*> daughters = current->getDaughters();
1036 nDaughters = current->getNDaughters();
1037 for (
int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
1038 stacked.push(daughters[iDaughter]);
1043 if (nClusterDaughters < 1) {
1044 B2WARNING(
"There are no clusters amongst the daughters of the provided particle!");
1047 B2DEBUG(10,
"Number of daughters with cluster associated = " << nClusterDaughters);
1054 std::string cutString =
"";
1055 if (arguments.size() > 0) {
1056 cutString = arguments[0];
1060 std::string photonlistname =
"gamma:all";
1061 if (arguments.size() > 1) {
1062 photonlistname = arguments[1];
1065 std::string tracklistname =
"e-:all";
1066 if (arguments.size() > 2) {
1067 tracklistname = arguments[2];
1070 auto func = [cut, photonlistname, tracklistname](
const Particle * particle) ->
double {
1074 B2WARNING(
"The variable photonHasOverlap is supposed to be calculated for photons. Returning NaN.");
1078 StoreObjPtr<ParticleList> photonlist(photonlistname);
1079 if (!(photonlist.isValid()))
1081 B2WARNING(
"The provided particle list " << photonlistname <<
" does not exist."
1082 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1087 B2WARNING(
"The list " << photonlistname <<
" does not contain photons."
1088 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1092 StoreObjPtr<ParticleList> tracklist(tracklistname);
1093 if (!(tracklist.isValid()))
1095 B2WARNING(
"The provided particle list " << tracklistname <<
" does not exist."
1096 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1101 B2WARNING(
"The list " << tracklistname <<
" does not contain charged final state particles."
1102 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1106 double connectedRegionID = eclClusterConnectedRegionID(particle);
1107 int mdstSource = particle->getMdstSource();
1109 for (
unsigned int i = 0; i < photonlist->getListSize(); i++)
1111 const Particle* part = photonlist->getParticle(i);
1114 if (part->getMdstSource() == mdstSource) {
1119 if (!cut->check(part)) {
1123 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1128 for (
unsigned int i = 0; i < tracklist->getListSize(); i++)
1130 const Particle* part = tracklist->getParticle(i);
1133 if (!cut->check(part)) {
1137 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1147 VARIABLE_GROUP(
"ECL cluster related");
1148 REGISTER_VARIABLE(
"clusterEoP", eclClusterEoP, R
"DOC(
1149Returns ratio of the cluster energy `clusterE` over momentum :math:`p`.
1152 The cluster energy is already corrected for Bremsstrahlung.
1155 REGISTER_VARIABLE("clusterReg", eclClusterDetectionRegion, R
"DOC(
1156Returns an integer code representing the ECL region for the cluster:
1158- 1: forward, 2: barrel, 3: backward
1159- 11: between forward endcap and barrel, 13: between backward endcap and barrel
1160- 0: outside the ECL acceptance region
1163 REGISTER_VARIABLE("clusterDeltaLTemp", eclClusterDeltaL, R
"DOC(
1164Returns the :math:`\Delta L` for the cluster shape as defined below.
1166First, the cluster direction is constructed by calculating the weighted average of the orientation
1167for the crystals in the cluster. The POCA of the vector with this direction originating from the
1168cluster center and an extrapolated track can be used to the calculate the shower
1169depth. :math:`\Delta L` is then defined as the distance between this intersection and the cluster center.
1172 This distance is calculated on the reconstruction level and is temporarily
1173 included in mdst for investigation purposes. If it is found
1174 that it is not crucial for physics analyses then this variable will be removed
1175 in future releases. So keep in mind that this variable might be removed in the future.
1178 Please read `this <importantNoteECL>` first.
1180 - Lower limit: :math:`-250.0`
1181 - Upper limit: :math:`250.0`
1182 - Precision: :math:`10` bit
1185 REGISTER_VARIABLE("minC2TDist", eclClusterIsolation, R"DOC(
1186Returns the distance between the cluster and its nearest track.
1188For all tracks in the event, the distance between each of their extrapolated hits in the ECL and the ECL shower
1189position is calculated, and the overall smallest distance is returned. If there are no extrapolated hits found in the ECL
1190for the event, ``NaN`` will be returned. The track array index of the track that is closest to the cluster can be
1191retrieved using `minC2TDistID`.
1194 Please read `this <importantNoteECL>` first.
1196 - Lower limit: :math:`0.0`
1197 - Upper limit: :math:`250.0`
1198 - Precision: :math:`10` bit
1201 REGISTER_VARIABLE("minC2TDistID", eclClusterIsolationID, R"DOC(
1202Returns the track array index of the nearest track to the cluster. The nearest track is calculated
1203using the `minC2TDist` variable.
1206 REGISTER_METAVARIABLE("minC2TDistVar(variable,particleList='pi-:all')", eclClusterIsolationVar, R
"DOC(
1207Returns the value of your chosen variable for the track nearest to the given cluster as calculated by
1210The first parameter ``variable`` is the variable name e.g. `nCDCHits`, while the second (optional) parameter ``particleList``
1211is the particle list name which will be used in the calculation of `minC2TDist`. The default particle list used
1214)DOC", Manager::VariableDataType::c_double);
1215 REGISTER_VARIABLE("clusterE", eclClusterE, R
"DOC(
1216Returns the cluster energy corrected for leakage and background.
1219 We only store clusters with :math:`E > 20\,` MeV.
1221.. topic:: Calculating Photon Energy
1223 The raw photon energy is given by the weighted sum of all crystal energies within the cluster.
1224 The weights per crystals are :math:`\leq 1` after cluster energy splitting in the case of overlapping
1225 clusters. The number of crystals that are included in the sum depends on a initial energy estimation
1226 and local beam background levels for the highest energy crystal. The crystal number is optimized to minimize
1227 the resolution of photons. Photon energy distributions always show a low energy tail
1228 due to unavoidable longitudinal and transverse leakage. The peak position of the photon energy distributions are
1229 corrected to match the true photon energy in MC. The corrections applied include:
1231 - Leakage correction: using MC samples of mono-energetic single photon, a correction factor
1232 :math:`f` as function of the reconstructed detector position, photon energy and beam background level
1233 is determined via :math:`f = \frac{\text{peak_reconstructed}}{\text{energy_true}}`
1235 - Cluster energy calibration (data only): to reach the target precision of :math:`< 1.8\%` energy
1236 resolution for high energetic photons, the remaining difference between MC and data is calibrated
1237 using kinematically fits to muon pairs
1239 It is important to note that after perfect leakage corrections and cluster energy calibrations,
1240 the :math:`\pi^{0}` mass peak will be shifted slightly to smaller values than the PDG average
1241 due to the low energy tails of photons.
1244 Please read `this <importantNoteECL>` first.
1246 - Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV in the lab frame)
1247 - Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV in the lab frame)
1248 - Precision: :math:`18` bit
1251 REGISTER_VARIABLE("clusterErrorE", eclClusterErrorE, R"DOC(
1252Returns the uncertainty on the cluster energy. It is derived from
1253a background level and energy-dependent error tabulation.
1256 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1257 a directly-reconstructed quantity. For more information please see the
1258 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1262 REGISTER_VARIABLE("clusterErrorPhi", eclClusterErrorPhi, R"DOC(
1263Returns the uncertainty on the phi angle of the cluster. It is derived from
1264a background level and energy-dependent error tabulation.
1267 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1268 a directly-reconstructed quantity. For more information please see the
1269 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1273 REGISTER_VARIABLE("clusterErrorTheta", eclClusterErrorTheta, R"DOC(
1274Returns the uncertainty on the theta angle of the cluster. It is derived from
1275a background level and energy-dependent error tabulation.
1278 This variable should not be used a selection variable or in an MVA for photon identification as it is not
1279 a directly-reconstructed quantity. For more information please see the
1280 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1284 REGISTER_VARIABLE("clusterR", eclClusterR, R"DOC(
1285Returns the distance of the cluster centroid from :math:`(0,0,0)`.
1288 This variable is not recommended for use in analyses as they are difficult to interpret. For more information please see the
1289 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1293 REGISTER_VARIABLE("clusterPhi", eclClusterPhi, R"DOC(
1294Returns the azimuthal angle :math:`\phi` of the cluster. This is generally not equal
1295to the azimuthal angle of the photon.
1297.. topic:: Calculating Cluster Direction
1299 The direction of a cluster is given by the connecting line from :math:`\,(0,0,0)\,` to
1300 cluster centroid position in the ECL. The centroid position is calculated using up to 21 crystals
1301 (as 5x5 grid excluding corners) after the crystal energies are split in the case of overlapping clusters.
1302 The centroid position is the logarithmically weighted average of all crystals evaluated at the
1303 crystal centers. The centroid is generally biased towards the centers of the highest energetic
1304 crystal. This effect is larger for low energy photons. Beam backgrounds slightly decrease the
1305 position resolution, and mainly effects the low energy photons.
1307 Unlike for charged tracks, the uncertainty (covariance) of the photon direction is not determined
1308 based on individual cluster properties but taken from MC-based parametrizations of the resolution
1309 as function of true photon energy, true photon direction and beam background level.
1312 Please read `this <importantNoteECL>` first.
1314 - Lower limit: :math:`-\pi`
1315 - Upper limit: :math:`\pi`
1316 - Precision: :math:`16` bit
1319 REGISTER_VARIABLE("clusterConnectedRegionID", eclClusterConnectedRegionID, R"DOC(
1320Returns connected region ID for the cluster.
1322 REGISTER_VARIABLE("clusterTheta", eclClusterTheta, R
"DOC(
1323Returns the polar angle :math:`\theta` of the cluster. This is generally not equal
1324to the polar angle of the photon.
1326.. topic:: Calculating Cluster Direction
1328 The direction of a cluster is given by the connecting line from :math:`\,(0,0,0)\,` to
1329 cluster centroid position in the ECL. The centroid position is calculated using up to 21 crystals
1330 (as 5x5 grid excluding corners) after the crystal energies are split in the case of overlapping clusters.
1331 The centroid position is the logarithmically weighted average of all crystals evaluated at the
1332 crystal centers. The centroid is generally biased towards the centers of the highest energetic
1333 crystal. This effect is larger for low energy photons. Beam backgrounds slightly decrease the
1334 position resolution, and mainly effects the low energy photons.
1336 Unlike for charged tracks, the uncertainty (covariance) of the photon direction is not determined
1337 based on individual cluster properties but taken from MC-based parametrizations of the resolution
1338 as function of true photon energy, true photon direction and beam background level.
1341 Please read `this <importantNoteECL>` first.
1343 - Lower limit: :math:`0.0`
1344 - Upper limit: :math:`\pi`
1345 - Precision: :math:`16` bit
1348 REGISTER_VARIABLE("clusterTiming", eclClusterTiming, R"DOC(
1349Returns the time of the cluster. This is calculated **differently** in Belle and Belle II. Please
1350read their definitions below.
1352.. topic:: In Belle II
1354 It is calculated as the cluster time minus the `eventT0`. The cluster time is obtained by a fit to
1355 the recorded waveform of the highest energy crystal in the cluster. For a cluster produced by a
1356 particle from the IP, the cluster time should be consistent with `eventT0` within the uncertainties
1357 following all calibrations and corrections. For MC, note that the calibrations and corrections are not
1358 fully simulated. In order to see if the waveform fit fails, see `clusterHasFailedTiming`.
1361 Please read `this <importantNoteECL>` first.
1363 - Lower limit: :math:`-1000.0`
1364 - Upper limit: :math:`1000.0`
1365 - Precision: :math:`12` bit
1369 It is equal to the trigger cell (TC) time corresponding to the cluster. This information is only
1370 available in Belle data since experiment 31, and not available in Belle MC. Clusters produced at the IP
1371 in time with the event have a TC time in the range of 9000 - 11000. More information can be found in the
1372 Appendix of Belle note 831.
1375 In case this variable is obtained from Belle data that is stored in Belle II mdst/udst format, it will be truncated to:
1377 - Lower limit: :math:`-1000.0`
1378 - Upper limit: :math:`1000.0`
1379 - Precision: :math:`12` bit
1382 REGISTER_VARIABLE("clusterHasFailedTiming", eclClusterHasFailedTiming, R"DOC(
1383Status bit indicating if the waveform fit for the `clusterTiming` calculation has failed.
1385 REGISTER_VARIABLE("clusterErrorTiming", eclClusterErrorTiming, R
"DOC(
1386Returns the cluster timing uncertainty which is equal to the :math:`dt99` value as defined below. Very large
1387values of :math:`dt99` are an indication of a failed waveform fit for the cluster.
1389The timing distribution for each cluster is non-Gaussian and so the value :math:`dt99` is stored where
1390:math:`|\text{timing}| / \text{dt99} < 1` is designed to give a :math:`99\%` timing efficiency for
1391true photons from the IP. (This definition results in an efficiency that is approximately flat in energy
1392and independent of the beam background level). The :math:`dt99` value stored is determined using MC with a
1393parametrisation that depends on the true energy deposition in the highest energetic crystal and the
1394local beam background level in that crystal.
1397 This variable should should only be used for relative timing selections as it is not
1398 a directly-reconstructed quantity. For more information please see the
1399 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1403 Please read `this <importantNoteECL>` first.
1405 - Lower limit: :math:`0.0`
1406 - Upper limit: :math:`1000.0`
1407 - Precision: :math:`12` bit
1410 REGISTER_VARIABLE("clusterHasFailedErrorTiming", eclClusterHasFailedErrorTiming, R"DOC(
1411Status bit indicating if the calculation of `clusterErrorTiming` has failed due to a failed
1414 REGISTER_VARIABLE("clusterHighestE", eclClusterHighestE, R
"DOC(
1415Returns the energy of the highest energetic crystal in the cluster after reweighting.
1418 This variable is not recommended for use in analyses as they are difficult to interpret. For more information please see the
1419 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1423 Please read `this <importantNoteECL>` first.
1425 - Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV)
1426 - Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV)
1427 - Precision: :math:`18` bit
1430 REGISTER_VARIABLE("clusterCellID", eclClusterCellId,
1431 "Returns the cell ID of the crystal with highest energy in the cluster.");
1432 REGISTER_VARIABLE("clusterThetaID", eclClusterThetaId, R"DOC(
1433Returns the :math:`\theta` ID of the crystal with highest energy in the cluster. There are
143469 :math:`\theta` IDs in total covering the entire ECL acceptance. The mapping between cell ID number
1435and :math:`\theta` ID can be found in the source code linked to the right of this variable description.
1437 REGISTER_VARIABLE("clusterPhiID", eclClusterPhiId, R
"DOC(
1438Returns the :math:`\phi` ID of the crystal with highest energy in the cluster.
1439While :math:`\theta` ID indicates the specific ring of the calorimeter,
1440:math:`\phi` ID indicates a position of a crystal in that ring. When facing
1441towards the direction of an electron beam, :math:`\phi` IDs go clockwise, with
14420 corresponding to the crystal closest to the outer side of the main ring tunnel.
1444.. admonition:: Diagram
1445 :class: dropdown xhint stacked
1447 .. code-block:: text
1449 phi_id = (nring/4) phi_id = (nring/4) - 1
1452 .... . . ││.. .. . .
1453 .. . . .... ││ ..... . . . .
1461 nring/2 ───── (towards the ───── phi_id = 0
1462 nring/2 - 1 ───── electron beam) ───── phi_id = (nring - 1)
1470 ... . . . .. ││. .. . .... .
1471 . . . . .││ ... ... .
1474 phi_id = (nring*3/4) - 1 phi_id = (nring/4) - 1
1476 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>`_.
1479 REGISTER_VARIABLE("clusterE1E9", eclClusterE1E9, R
"DOC(
1480Returns the ratio of the energy in the central crystal (:math:`E_1`) to the total energy in the
14813x3 crystal grid around the central crystal (:math:`E_9`). Since :math:`E_1 \leq E_9`, this ratio is
1482:math:`\leq 1` and tends towards larger values for photons and smaller values for hadrons.
1485 Please read `this <importantNoteECL>` first.
1487 - Lower limit: :math:`0.0`
1488 - Upper limit: :math:`1.0`
1489 - Precision: :math:`10` bit
1492 REGISTER_VARIABLE("clusterE9E25", eclClusterE9E25, R
"DOC(
1493Returns `clusterE9E21`. This variable is kept for backwards compatibility.
1495 REGISTER_VARIABLE("clusterE9E21", eclClusterE9E21, R
"DOC(
1496Returns the ratio of the total energy in the 3x3 crystal grid around the central
1497crystal (:math:`E_9`) to the total energy in the 5x5 crystal grid around the central crystal
1498excluding the corners (:math:`E_{21}`). Since :math:`E_9 \leq E_{21}`, this ratio is :math:`\leq 1` and tends towards larger
1499values for photons and smaller values for hadrons.
1502 Please read `this <importantNoteECL>` first.
1504 - Lower limit: :math:`0.0`
1505 - Upper limit: :math:`1.0`
1506 - Precision: :math:`10` bit
1509 REGISTER_VARIABLE("clusterAbsZernikeMoment40", eclClusterAbsZernikeMoment40, R
"DOC(
1510Returns absolute value of the 40th Zernike moment :math:`|Z_{40}|`. An explanation on this shower
1511shape variable is in the description for the `clusterZernikeMVA` variable.
1514 Please read `this <importantNoteECL>` first.
1516 - Lower limit: :math:`0.0`
1517 - Upper limit: :math:`1.7`
1518 - Precision: :math:`10` bit
1521 REGISTER_VARIABLE("clusterAbsZernikeMoment51", eclClusterAbsZernikeMoment51, R
"DOC(
1522Returns absolute value of the 51st Zernike moment :math:`|Z_{51}|`. An explanation on this shower
1523shape variable is in the description for the `clusterZernikeMVA` variable.
1526 Please read `this <importantNoteECL>` first.
1528 - Lower limit: :math:`0.0`
1529 - Upper limit: :math:`1.2`
1530 - Precision: :math:`10` bit
1533 REGISTER_VARIABLE("clusterZernikeMVA", eclClusterZernikeMVA, R
"DOC(
1534Returns output of an MVA trained to use eleven Zernike moments of the cluster.
1536Zernike moments are calculated for each shower in the plane perpendicular to
1537the shower direction via
1540 |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|
1542where :math:`n, m` are the integers, :math:`i` runs over each crystal in the shower,
1543:math:`E_{i}` is the energy of the i-th crystal in the shower,
1544:math:`R_{nm}` is a polynomial of degree :math:`n`,
1545:math:`\rho_{i}` is the radial distance of the :math:`i`-th crystal in the perpendicular plane,
1546and :math:`\alpha_{i}` is the polar angle of the :math:`i`-th crystal in the perpendicular plane.
1547As a crystal can be related to more than one shower, :math:`w_{i}` is the fraction of the
1548energy of the :math:`i`-th crystal associated with the shower.
1551 This variable is sensitive to other nearby particles and so cluster isolation properties shoud
1552 always be checked. For more information please see the
1553 `ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_
1557 - More details about the implementation can be found in `BELLE2-NOTE-TE-2017-001 <https://docs.belle2.org/record/454?ln=en>`_ .
1558 - More details about Zernike polynomials can be found on `Wikipedia <https://en.wikipedia.org/wiki/Zernike_polynomials>`_ .
1561 Please read `this <importantNoteECL>` first.
1563 - Lower limit: :math:`0.0`
1564 - Upper limit: :math:`1.0`
1565 - Precision: :math:`10` bit
1568 REGISTER_VARIABLE("clusterSecondMoment", eclClusterSecondMoment, R
"DOC(
1569Returns the second moment :math:`S` of the cluster. This is mainly implemented for reconstructing high a
1570energy :math:`\pi^0` originating from merged clusters.
1575 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}}
1577where :math:`E_{i} = (E_0, E_1, ...)` are the crystal energies sorted by descending energy, :math:`w_{i}` is
1578the fraction of the crystal energy associated with the shower, and :math:`r_{i}` is the distance of
1579the :math:`i`-th digit to the shower center projected onto a plane perpendicular to the
1580shower axis. :math:`S_{0}(\theta)` normalizes :math:`S` to 1 for isolated photons.
1583 Please read `this <importantNoteECL>` first.
1585 - Lower limit: :math:`0.0`
1586 - Upper limit: :math:`40.0`
1587 - Precision: :math:`10` bit
1589)DOC","dimensionless");
1590 REGISTER_VARIABLE("clusterLAT", eclClusterLAT, R"DOC(
1591Returns lateral energy distribution of the shower. For radially-symmetric electromagnetic showers, this
1592variable peaks at :math:`\approx 0.3`. It is larger for hadronic particles and electrons with a nearby relative
1593or Bremsstrahlung photon.
1595It is defined as following:
1598 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}}
1600where :math:`E_{i} = (E_0, E_1, ...)` are the crystal energies sorted by descending energy, :math:`w_{i}` is
1601the fraction of the crystal energy associated with the shower, :math:`r_{i}` is the distance of
1602the :math:`i`-th digit to the shower center projected onto a plane perpendicular to the shower axis,
1603and :math:`r_{0} \approx 5\,cm` is the average distance between two crystal centres.
1606 This variable peaks around 0.3 for symmetrical electromagnetic showers and is larger for hadronic
1607 showers and electrons with a close-by radiative or Bremsstrahlung photon.
1610 Please read `this <importantNoteECL>` first.
1612 - Lower limit: :math:`0.0`
1613 - Upper limit: :math:`1.0`
1614 - Precision: :math:`10` bit
1617 REGISTER_VARIABLE("clusterNHits", eclClusterNHits, R
"DOC(
1618Returns sum of weights :math:`w_{i}` (:math:`w_{i} \leq 1`) of all crystals in the cluster.
1619For non-overlapping clusters this is equal to the number of crystals in the cluster. However, in the case
1620of overlapping clusters where individual crystal energies are split among them, this can be a non-integer value.
1623 If fractional weights are not of interest, this value should be cast to the nearest `int`
1626 Please read `this <importantNoteECL>` first.
1628 - Lower limit: :math:`0.0`
1629 - Upper limit: :math:`200.0`
1630 - Precision: :math:`10` bit
1633 REGISTER_VARIABLE("clusterTrackMatch", eclClusterTrackMatched, R
"DOC(
1634Returns 1.0 if at least one reconstructed charged track is matched to the cluster. Track-cluster
1635matching is briefly described below.
1637Every reconstructed track is extrapolated to the ECL. Every ECL crystal that is crossed by
1638the extrapolated track is marked. Following this, every cluster that contains a marked crystal
1639becomes associated with the original track. The current algorithm matches only one cluster to a
1640track but can match multiple tracks to the same cluster. In the latter case, all tracks matched
1641to the same cluster will return the same cluster variables e.g. all will have the same `clusterE`.
1643 REGISTER_VARIABLE("nECLClusterTrackMatches", nECLClusterTrackMatches, R
"DOC(
1644Returns the number of tracks matched to the cluster. For more information on track-cluster matching
1645please see the description for `clusterTrackMatch`.
1647For the clusters of neutral particles, this should always return 0. If there is no cluster ``NaN`` is
1650 REGISTER_VARIABLE("clusterHasPulseShapeDiscrimination", eclClusterHasPulseShapeDiscrimination, R
"DOC(
1651Status bit to indicate if the waveforms from the cluster pass the requirements for computing pulse
1652shape discrimination variables such as `clusterPulseShapeDiscriminationMVA`.
1654.. topic:: Pulse Shape Information Requirements
1656 The exact requirements for a cluster have pulse shape information are as follows:
1657 - there is at least one crystal with energy above 30 MeV for phase 2 data or 50 MeV for phase 3 data
1658 (this is the energy threshold requirement for saving waveforms offline)
1659 - one of the waveforms for the cluster must have a good :math:`\chi^2` fit
1662 REGISTER_VARIABLE("beamBackgroundSuppression", beamBackgroundSuppression, R
"DOC(
1663Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from beam background clusters.
1664Class 1 is for true photon clusters while class 0 is for beam background clusters.
1666The MVA has been trained using MC and the features used, in decreasing importance, are:
1669- `clusterPulseShapeDiscriminationMVA`
1672- `clusterZernikeMVA` (this has been removed starting from the MC16 training)
1676 For the correct usage, please see
1677 the `Performance Recommendations Webpage <https://belle2.pages.desy.de/performance/recommendations/>`_.
1681 Please cite `this proceeding <https://inspirehep.net/literature/2785196>`_ if using this tool.
1683 REGISTER_VARIABLE("fakePhotonSuppression", fakePhotonSuppression, R
"DOC(
1684Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from fake photon clusters.
1685Class 1 is for true photon clusters while class 0 is for fake photon clusters.
1687The MVA has been trained using MC and the features, in decreasing importance, are:
1689- `clusterPulseShapeDiscriminationMVA`
1694- `clusterZernikeMVA` (this has been removed starting from the MC16 training)
1697 For the correct usage, please see
1698 the `Performance Recommendations Webpage <https://belle2.pages.desy.de/performance/recommendations/>`_.
1701 Please cite `this proceeding <https://inspirehep.net/literature/2785196>`_ if using this tool.
1704 REGISTER_VARIABLE("hadronicSplitOffSuppression", hadronicSplitOffSuppression, R
"DOC(
1705Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from hadronic splitoff clusters.
1708- 1 for true photon clusters
1709- 0 for hadronic splitoff clusters
1711The MVA has been trained using samples of signal photons and hadronic splitoff photons coming from MC.
1712The features used are (in decreasing order of significance):
1714- `clusterPulseShapeDiscriminationMVA`
1716- `clusterZernikeMVA`
1720- `clusterSecondMoment`
1723 MAKE_DEPRECATED("hadronicSplitOffSuppression",
true,
"light-2302-genetta", R
"DOC(
1724 Use the variable `fakePhotonSuppression` instead which is maintained and uses the latest weight files.
1726 REGISTER_VARIABLE("clusterKlId", eclClusterKlId, R
"DOC(
1727Returns MVA classifier that uses ECL clusters variables to discriminate Klong clusters from em background.
1736 REGISTER_VARIABLE("clusterPulseShapeDiscriminationMVA", eclPulseShapeDiscriminationMVA, R
"DOC(
1737Returns the output of an MVA classifier that uses pulse shape information to discriminate between electromagnetic
1738and hadronic showers. Class 1 is for electromagnetic showers while class 0 is for hadronic showers.
1741 Please cite `this paper <https://inspirehep.net/literature/1807894>`_ if using this tool.
1744 REGISTER_VARIABLE("clusterNumberOfHadronDigits", eclClusterNumberOfHadronDigits, R
"DOC(
1745Returns the number of hadron digits in the cluster based on pulse shape information. This is the weight sum of cluster digits
1746that have :math:`> 3\,` MeV for the hadronic scintillation component. The digits must have pulse shape information available
1747(see `clusterHasPulseShapeDiscrimination` for more information).
1750 This is a purely technical flag and should not be used for any physics-level selection
1753 Please read `this <importantNoteECL>` first.
1755 - Lower limit: :math:`0.0`
1756 - Upper limit: :math:`255.0`
1757 - Precision: :math:`18` bit
1760 REGISTER_VARIABLE("clusterClusterID", eclClusterId, R
"DOC(
1761Returns the ID the cluster within the connected region to which it belongs.
1763 REGISTER_VARIABLE("clusterHasNPhotons", eclClusterHasNPhotonsHypothesis, R
"DOC(
1764Returns 1.0 if the cluster has the "N photons" hypothesis (historically called "N1"),
17650.0 if not, and ``NaN`` if no cluster is associated to the particle.
1767 REGISTER_VARIABLE("clusterHasNeutralHadron", eclClusterHasNeutralHadronHypothesis, R
"DOC(
1768Returns 1.0 if the cluster has the "neutral hadrons" hypothesis (historically called "N2"),
17690.0 if not, and ``NaN`` if no cluster is associated to the particle.
1771 REGISTER_VARIABLE("eclExtTheta", eclExtTheta, R
"DOC(
1772Returns the :math:`\theta` angle of the extrapolated track associated to the cluster (if any).
1775 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1778 REGISTER_VARIABLE("eclExtPhi", eclExtPhi, R"DOC(
1779Returns the :math:`\phi` angle of the extrapolated track associated to the cluster (if any).
1782 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1785 REGISTER_VARIABLE("eclExtPhiId", eclExtPhiId, R"DOC(
1786Returns the :math:`\phi` ID of the extrapolated track associated to the cluster (if any).
1789 This requires the ``ECLTrackCalDigitMatch`` module to be executed.
1792 REGISTER_VARIABLE("weightedAverageECLTime", weightedAverageECLTime, R
"DOC(
1793Returns the weighted average time of all clusters corresponding to daughter particles of the provided particle.
1796 REGISTER_VARIABLE(
"maxWeightedDistanceFromAverageECLTime", maxWeightedDistanceFromAverageECLTime, R
"DOC(
1797Returns maximum weighted distance between time of the cluster of a photon and the ECL average time, amongst
1798the clusters (neutrals) and matched clusters (charged) of daughters (of all generations) of the provided particle.
1801 REGISTER_VARIABLE(
"clusterMdstIndex", eclClusterMdstIndex, R
"DOC(
1802Returns the ``StoreArray`` index of the cluster mDST object. This can be useful for track-based particles that are matched to an cluster.
1805 REGISTER_VARIABLE("nECLOutOfTimeCrystals", nECLOutOfTimeCrystals, R
"DOC(
1806**[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
18077 MeV are are counted.
1810 REGISTER_VARIABLE("nECLOutOfTimeCrystalsFWDEndcap", nECLOutOfTimeCrystalsFWDEndcap, R
"DOC(
1811**[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
18127 MeV are are counted.
1815 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBarrel", nECLOutOfTimeCrystalsBarrel, R
"DOC(
1816**[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
18177 MeV are are counted.
1820 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBWDEndcap", nECLOutOfTimeCrystalsBWDEndcap, R
"DOC(
1821**[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
18227 MeV are are counted.
1825 REGISTER_VARIABLE("nRejectedECLShowers", nRejectedECLShowers, R
"DOC(
1826**[Eventbased]** Returns the number of ECL showers that do not become clusters. If the number exceeds 255, the variable is set to 255.
1829 REGISTER_VARIABLE("nRejectedECLShowersFWDEndcap", nRejectedECLShowersFWDEndcap, R
"DOC(
1830**[Eventbased]** Returns the number of ECL showers in the forward endcap that do not become clusters.
1831If the number exceeds 255, the variable is set to 255.
1834 REGISTER_VARIABLE("nRejectedECLShowersBarrel", nRejectedECLShowersBarrel, R
"DOC(
1835**[Eventbased]** Returns the number of ECL showers in the barrel that do not become clusters.
1836If the number exceeds 255, the variable is set to 255.
1839 REGISTER_VARIABLE("nRejectedECLShowersBWDEndcap", nRejectedECLShowersBWDEndcap, R
"DOC(
1840**[Eventbased]** Returns the number of ECL showers in the backward endcap that do not become clusters.
1841If the number exceeds 255, the variable is set to 255.
1844 REGISTER_VARIABLE("nKLMMultistripHitsFWDEndcap", nKLMMultistripHitsFWDEndcap, R
"DOC(
1845**[Eventbased]** Returns the number of multi-strip hits in the KLM forward endcap associated with the ECL cluster.
1848 REGISTER_VARIABLE("nKLMMultistripHitsBarrel", nKLMMultistripHitsBarrel, R
"DOC(
1849**[Eventbased]** Returns the number of multi-strip hits in the KLM barrel associated with the ECL cluster.
1852 REGISTER_VARIABLE("nKLMMultistripHitsBWDEndcap", nKLMMultistripHitsBWDEndcap, R
"DOC(
1853**[Eventbased]** Returns the number of multi-strip hits in the KLM backward endcap associated with the ECL cluster.
1856 REGISTER_VARIABLE("nKLMMultistripHits", nKLMMultistripHits, R
"DOC(
1857**[Eventbased]** Returns the number of multi-strip hits in the KLM associated with the ECL cluster.
1860 REGISTER_VARIABLE("nECLShowersFWDEndcap", nECLShowersFWDEndcap, R
"DOC(
1861**[Eventbased]** Returns the number of ECL showers in the forward endcap.
1864 REGISTER_VARIABLE("nECLShowersBarrel", nECLShowersBarrel, R
"DOC(
1865**[Eventbased]** Returns the number of ECL showers in the barrel.
1868 REGISTER_VARIABLE("nECLShowersBWDEndcap", nECLShowersBWDEndcap, R
"DOC(
1869**[Eventbased]** Returns the number of ECL showers in the backward endcap.
1872 REGISTER_VARIABLE("nECLShowers", nECLShowers, R
"DOC(
1873**[Eventbased]** Returns the number of ECL showers.
1876 REGISTER_VARIABLE("nECLLocalMaximumsFWDEndcap", nECLLocalMaximumsFWDEndcap, R
"DOC(
1877**[Eventbased]** Returns the number of Local Maximums in the ECL forward endcap.
1880 REGISTER_VARIABLE("nECLLocalMaximumsBarrel", nECLLocalMaximumsBarrel, R
"DOC(
1881**[Eventbased]** Returns the number of Local Maximums in the ECL barrel.
1884 REGISTER_VARIABLE("nECLLocalMaximumsBWDEndcap", nECLLocalMaximumsBWDEndcap, R
"DOC(
1885**[Eventbased]** Returns the number of Local Maximums in the ECL backward endcap.
1888 REGISTER_VARIABLE("nECLLocalMaximums", nECLLocalMaximums, R
"DOC(
1889**[Eventbased]** Returns the number of Local Maximums in the ECL.
1892 REGISTER_VARIABLE("nECLTriggerCellsFWDEndcap", nECLTriggerCellsFWDEndcap, R
"DOC(
1893**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the forward endcap.
1896 REGISTER_VARIABLE("nECLTriggerCellsBarrel", nECLTriggerCellsBarrel, R
"DOC(
1897**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the barrel.
1900 REGISTER_VARIABLE("nECLTriggerCellsBWDEndcap", nECLTriggerCellsBWDEndcap, R
"DOC(
1901**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV in the backward endcap.
1904 REGISTER_VARIABLE("nECLTriggerCells", nECLTriggerCells, R
"DOC(
1905**[Eventbased]** Returns the number of ECL trigger cells above 100 MeV.
1908 REGISTER_VARIABLE("eclClusterOnlyInvariantMass", eclClusterOnlyInvariantMass, R
"DOC(
1909Returns the invariant mass calculated from all neutral and track-matched cluster daughters using the cluster 4-momenta.
1910This is primarily used for ECL-based dark sector physics and debugging track-cluster matching.
1912)DOC","GeV/:math:`\\text{c}^2`");
1914 REGISTER_METAVARIABLE("photonHasOverlap(cutString, photonlistname, tracklistname)", photonHasOverlap, R"DOC(
1915Returns ``True`` if the connection region of the cluster is shared by another cluster. Both neutral and track-matched clusters
1918A ``cutString`` can be provided in order to ignore clusters that do not satisfy a given criteria. By default, the particle lists
1919``gamma:all`` and ``e-:all`` are used to check for neutral and track-matched clusters respectively. However, this can be customised
1920by using the ``photonlistname`` and ``tracklistname`` parameters. If ``gamma:all`` or ``e-:all`` does not exist or if this variable is applied
1921to a particle that is not a photon, ``NaN`` will be returned.
1922)DOC", Manager::VariableDataType::c_double);
1924 REGISTER_VARIABLE("clusterUncorrE", eclClusterUncorrectedE, R
"DOC(
1925Returns the uncorrected energy of the cluster.
1928 This variable should not be used for any physics analysis but only for ECL or calibration studies.
1932 REGISTER_VARIABLE("distanceToMcKl",distanceToMcKl,R"DOC(
1933Returns the distance to the nearest truth-matched :math:`K_L^0` particle that has been extrapolated to the cluster.
1936 This requires the `getNeutralHadronGeomMatches` function to be used.
1940 REGISTER_VARIABLE(
"distanceToMcNeutron",distanceToMcNeutron,R
"DOC(
1941Returns the distance to the nearest truth-matched (anti)neutron particle that has been extrapolated to the cluster.
1944 This requires the `getNeutralHadronGeomMatches` function to be used.
1948 REGISTER_VARIABLE(
"mdstIndexMcKl",mdstIndexMcKl,R
"DOC(
1949Returns the ``StoreArray`` index of the mDST object corresponding to the nearest truth-matched :math:`K_L^0` particle as determined
1950during the calculation of the `distanceToMcKl` variable.
1953 This requires the `getNeutralHadronGeomMatches` function to be used.
1957 REGISTER_VARIABLE("mdstIndexMcNeutron",mdstIndexMcNeutron,R
"DOC(
1958Returns the ``StoreArray`` index of the mDST object corresponding to the nearest truth-matched (anti)neutron particle as determined
1959during the calculation of the `distanceToMcKl` variable.
1962 This requires the `getNeutralHadronGeomMatches` function to be used.
1964 REGISTER_VARIABLE("clusterTimeNorm90", eclClusterTimeNorm90,
1966 Returns cluster's timing normalized such that :math:`90\%` of real photons will
1967 have :math:`|\text{clusterTimeNorm90}| < 1`. Normalization depends on energy, background
1968 level, and cellID, and differs for data and MC. Valid only for crystals within the CDC acceptance, :math:`161 <= |\text{clusterCellID}| <= 8608`. Note: the required payloads are stored in the neutrals global tag. Please find the latest recommendation using :ref:`b2help-recommendation`.)DOC",
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.