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();
132 double eclPulseShapeDiscriminationMVA(
const Particle* particle)
134 const ECLCluster* cluster = particle->getECLCluster();
136 if (eclClusterHasPulseShapeDiscrimination(particle)) {
137 return cluster->getPulseShapeDiscriminationMVA();
145 double eclClusterNumberOfHadronDigits(
const Particle* particle)
148 const ECLCluster* cluster = particle->getECLCluster();
150 if (eclClusterHasPulseShapeDiscrimination(particle)) {
151 return cluster->getNumberOfHadronDigits();
158 double eclClusterDetectionRegion(
const Particle* particle)
161 const ECLCluster* cluster = particle->getECLCluster();
163 return cluster->getDetectorRegion();
168 double eclClusterIsolation(
const Particle* particle)
171 const ECLCluster* cluster = particle->getECLCluster();
173 auto minDist = cluster->getMinTrkDistance();
180 double eclClusterIsolationID(
const Particle* particle)
183 const ECLCluster* cluster = particle->getECLCluster();
185 return cluster->getMinTrkDistanceID();
192 if (arguments.size() > 2 or arguments.size() == 0)
193 B2FATAL(
"Wrong number of arguments (2 required) for meta variable minC2TDistVar");
194 std::string listName =
"pi-:all";
195 std::string variableName = arguments[0];
196 if (arguments.size() == 2)
197 listName = arguments[1];
200 auto func = [listName, variableName](
const Particle * particle) ->
double {
201 StoreObjPtr<ParticleList> particleList(listName);
202 if (!(particleList.isValid()))
204 B2FATAL(
"Invalid Listname " << listName <<
" given to minC2TDistVar!");
207 const ECLCluster* cluster = particle->getECLCluster();
210 auto trackID = cluster->getMinTrkDistanceID();
213 for (
unsigned int i = 0; i < particleList->getListSize(); i++)
215 const Particle* listParticle = particleList->getParticle(i);
216 if (listParticle and listParticle->getTrack() and listParticle->getTrack()->getArrayIndex() == trackID) {
217 result = std::get<double>(var->function(listParticle));
226 double eclClusterConnectedRegionID(
const Particle* particle)
229 const ECLCluster* cluster = particle->getECLCluster();
231 return cluster->getConnectedRegionId();
236 double eclClusterDeltaL(
const Particle* particle)
239 const ECLCluster* cluster = particle->getECLCluster();
241 return cluster->getDeltaL();
246 double eclClusterErrorE(
const Particle* particle)
249 const ECLCluster* cluster = particle->getECLCluster();
252 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
253 return sqrt(fabs(EPhiThetaCov[0][0]));
258 double eclClusterUncorrectedE(
const Particle* particle)
261 const ECLCluster* cluster = particle->getECLCluster();
263 return cluster->getEnergyRaw();
268 double eclClusterE(
const Particle* particle)
272 const ECLCluster* cluster = particle->getECLCluster();
275 ROOT::Math::PxPyPzEVector p4Cluster = clutls.GetCluster4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
277 return frame.getMomentum(p4Cluster).E();
282 double eclClusterHighestE(
const Particle* particle)
285 const ECLCluster* cluster = particle->getECLCluster();
287 return cluster->getEnergyHighestCrystal();
292 double eclClusterCellId(
const Particle* particle)
295 const ECLCluster* cluster = particle->getECLCluster();
297 return cluster->getMaxECellId();
303 const std::array<int, 69> lastCellIDperThetaID{48, 96, 160, 224, 288, 384, 480, 576, 672, 768, 864,
304 1008, 1152, 1296, 1440, 1584, 1728, 1872, 2016, 2160, 2304, 2448,
305 2592, 2736, 2880, 3024, 3168, 3312, 3456, 3600, 3744, 3888, 4032,
306 4176, 4320, 4464, 4608, 4752, 4896, 5040, 5184, 5328, 5472, 5616,
307 5760, 5904, 6048, 6192, 6336, 6480, 6624, 6768, 6912, 7056, 7200,
308 7344, 7488, 7632, 7776, 7920, 8064, 8160, 8256, 8352, 8448, 8544,
311 double eclClusterThetaId(
const Particle* particle)
314 const ECLCluster* cluster = particle->getECLCluster();
316 int cellID = cluster->getMaxECellId();
317 return std::distance(lastCellIDperThetaID.begin(), std::lower_bound(lastCellIDperThetaID.begin(), lastCellIDperThetaID.end(),
323 double eclClusterPhiId(
const Particle* particle)
326 const ECLCluster* cluster = particle->getECLCluster();
328 int cellID = cluster->getMaxECellId();
332 int closestinlist = lastCellIDperThetaID[std::distance(lastCellIDperThetaID.begin(), std::lower_bound(lastCellIDperThetaID.begin(),
333 lastCellIDperThetaID.end(), cellID)) - 1];
334 return cellID - closestinlist - 1;
340 double eclClusterTiming(
const Particle* particle)
343 const ECLCluster* cluster = particle->getECLCluster();
345 return cluster->getTime();
350 double eclClusterHasFailedTiming(
const Particle* particle)
352 const ECLCluster* cluster = particle->getECLCluster();
354 return cluster->hasFailedFitTime();
359 double eclClusterErrorTiming(
const Particle* particle)
362 const ECLCluster* cluster = particle->getECLCluster();
364 return cluster->getDeltaTime99();
369 double eclClusterHasFailedErrorTiming(
const Particle* particle)
371 const ECLCluster* cluster = particle->getECLCluster();
373 return cluster->hasFailedTimeResolution();
378 double eclClusterTheta(
const Particle* particle)
382 const ECLCluster* cluster = particle->getECLCluster();
385 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
387 return frame.getMomentum(p4Cluster).Theta();
392 double eclClusterErrorTheta(
const Particle* particle)
395 const ECLCluster* cluster = particle->getECLCluster();
398 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
399 return sqrt(fabs(EPhiThetaCov[2][2]));
404 double eclClusterErrorPhi(
const Particle* particle)
407 const ECLCluster* cluster = particle->getECLCluster();
410 const auto EPhiThetaCov = clutls.GetCovarianceMatrix3x3FromCluster(cluster);
411 return sqrt(fabs(EPhiThetaCov[1][1]));
416 double eclClusterPhi(
const Particle* particle)
420 const ECLCluster* cluster = particle->getECLCluster();
423 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, particle->getECLClusterEHypothesisBit());
425 return frame.getMomentum(p4Cluster).Phi();
430 double eclClusterR(
const Particle* particle)
433 const ECLCluster* cluster = particle->getECLCluster();
435 return cluster->getR();
440 double eclClusterE1E9(
const Particle* particle)
443 const ECLCluster* cluster = particle->getECLCluster();
445 return cluster->getE1oE9();
450 double eclClusterE9E21(
const Particle* particle)
453 const ECLCluster* cluster = particle->getECLCluster();
455 return cluster->getE9oE21();
460 double eclClusterAbsZernikeMoment40(
const Particle* particle)
463 const ECLCluster* cluster = particle->getECLCluster();
465 return cluster->getAbsZernike40();
470 double eclClusterAbsZernikeMoment51(
const Particle* particle)
473 const ECLCluster* cluster = particle->getECLCluster();
475 return cluster->getAbsZernike51();
480 double eclClusterZernikeMVA(
const Particle* particle)
483 const ECLCluster* cluster = particle->getECLCluster();
485 return cluster->getZernikeMVA();
490 double eclClusterSecondMoment(
const Particle* particle)
493 const ECLCluster* cluster = particle->getECLCluster();
495 return cluster->getSecondMoment();
500 double eclClusterLAT(
const Particle* particle)
503 const ECLCluster* cluster = particle->getECLCluster();
505 return cluster->getLAT();
510 double eclClusterNHits(
const Particle* particle)
513 const ECLCluster* cluster = particle->getECLCluster();
515 return cluster->getNumberOfCrystals();
520 double eclClusterTrackMatched(
const Particle* particle)
523 const ECLCluster* cluster = particle->getECLCluster();
525 const Track* track = cluster->getRelatedFrom<Track>();
535 double nECLClusterTrackMatches(
const Particle* particle)
538 const ECLCluster* cluster = particle->getECLCluster();
543 size_t out = cluster->getRelationsFrom<Track>().size();
547 double eclClusterId(
const Particle* particle)
549 const ECLCluster* cluster = particle->getECLCluster();
551 return cluster->getClusterId();
556 double eclClusterHasNPhotonsHypothesis(
const Particle* particle)
558 const ECLCluster* cluster = particle->getECLCluster();
565 double eclClusterHasNeutralHadronHypothesis(
const Particle* particle)
567 const ECLCluster* cluster = particle->getECLCluster();
574 double eclClusterHasPulseShapeDiscrimination(
const Particle* particle)
576 const ECLCluster* cluster = particle->getECLCluster();
578 return cluster->hasPulseShapeDiscrimination();
583 double eclExtTheta(
const Particle* particle)
586 const Track* track = particle->getTrack();
589 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
592 return eclinfo->getExtTheta();
594 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
602 double eclExtPhi(
const Particle* particle)
605 const Track* track = particle->getTrack();
608 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
611 return eclinfo->getExtPhi();
613 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
621 double eclExtPhiId(
const Particle* particle)
623 const Track* track = particle->getTrack();
626 auto* eclinfo = track->getRelatedTo<ECLEnergyCloseToTrack>();
629 return eclinfo->getExtPhiId();
631 B2WARNING(
"Relation to ECLEnergyCloseToTrack not found, did you forget to run ECLTrackCalDigitMatchModule?");
639 double weightedAverageECLTime(
const Particle* particle)
641 int nDaughters = particle->getNDaughters();
642 if (nDaughters < 1) {
643 B2WARNING(
"The provided particle has no daughters!");
647 double numer = 0, denom = 0;
648 int numberOfClusterDaughters = 0;
650 auto weightedECLTimeAverage = [&numer, &denom, &numberOfClusterDaughters](
const Particle * p) {
651 const ECLCluster* cluster = p->getECLCluster();
652 if (cluster and not cluster->hasFailedFitTime()) {
653 numberOfClusterDaughters ++;
655 double time = cluster->getTime();
656 B2DEBUG(10,
"time[" << numberOfClusterDaughters <<
"] = " << time);
657 double deltatime = cluster->getDeltaTime99();
658 B2DEBUG(10,
"deltatime[" << numberOfClusterDaughters <<
"] = " << deltatime);
659 numer += time / pow(deltatime, 2);
660 B2DEBUG(11,
"numer[" << numberOfClusterDaughters <<
"] = " << numer);
661 denom += 1 / pow(deltatime, 2);
662 B2DEBUG(11,
"denom[" << numberOfClusterDaughters <<
"] = " << denom);
667 particle->forEachDaughter(weightedECLTimeAverage,
true,
true);
669 if (numberOfClusterDaughters < 1) {
670 B2WARNING(
"There are no clusters or cluster matches amongst the daughters of the provided particle!");
675 B2WARNING(
"The denominator of the weighted mean is zero!");
678 B2DEBUG(10,
"numer/denom = " << numer / denom);
679 return numer / denom;
683 double maxWeightedDistanceFromAverageECLTime(
const Particle* particle)
685 int nDaughters = particle->getNDaughters();
686 if (nDaughters < 1) {
687 B2WARNING(
"The provided particle has no daughters!");
691 double maxTimeDiff = -DBL_MAX;
692 int numberOfClusterDaughters = 0;
694 double averageECLTime = weightedAverageECLTime(particle);
696 auto maxTimeDifference = [&maxTimeDiff, &numberOfClusterDaughters, &averageECLTime](
const Particle * p) {
698 const ECLCluster* cluster = p->getECLCluster();
700 numberOfClusterDaughters ++;
702 double time = cluster->getTime();
703 B2DEBUG(10,
"time[" << numberOfClusterDaughters <<
"] = " << time);
704 double deltatime = cluster->getDeltaTime99();
705 B2DEBUG(10,
"deltatime[" << numberOfClusterDaughters <<
"] = " << deltatime);
706 double maxTimeDiff_temp = fabs((time - averageECLTime) / deltatime);
707 B2DEBUG(11,
"maxTimeDiff_temp[" << numberOfClusterDaughters <<
"] = " << maxTimeDiff_temp);
708 if (maxTimeDiff_temp > maxTimeDiff)
709 maxTimeDiff = maxTimeDiff_temp;
710 B2DEBUG(11,
"maxTimeDiff[" << numberOfClusterDaughters <<
"] = " << maxTimeDiff);
715 particle->forEachDaughter(maxTimeDifference,
true,
true);
717 if (numberOfClusterDaughters < 1) {
718 B2WARNING(
"There are no clusters or cluster matches amongst the daughters of the provided particle!");
722 if (maxTimeDiff < 0) {
723 B2WARNING(
"The max time difference is negative!");
726 B2DEBUG(10,
"maxTimeDiff = " << maxTimeDiff);
731 double eclClusterMdstIndex(
const Particle* particle)
733 const ECLCluster* cluster = particle->getECLCluster();
735 return cluster->getArrayIndex();
741 double eclClusterTimeNorm90(
const Particle* particle)
744 const ECLCluster* cluster = particle->getECLCluster();
745 StoreObjPtr<EventLevelClusteringInfo> elci;
748 std::string payloadName =
"ECLTimingNormalization_data";
750 static DBObjPtr<ECLTimingNormalization> ECLTimingNormalization(payloadName);
751 if (!ECLTimingNormalization.isValid()) {
752 B2FATAL(payloadName <<
" payload is not available");
755 if (elci and cluster) {
758 unsigned short cellID = cluster->getMaxECellId();
759 const unsigned short firstCellID = 161;
760 const unsigned short lastCellID = 8608;
762 int iCrys = cellID - 1;
765 double rawTime = cluster->getTime();
766 const double timingBit = 2000. / 4096.;
767 double tSmear = timingBit * (gRandom->Uniform() - 0.5);
768 double time = rawTime + tSmear;
772 double clusterERaw = cluster->getEnergyRaw();
773 double singleECorrected = cluster->getEnergyHighestCrystal();
774 double singleCrystalE = singleECorrected * clusterERaw / clusterECorrected;
775 double basicEScale = 0.1 / singleCrystalE;
778 const int firstBarrel = 1153;
779 const int lastBarrel = 7776;
780 double ootCrys = elci->getNECLCalDigitsOutOfTimeBarrel();
781 if (cellID < firstBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeFWD();}
782 if (cellID > lastBarrel) {ootCrys = elci->getNECLCalDigitsOutOfTimeBWD();}
786 std::array< std::array<float, 7>, 8736> par7 = ECLTimingNormalization->getTimeWalkPar();
788 float EForCor = singleCrystalE;
789 if (EForCor < par7[iCrys][5]) {EForCor = par7[iCrys][5];}
790 if (EForCor > par7[iCrys][6]) {EForCor = par7[iCrys][6];}
791 float dE = EForCor - par7[iCrys][0];
792 double timeWalkCor = par7[iCrys][1] + par7[iCrys][2] * dE;
794 timeWalkCor = par7[iCrys][1] + par7[iCrys][3] * dE + par7[iCrys][4] * dE * dE;
799 std::array< std::array<float, 5>, 8736> bPar = ECLTimingNormalization->getBackgroundPar();
802 if (oot < bPar[iCrys][3]) {oot = bPar[iCrys][3];}
803 if (oot > bPar[iCrys][4]) {oot = bPar[iCrys][4];}
804 double backgroundNorm = bPar[iCrys][0] + bPar[iCrys][1] * oot + bPar[iCrys][2] * oot * oot;
808 par7 = ECLTimingNormalization->getEnergyPar();
810 EForCor = singleCrystalE;
811 if (EForCor < par7[iCrys][5]) {EForCor = par7[iCrys][5];}
812 if (EForCor > par7[iCrys][6]) {EForCor = par7[iCrys][6];}
813 dE = EForCor - par7[iCrys][0];
814 double energyNorm = par7[iCrys][1] + par7[iCrys][2] * dE;
816 energyNorm = par7[iCrys][1] + par7[iCrys][3] * dE + par7[iCrys][4] * dE * dE;
820 double minTNorm = (double)ECLTimingNormalization->getMinTNormalization();
821 double tNormalization = basicEScale * backgroundNorm * energyNorm;
822 if (tNormalization < minTNorm) {tNormalization = minTNorm;}
823 double tNorm90 = (time - timeWalkCor) / tNormalization;
836 double nECLOutOfTimeCrystalsFWDEndcap(
const Particle*)
838 StoreObjPtr<EventLevelClusteringInfo> elci;
840 return (
double)elci->getNECLCalDigitsOutOfTimeFWD();
843 double nECLOutOfTimeCrystalsBarrel(
const Particle*)
845 StoreObjPtr<EventLevelClusteringInfo> elci;
847 return (
double)elci->getNECLCalDigitsOutOfTimeBarrel();
850 double nECLOutOfTimeCrystalsBWDEndcap(
const Particle*)
852 StoreObjPtr<EventLevelClusteringInfo> elci;
854 return (
double)elci->getNECLCalDigitsOutOfTimeBWD();
857 double nECLOutOfTimeCrystals(
const Particle*)
859 StoreObjPtr<EventLevelClusteringInfo> elci;
861 return (
double)elci->getNECLCalDigitsOutOfTime();
864 double nRejectedECLShowersFWDEndcap(
const Particle*)
866 StoreObjPtr<EventLevelClusteringInfo> elci;
868 return (
double)elci->getNECLShowersRejectedFWD();
871 double nRejectedECLShowersBarrel(
const Particle*)
873 StoreObjPtr<EventLevelClusteringInfo> elci;
875 return (
double)elci->getNECLShowersRejectedBarrel();
878 double nRejectedECLShowersBWDEndcap(
const Particle*)
880 StoreObjPtr<EventLevelClusteringInfo> elci;
882 return (
double)elci->getNECLShowersRejectedBWD();
885 double nRejectedECLShowers(
const Particle*)
887 StoreObjPtr<EventLevelClusteringInfo> elci;
889 return (
double) elci->getNECLShowersRejected();
892 double nKLMMultistripHitsFWDEndcap(
const Particle*)
894 StoreObjPtr<EventLevelClusteringInfo> elci;
896 return (
double) elci->getNKLMDigitsMultiStripFWD();
899 double nKLMMultistripHitsBarrel(
const Particle*)
901 StoreObjPtr<EventLevelClusteringInfo> elci;
903 return (
double) elci->getNKLMDigitsMultiStripBarrel();
906 double nKLMMultistripHitsBWDEndcap(
const Particle*)
908 StoreObjPtr<EventLevelClusteringInfo> elci;
910 return (
double) elci->getNKLMDigitsMultiStripBWD();
913 double nKLMMultistripHits(
const Particle*)
915 StoreObjPtr<EventLevelClusteringInfo> elci;
917 return (
double) elci->getNKLMDigitsMultiStrip();
920 double nECLShowersFWDEndcap(
const Particle*)
922 StoreObjPtr<EventLevelClusteringInfo> elci;
924 return (
double) elci->getNECLShowersFWD();
927 double nECLShowersBarrel(
const Particle*)
929 StoreObjPtr<EventLevelClusteringInfo> elci;
931 return (
double) elci->getNECLShowersBarrel();
934 double nECLShowersBWDEndcap(
const Particle*)
936 StoreObjPtr<EventLevelClusteringInfo> elci;
938 return (
double) elci->getNECLShowersBWD();
941 double nECLShowers(
const Particle*)
943 StoreObjPtr<EventLevelClusteringInfo> elci;
945 return (
double) elci->getNECLShowers();
948 double nECLLocalMaximumsFWDEndcap(
const Particle*)
950 StoreObjPtr<EventLevelClusteringInfo> elci;
952 return (
double) elci->getNECLLocalMaximumsFWD();
955 double nECLLocalMaximumsBarrel(
const Particle*)
957 StoreObjPtr<EventLevelClusteringInfo> elci;
959 return (
double) elci->getNECLLocalMaximumsBarrel();
962 double nECLLocalMaximumsBWDEndcap(
const Particle*)
964 StoreObjPtr<EventLevelClusteringInfo> elci;
966 return (
double) elci->getNECLLocalMaximumsBWD();
969 double nECLLocalMaximums(
const Particle*)
971 StoreObjPtr<EventLevelClusteringInfo> elci;
973 return (
double) elci->getNECLLocalMaximums();
976 double nECLTriggerCellsFWDEndcap(
const Particle*)
978 StoreObjPtr<EventLevelClusteringInfo> elci;
980 return (
double) elci->getNECLTriggerCellsFWD();
983 double nECLTriggerCellsBarrel(
const Particle*)
985 StoreObjPtr<EventLevelClusteringInfo> elci;
987 return (
double) elci->getNECLTriggerCellsBarrel();
990 double nECLTriggerCellsBWDEndcap(
const Particle*)
992 StoreObjPtr<EventLevelClusteringInfo> elci;
994 return (
double) elci->getNECLTriggerCellsBWD();
997 double nECLTriggerCells(
const Particle*)
999 StoreObjPtr<EventLevelClusteringInfo> elci;
1001 return (
double) elci->getNECLTriggerCells();
1004 double eclClusterEoP(
const Particle* part)
1006 double E = eclClusterE(part);
1007 if (part->hasExtraInfo(
"bremsCorrectedPhotonEnergy")) {
1008 E += part->getExtraInfo(
"bremsCorrectedPhotonEnergy");
1010 const double p = part->getMomentumMagnitude();
1015 double eclClusterOnlyInvariantMass(
const Particle* part)
1017 int nDaughters = part->getNDaughters();
1018 ROOT::Math::PxPyPzEVector sum;
1020 if (nDaughters < 1) {
1021 return part->getMass();
1023 int nClusterDaughters = 0;
1024 std::stack<const Particle*> stacked;
1026 while (!stacked.empty()) {
1027 const Particle* current = stacked.top();
1030 const ECLCluster* cluster = current->getECLCluster();
1033 nClusterDaughters ++;
1034 ClusterUtils clutls;
1035 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, clusterBit);
1038 const std::vector<Particle*> daughters = current->getDaughters();
1039 nDaughters = current->getNDaughters();
1040 for (
int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
1041 stacked.push(daughters[iDaughter]);
1046 if (nClusterDaughters < 1) {
1047 B2WARNING(
"There are no clusters amongst the daughters of the provided particle!");
1050 B2DEBUG(10,
"Number of daughters with cluster associated = " << nClusterDaughters);
1057 std::string cutString =
"";
1058 if (arguments.size() > 0) {
1059 cutString = arguments[0];
1063 std::string photonlistname =
"gamma:all";
1064 if (arguments.size() > 1) {
1065 photonlistname = arguments[1];
1068 std::string tracklistname =
"e-:all";
1069 if (arguments.size() > 2) {
1070 tracklistname = arguments[2];
1073 auto func = [cut, photonlistname, tracklistname](
const Particle * particle) ->
double {
1077 B2WARNING(
"The variable photonHasOverlap is supposed to be calculated for photons. Returning NaN.");
1081 StoreObjPtr<ParticleList> photonlist(photonlistname);
1082 if (!(photonlist.isValid()))
1084 B2WARNING(
"The provided particle list " << photonlistname <<
" does not exist."
1085 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1090 B2WARNING(
"The list " << photonlistname <<
" does not contain photons."
1091 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1095 StoreObjPtr<ParticleList> tracklist(tracklistname);
1096 if (!(tracklist.isValid()))
1098 B2WARNING(
"The provided particle list " << tracklistname <<
" does not exist."
1099 " Therefore, the variable photonHasOverlap can not be calculated. Returning NaN.");
1104 B2WARNING(
"The list " << tracklistname <<
" does not contain charged final state particles."
1105 " Therefore, the variable photonHasOverlap can not be calculated reliably. Returning NaN.");
1109 double connectedRegionID = eclClusterConnectedRegionID(particle);
1110 int mdstSource = particle->getMdstSource();
1112 for (
unsigned int i = 0; i < photonlist->getListSize(); i++)
1114 const Particle* part = photonlist->getParticle(i);
1117 if (part->getMdstSource() == mdstSource) {
1122 if (!cut->check(part)) {
1126 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1131 for (
unsigned int i = 0; i < tracklist->getListSize(); i++)
1133 const Particle* part = tracklist->getParticle(i);
1136 if (!cut->check(part)) {
1140 if (connectedRegionID == eclClusterConnectedRegionID(part)) {
1150 VARIABLE_GROUP(
"ECL Cluster related");
1151 REGISTER_VARIABLE(
"clusterEoP", eclClusterEoP, R
"DOC(
1152Returns ratio of uncorrelated energy E over momentum p, a convenience
1153alias for (clusterE / p).
1155 REGISTER_VARIABLE("clusterReg", eclClusterDetectionRegion, R
"DOC(
1156Returns an integer code for the ECL region of a cluster.
1158- 1: forward, 2: barrel, 3: backward,
1159- 11: between FWD and barrel, 13: between BWD and barrel,
1162 REGISTER_VARIABLE("clusterDeltaLTemp", eclClusterDeltaL, R
"DOC(
1163| Returns DeltaL for the shower shape.
1164| A cluster comprises the energy depositions of several crystals. All these crystals have slightly
1165 different orientations in space. A shower direction can be constructed by calculating the weighted
1166 average of these orientations using the corresponding energy depositions as weights. The intersection
1167 (more precisely the point of closest approach) of the vector with this direction originating from the
1168 cluster center and an extrapolated track can be used as reference for the calculation of the shower
1169 depth. It is defined as the distance between this intersection and the cluster center.
1172 This distance is calculated on the reconstructed level and is temporarily
1173 included to the ECL cluster MDST data format for studying purposes. If it is found
1174 that it is not crucial for physics analysis then this variable will be removed
1176 Therefore, keep in mind that this variable might be removed in the future!
1179 | Please read `this <importantNoteECL>` first.
1180 | Lower limit: :math:`-250.0`
1181 | Upper limit: :math:`250.0`
1182 | Precision: :math:`10` bit
1187 REGISTER_VARIABLE("minC2TDist", eclClusterIsolation, R"DOC(
1188Returns the distance between the ECL cluster and its nearest track.
1190For all tracks in the event, the distance between each of their extrapolated hits in the ECL and the ECL shower
1191position is calculated, and the overall smallest distance is returned. The track array index of the track that is
1192closest to the ECL cluster can be retrieved using `minC2TDistID`.
1194If the calculated distance is greater than :math:`250.0`, the returned distance will be capped at :math:`250.0`.
1195If there are no extrapolated hits found in the ECL for the event, NaN will be returned.
1198 This distance is calculated on the reconstructed level.
1201 | Please read `this <importantNoteECL>` first.
1202 | Lower limit: :math:`0.0`
1203 | Upper limit: :math:`250.0`
1204 | Precision: :math:`10` bit
1208 REGISTER_VARIABLE("minC2TDistID", eclClusterIsolationID, R"DOC(
1209Returns the track array index of the nearest track to the ECL cluster. The nearest track is calculated
1210using the `minC2TDist` variable.
1212 REGISTER_METAVARIABLE("minC2TDistVar(variable,particleList=pi-:all)", eclClusterIsolationVar, R
"DOC(
1213Returns the variable value of the nearest track to the given ECL cluster as calculated by `minC2TDist`. The
1214first argument is the variable name, e.g. `nCDCHits`, while the second (optional) argument is the particle list name which
1215will be used to pick up the nearest track in the calculation of `minC2TDist`. The default particle list used
1217)DOC", Manager::VariableDataType::c_double);
1218 REGISTER_VARIABLE("clusterE", eclClusterE, R
"DOC(
1219Returns ECL cluster's energy corrected for leakage and background.
1221The raw photon energy is given by the weighted sum of all ECL crystal energies within the ECL cluster.
1222The weights per crystals are :math:`\leq 1` after cluster energy splitting in the case of overlapping
1223clusters. The number of crystals that are included in the sum depends on a initial energy estimation
1224and local beam background levels at the highest energy crystal position. It is optimized to minimize
1225the core width (resolution) of true photons. Photon energy distributions always show a low energy tail
1226due to unavoidable longitudinal and transverse leakage that can be further modified by the clustering
1227algorithm and beam backgrounds.The peak position of the photon energy distributions are corrected to
1228match the true photon energy in MC:
1230- Leakage correction: Using large MC samples of mono-energetic single photons, a correction factor
1231 :math:`f` as function of reconstructed detector position, reconstructed photon energy and beam backgrounds
1232 is determined via :math:`f = \frac{\text{peak_reconstructed}}{\text{energy_true}}`.
1234- Cluster energy calibration (data only): To reach the target precision of :math:`< 1.8\%` energy
1235 resolution for high energetic photons, the remaining difference between MC and data must be calibrated
1236 using kinematically fit muon pairs. This calibration is only applied to data and not to MC and will
1237 take time to develop.
1239- Energy Bias Correction module, sub-percent correction, is NOT applied on clusterE, but on photon energy
1240 and momentum. Only applied to data.
1242It is important to note that after perfect leakage correction and cluster energy calibration,
1243the :math:`\pi^{0}` mass peak will be shifted slightly to smaller values than the PDG average
1244due to the low energy tails of photons. The :math:`\pi^{0}` mass peak must not be corrected
1245to the PDG value by adjusting the reconstructed photon energies. Selection criteria based on
1246the mass for :math:`\pi^{0}` candidates must be based on the biased value. Most analysis
1247will used mass constrained :math:`\pi^{0}` s anyhow.
1250 We only store clusters with :math:`E > 20\,` MeV.
1253 | Please read `this <importantNoteECL>` first.
1254 | Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV)
1255 | Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV)
1256 | Precision: :math:`18` bit
1257 | This value can be changed to a different reference frame with :b2:var:`useCMSFrame`.
1261 REGISTER_VARIABLE("clusterErrorE", eclClusterErrorE, R"DOC(
1262Returns ECL cluster's uncertainty on energy
1263(from background level and energy dependent tabulation).
1266 REGISTER_VARIABLE("clusterErrorPhi", eclClusterErrorPhi, R"DOC(
1267Returns ECL cluster's uncertainty on :math:`\phi`
1268(from background level and energy dependent tabulation).
1271 REGISTER_VARIABLE("clusterErrorTheta", eclClusterErrorTheta, R"DOC(
1272Returns ECL cluster's uncertainty on :math:`\theta`
1273(from background level and energy dependent tabulation).
1277 REGISTER_VARIABLE("clusterR", eclClusterR, R"DOC(
1278Returns ECL cluster's centroid distance from :math:`(0,0,0)`.
1281 REGISTER_VARIABLE("clusterPhi", eclClusterPhi, R"DOC(
1282Returns ECL cluster's azimuthal angle :math:`\phi`
1283(this is not generally equal to a photon azimuthal angle).
1285| The direction of a cluster is given by the connecting line of :math:`\,(0,0,0)\,` and
1286 cluster centroid position in the ECL.
1287| The cluster centroid position is calculated using up to 21 crystals (5x5 excluding corners)
1288 after cluster energy splitting in the case of overlapping clusters.
1289| The centroid position is the logarithmically weighted average of all crystals evaluated at
1290 the crystal centers. Cluster centroids are generally biased towards the centers of the
1291 highest energetic crystal. This effect is larger for low energetic photons.
1292| Beam backgrounds slightly decrease the position resolution, mainly for low energetic photons.
1295 Radius of a cluster is almost constant in the barrel and should not be used directly in any selection.
1297Unlike for charged tracks, the uncertainty (covariance) of the photon directions is not determined
1298based on individual cluster properties but taken from on MC-based parametrizations of the resolution
1299as function of true photon energy, true photon direction and beam background level.
1302 Users must use the actual particle direction (done automatically in the modularAnalysis using the average
1303 IP position (can be changed if needed)) and not the ECL Cluster direction (position in the ECL measured
1304 from :math:`(0,0,0)`) for particle kinematics.
1307 | Please read `this <importantNoteECL>` first.
1308 | Lower limit: :math:`-\pi`
1309 | Upper limit: :math:`\pi`
1310 | Precision: :math:`16` bit
1314 REGISTER_VARIABLE("clusterConnectedRegionID", eclClusterConnectedRegionID, R"DOC(
1315Returns ECL cluster's connected region ID.
1317 REGISTER_VARIABLE("clusterTheta", eclClusterTheta, R
"DOC(
1318Returns ECL cluster's polar angle :math:`\theta`
1319(this is not generally equal to a photon polar angle).
1321| The direction of a cluster is given by the connecting line of :math:`\,(0,0,0)\,` and
1322 cluster centroid position in the ECL.
1323| The cluster centroid position is calculated using up to 21 crystals (5x5 excluding corners)
1324 after cluster energy splitting in the case of overlapping clusters.
1325| The centroid position is the logarithmically weighted average of all crystals evaluated at
1326 the crystal centers. Cluster centroids are generally biased towards the centers of the
1327 highest energetic crystal. This effect is larger for low energetic photons.
1328| Beam backgrounds slightly decrease the position resolution, mainly for low energetic photons.
1331 Radius of a cluster is almost constant in the barrel and should not be used directly in any selection.
1333Unlike for charged tracks, the uncertainty (covariance) of the photon directions is not determined
1334based on individual cluster properties but taken from on MC-based parametrizations of the resolution
1335as function of true photon energy, true photon direction and beam background level.
1338 Users must use the actual particle direction (done automatically in the modularAnalysis using the average
1339 IP position (can be changed if needed)) and not the ECL Cluster direction (position in the ECL measured
1340 from :math:`(0,0,0)`) for particle kinematics.
1343 | Please read `this <importantNoteECL>` first.
1344 | Lower limit: :math:`0.0`
1345 | Upper limit: :math:`\pi`
1346 | Precision: :math:`16` bit
1350 REGISTER_VARIABLE("clusterTiming", eclClusterTiming, R"DOC(
1352Returns the time of the ECL cluster. It is calculated as the Photon timing minus the Event t0.
1353Photon timing is given by the fitted time of the recorded waveform of the highest energy crystal in the
1354cluster. After all calibrations and corrections (including Time-Of-Flight), photons from the interaction
1355point (IP) should have a Photon timing that corresponds to the Event t0, :math:`t_{0}`. The Event t0 is the
1356time of the event and may be measured by a different sub-detector (see Event t0 documentation). For an ECL
1357cluster produced at the interaction point in time with the event, the cluster time should be consistent with zero
1358within the uncertainties. Special values are returned if the fit for the Photon timing fails (see
1359documentation for `clusterHasFailedTiming`). (For MC, the calibrations and corrections are not fully simulated).
1362 | Please read `this <importantNoteECL>` first.
1363 | Lower limit: :math:`-1000.0`
1364 | Upper limit: :math:`1000.0`
1365 | Precision: :math:`12` bit
1369Returns the trigger cell (TC) time of the ECL cluster (photon).
1370This information is available only in Belle data since experiment 31, and not available in Belle MC.
1371Clusters produced at the interaction point in time with the event, have TC time in the range of 9000-11000
1372Calculated based on the 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:
1376 | Lower limit: :math:`-1000.0`
1377 | Upper limit: :math:`1000.0`
1378 | Precision: :math:`12` bit
1382 REGISTER_VARIABLE("clusterHasFailedTiming", eclClusterHasFailedTiming, R"DOC(
1383Status bit for if the ECL cluster's timing fit failed. Photon timing is given by the fitted time
1384of the recorded waveform of the highest energetic crystal in a cluster; however, that fit can fail and so
1385this variable tells the user if that has happened.
1387 REGISTER_VARIABLE("clusterErrorTiming", eclClusterErrorTiming, R
"DOC(
1388Returns ECL cluster's timing uncertainty that contains :math:`99\%` of true photons (dt99).
1390The photon timing uncertainty is currently determined using MC. The resulting parametrization depends on
1391the true energy deposition in the highest energetic crystal and the local beam background level in that crystal.
1392The resulting timing distribution is non-Gaussian and for each photon the value dt99 is stored,
1393where :math:`|\text{timing}| / \text{dt99} < 1` is designed to give a :math:`99\%`
1394timing efficiency for true photons from the IP.
1395The resulting efficiency is approximately flat in energy and independent of beam background levels.
1397Very large values of dt99 are an indication of failed waveform fits in the ECL.
1398We remove such clusters in most physics photon lists.
1401 | Please read `this <importantNoteECL>` first.
1402 | Lower limit: :math:`0.0`
1403 | Upper limit: :math:`1000.0`
1404 | Precision: :math:`12` bit
1407 In real data there will be a sizeable number of high energetic Bhabha events
1408 (from previous or later bunch collisions) that can easily be rejected by timing cuts.
1409 However, these events create large ECL clusters that can overlap with other ECL clusters
1410 and it is not clear that a simple rejection is the correction strategy.
1414 REGISTER_VARIABLE("clusterHasFailedErrorTiming", eclClusterHasFailedErrorTiming, R"DOC(
1415Status bit for if the ECL cluster's timing uncertainty calculation failed. Photon timing is given by the fitted time
1416of the recorded waveform of the highest energetic crystal in a cluster; however, that fit can fail and so
1417this variable tells the user if that has happened.
1419 REGISTER_VARIABLE("clusterHighestE", eclClusterHighestE, R
"DOC(
1420Returns energy of the highest energetic crystal in the ECL cluster after reweighting.
1423 This variable must be used carefully since it can bias shower selection
1424 towards photons that hit crystals in the center and hence have a large energy
1425 deposition in the highest energy crystal.
1428 | Please read `this <importantNoteECL>` first.
1429 | Lower limit: :math:`-5` (:math:`e^{-5} = 0.00674\,` GeV)
1430 | Upper limit: :math:`3.0` (:math:`e^3 = 20.08553\,` GeV)
1431 | Precision: :math:`18` bit
1435 REGISTER_VARIABLE("clusterCellID", eclClusterCellId,
1436 "Returns cellId of the crystal with highest energy in the ECLCluster.");
1437 REGISTER_VARIABLE("clusterThetaID", eclClusterThetaId,
1438 "Returns thetaId of the crystal with highest energy in the ECLCluster.");
1439 REGISTER_VARIABLE("clusterPhiID", eclClusterPhiId,
1440 "Returns phiId of the crystal with highest energy in the ECLCluster.");
1441 REGISTER_VARIABLE("clusterE1E9", eclClusterE1E9, R"DOC(
1442Returns ratio of energies of the central crystal, E1, and 3x3 crystals, E9, around the central crystal.
1443Since :math:`E1 \leq E9`, this ratio is :math:`\leq 1` and tends towards larger values for photons
1444and smaller values for hadrons.
1447 | Please read `this <importantNoteECL>` first.
1448 | Lower limit: :math:`0.0`
1449 | Upper limit: :math:`1.0`
1450 | Precision: :math:`10` bit
1452 REGISTER_VARIABLE("clusterE9E25", eclClusterE9E25, R
"DOC(
1453Deprecated - kept for backwards compatibility - returns clusterE9E21.
1455 REGISTER_VARIABLE("clusterE9E21", eclClusterE9E21, R
"DOC(
1456Returns ratio of energies in inner 3x3 crystals, E9, and 5x5 crystals around the central crystal without corners.
1457Since :math:`E9 \leq E21`, this ratio is :math:`\leq 1` and tends towards larger values for photons
1458and smaller values for hadrons.
1461 | Please read `this <importantNoteECL>` first.
1462 | Lower limit: :math:`0.0`
1463 | Upper limit: :math:`1.0`
1464 | Precision: :math:`10` bit
1466 REGISTER_VARIABLE("clusterAbsZernikeMoment40", eclClusterAbsZernikeMoment40, R
"DOC(
1467Returns absolute value of Zernike moment 40 (:math:`|Z_{40}|`). (shower shape variable).
1470 | Please read `this <importantNoteECL>` first.
1471 | Lower limit: :math:`0.0`
1472 | Upper limit: :math:`1.7`
1473 | Precision: :math:`10` bit
1475 REGISTER_VARIABLE("clusterAbsZernikeMoment51", eclClusterAbsZernikeMoment51, R
"DOC(
1476Returns absolute value of Zernike moment 51 (:math:`|Z_{51}|`). (shower shape variable).
1479 | Please read `this <importantNoteECL>` first.
1480 | Lower limit: :math:`0.0`
1481 | Upper limit: :math:`1.2`
1482 | Precision: :math:`10` bit
1484 REGISTER_VARIABLE("clusterZernikeMVA", eclClusterZernikeMVA, R
"DOC(
1485Returns output of a MVA using eleven Zernike moments of the cluster. Zernike moments are calculated per
1486shower in a plane perpendicular to the shower direction via
1489 |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|
1491where n, m are the integers, :math:`i` runs over the crystals in the shower,
1492:math:`E_{i}` is the energy of the i-th crystal in the shower,
1493:math:`R_{nm}` is a polynomial of degree :math:`n`,
1494:math:`\rho_{i}` is the radial distance of the :math:`i`-th crystal in the perpendicular plane,
1495and :math:`\alpha_{i}` is the polar angle of the :math:`i`-th crystal in the perpendicular plane.
1496As a crystal can be related to more than one shower, :math:`w_{i}` is the fraction of the
1497energy of the :math:`i`-th crystal associated with the shower.
1499**Note:** this variable is sensitive to other nearby particles and so cluster isolation properties should always be checked;
1500for more information please see the
1501`ECL Cluster Recommendations <https://indico.belle2.org/event/13722/contributions/84645/attachments/31512/51585/ecl_recommendation.pdf>`_.
1503More details about the implementation can be found in `BELLE2-NOTE-TE-2017-001 <https://docs.belle2.org/record/454?ln=en>`_ .
1505More details about Zernike polynomials can be found in `Wikipedia <https://en.wikipedia.org/wiki/Zernike_polynomials>`_ .
1507| For cluster with hypothesisId==N1: raw MVA output.
1508| For cluster with hypothesisId==N2: 1 - prod{clusterZernikeMVA}, where the product is on all N1 showers
1509 belonging to the same connected region (shower shape variable).
1512 | Please read `this <importantNoteECL>` first.
1513 | Lower limit: :math:`0.0`
1514 | Upper limit: :math:`1.0`
1515 | Precision: :math:`10` bit
1517 REGISTER_VARIABLE("clusterSecondMoment", eclClusterSecondMoment, R
"DOC(
1518Returns second moment :math:`S`. It is defined as:
1521 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}}
1523where :math:`E_{i} = (E_0, E_1, ...)` are the single crystal energies sorted by energy, :math:`w_{i}` is
1524the crystal weight, and :math:`r_{i}` is the distance of the :math:`i`-th digit to the shower center projected
1525to a plane perpendicular to the shower axis. :math:`S_{0}(\theta)` normalizes :math:`S` to 1 for isolated photons.
1528 | Please read `this <importantNoteECL>` first.
1529 | Lower limit: :math:`0.0`
1530 | Upper limit: :math:`40.0`
1531 | Precision: :math:`10` bit
1534)DOC","dimensionless");
1535 REGISTER_VARIABLE("clusterLAT", eclClusterLAT, R"DOC(
1536Returns lateral energy distribution (shower variable). It is defined as following:
1539 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}}
1541where :math:`E_{i} = (E_{0}, E_{1}, ...)` are the single crystal energies sorted by energy
1542(:math:`E_{0}` is the highest energy and :math:`E_{1}` the second highest), :math:`w_{i}`
1543is the crystal weight, :math:`r_{i}` is the distance of the :math:`i`-th digit to the
1544shower center projected to a plane perpendicular to the shower axis,
1545and :math:`r_{0} \approx 5\,cm` is the distance between two crystals.
1547clusterLAT peaks around 0.3 for radially symmetrical electromagnetic showers and is larger
1548for hadronic events, and electrons with a close-by radiative or Bremsstrahlung photon.
1551 | Please read `this <importantNoteECL>` first.
1552 | Lower limit: :math:`0.0`
1553 | Upper limit: :math:`1.0`
1554 | Precision: :math:`10` bit
1556 REGISTER_VARIABLE("clusterNHits", eclClusterNHits, R
"DOC(
1557Returns sum of weights :math:`w_{i}` (:math:`w_{i} \leq 1`) of all crystals in an ECL cluster.
1558For non-overlapping clusters this is equal to the number of crystals in the cluster.
1559In case of energy splitting among nearby clusters, this can be a non-integer value.
1562 | Please read `this <importantNoteECL>` first.
1563 | Lower limit: :math:`0.0`
1564 | Upper limit: :math:`200.0`
1565 | Precision: :math:`10` bit
1566 | If fractional weights are not of interest, this value should be cast to the nearest integer.
1568 REGISTER_VARIABLE("clusterTrackMatch", eclClusterTrackMatched, R
"DOC(
1569Returns 1.0 if at least one reconstructed charged track is matched to the ECL cluster.
1571Every reconstructed charged track is extrapolated into the ECL.
1572Every ECL crystal that is crossed by the track extrapolation is marked.
1573Each ECL cluster that contains any marked crystal is matched to the track.
1574Multiple tracks can be matched to one cluster and multiple clusters can be matched to one track.
1575It is conceptually correct to have two tracks matched to the same cluster.
1577 REGISTER_VARIABLE("nECLClusterTrackMatches", nECLClusterTrackMatches, R
"DOC(
1578Returns number of charged tracks matched to this cluster.
1581 Sometimes (perfectly correctly) two tracks are extrapolated into the same cluster.
1583 - For charged particles, this should return at least 1 (but sometimes 2 or more).
1584 - For neutrals, this should always return 0.
1585 - Returns NaN if there is no cluster.
1587 REGISTER_VARIABLE("clusterHasPulseShapeDiscrimination", eclClusterHasPulseShapeDiscrimination, R
"DOC(
1588Status bit to indicate if cluster has digits with waveforms that passed energy and :math:`\chi^2`
1589thresholds for computing PSD variables.
1591 REGISTER_VARIABLE("beamBackgroundSuppression", beamBackgroundSuppression, R
"DOC(
1592Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from beam background clusters.
1593Class 1 is for true photon clusters while class 0 is for beam background clusters.
1595The MVA has been trained using MC and the features used are:
1598- `clusterPulseShapeDiscriminationMVA`
1602The variable `clusterZernikeMVA` is also used but only for the MC15 training.
1603Both run-dependent and run-independent weights are available. For more information on this, and for usage recommendations, please see
1604the `Neutrals Performance XWiki Page <https://xwiki.desy.de/xwiki/rest/p/e23c8>`_.
1606Please cite `this <https://inspirehep.net/literature/2785196>`_ if using this tool.
1608 REGISTER_VARIABLE("fakePhotonSuppression", fakePhotonSuppression, R
"DOC(
1609Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from fake photon clusters (e.g. split-offs,
1610track-cluster matching failures etc.). Class 1 is for true photon clusters while class 0 is for fake photon clusters.
1612The MVA has been trained using MC and the features are:
1614- `clusterPulseShapeDiscriminationMVA`
1620The variable `clusterZernikeMVA` is also used but only for the MC15 training.
1621Both run-dependent and run-independent weights are available. For more information on this, and for usage recommendations, please see
1622the `Neutrals Performance XWiki Page <https://xwiki.desy.de/xwiki/rest/p/e23c8>`_.
1624Please cite `this <https://inspirehep.net/literature/2785196>`_ if using this tool.
1626(This MVA is the same as the one used for `hadronicSplitOffSuppression` but that variable should not be used as it is deprecated and does not use the new weights).
1628 REGISTER_VARIABLE("hadronicSplitOffSuppression", hadronicSplitOffSuppression, R
"DOC(
1629Returns the output of an MVA classifier that uses shower-related variables to distinguish true photon clusters from hadronic splitoff clusters.
1632- 1 for true photon clusters
1633- 0 for hadronic splitoff clusters
1635The MVA has been trained using samples of signal photons and hadronic splitoff photons coming from MC. The features used are (in decreasing order of significance):
1637- `clusterPulseShapeDiscriminationMVA`
1639- `clusterZernikeMVA`
1643- `clusterSecondMoment`
1645 MAKE_DEPRECATED("hadronicSplitOffSuppression",
true,
"light-2302-genetta", R
"DOC(
1646 Use the variable `fakePhotonSuppression` instead which is maintained and uses the latest weight files.
1648 REGISTER_VARIABLE("clusterKlId", eclClusterKlId, R
"DOC(
1649Returns MVA classifier that uses ECL clusters variables to discriminate Klong clusters from em background.
1654 REGISTER_VARIABLE("clusterPulseShapeDiscriminationMVA", eclPulseShapeDiscriminationMVA, R
"DOC(
1655Returns MVA classifier that uses pulse shape discrimination to identify electromagnetic vs hadronic showers.
1657- 1 for electromagnetic showers
1658- 0 for hadronic showers
1660For details, see the following `PSD arxiv paper <https://arxiv.org/pdf/2007.09642>`_
1662 REGISTER_VARIABLE("clusterNumberOfHadronDigits", eclClusterNumberOfHadronDigits, R
"DOC(
1663Returns ECL cluster's number of hadron digits in cluster (pulse shape discrimination variable).
1664Weighted sum of digits in cluster with significant scintillation emission (:math:`> 3\,` MeV)
1665in the hadronic scintillation component.
1666Computed only using cluster digits with energy :math:`> 50\,` MeV and good offline waveform fit :math:`\chi^2`.
1669 | Please read `this <importantNoteECL>` first.
1670 | Lower limit: :math:`0.0`
1671 | Upper limit: :math:`255.0`
1672 | Precision: :math:`18` bit
1674 REGISTER_VARIABLE("clusterClusterID", eclClusterId, R
"DOC(
1675Returns ECL cluster ID of this ECL cluster within the connected region (CR) to which it belongs to.
1677 REGISTER_VARIABLE("clusterHasNPhotons", eclClusterHasNPhotonsHypothesis, R
"DOC(
1678Returns 1.0 if cluster has the 'N photons' hypothesis (historically called 'N1'),
16790.0 if not, and NaN if no cluster is associated to the particle.
1681 REGISTER_VARIABLE("clusterHasNeutralHadron", eclClusterHasNeutralHadronHypothesis, R
"DOC(
1682Returns 1.0 if the cluster has the 'neutral hadrons' hypothesis (historically called 'N2'),
16830.0 if not, and NaN if no cluster is associated to the particle.
1685 REGISTER_VARIABLE("eclExtTheta", eclExtTheta, R
"DOC(
1686Returns extrapolated :math:`\theta` of particle track associated to the cluster (if any). Requires module ECLTrackCalDigitMatch to be executed.
1689 REGISTER_VARIABLE("eclExtPhi", eclExtPhi, R"DOC(
1690Returns extrapolated :math:`\phi` of particle track associated to the cluster (if any). Requires module ECLTrackCalDigitMatch to be executed..
1693 REGISTER_VARIABLE("eclExtPhiId", eclExtPhiId, R"DOC(
1694Returns extrapolated :math:`\phi` ID of particle track associated to the cluster (if any). Requires module ECLTrackCalDigitMatch to be executed..
1696 REGISTER_VARIABLE("weightedAverageECLTime", weightedAverageECLTime, R
"DOC(
1697Returns ECL weighted average time of all clusters (neutrals) and matched clusters (charged) of daughters
1698(of any generation) of the provided particle.
1701 REGISTER_VARIABLE(
"maxWeightedDistanceFromAverageECLTime", maxWeightedDistanceFromAverageECLTime, R
"DOC(
1702Returns maximum weighted distance between time of the cluster of a photon and the ECL average time, amongst
1703the clusters (neutrals) and matched clusters (charged) of daughters (of all generations) of the provided particle.
1706 REGISTER_VARIABLE(
"clusterMdstIndex", eclClusterMdstIndex, R
"DOC(
1707StoreArray index(0 - based) of the MDST ECLCluster (useful for track-based particles matched to a cluster).
1710 REGISTER_VARIABLE("nECLOutOfTimeCrystals", nECLOutOfTimeCrystals, R
"DOC(
1711[Eventbased] Returns the number of crystals (ECLCalDigits) that are out of time.
1714 REGISTER_VARIABLE("nECLOutOfTimeCrystalsFWDEndcap", nECLOutOfTimeCrystalsFWDEndcap, R
"DOC(
1715[Eventbased] Returns the number of crystals (ECLCalDigits) that are out of time in the forward endcap.
1718 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBarrel", nECLOutOfTimeCrystalsBarrel, R
"DOC(
1719[Eventbased] Returns the number of crystals (ECLCalDigits) that are out of time in the barrel.
1722 REGISTER_VARIABLE("nECLOutOfTimeCrystalsBWDEndcap", nECLOutOfTimeCrystalsBWDEndcap, R
"DOC(
1723[Eventbased] Returns the number of crystals (ECLCalDigits) that are out of time in the backward endcap.
1726 REGISTER_VARIABLE("nRejectedECLShowers", nRejectedECLShowers, R
"DOC(
1727[Eventbased] Returns the number of showers in the ECL that do not become clusters.
1730 REGISTER_VARIABLE("nRejectedECLShowersFWDEndcap", nRejectedECLShowersFWDEndcap, R
"DOC(
1731[Eventbased] Returns the number of showers in the ECL that do not become clusters, from the forward endcap.
1732If the number exceeds 255 (uint8_t maximum value) the variable is set to 255.
1735 REGISTER_VARIABLE("nRejectedECLShowersBarrel", nRejectedECLShowersBarrel, R
"DOC(
1736[Eventbased] Returns the number of showers in the ECL that do not become clusters, from the barrel.
1737If the number exceeds 255 (uint8_t maximum value) the variable is set to 255.
1740 REGISTER_VARIABLE("nRejectedECLShowersBWDEndcap", nRejectedECLShowersBWDEndcap, R
"DOC(
1741[Eventbased] Returns the number of showers in the ECL that do not become clusters, from the backward endcap.
1742If the number exceeds 255 (uint8_t maximum value) the variable is set to 255.
1745 REGISTER_VARIABLE("nKLMMultistripHitsFWDEndcap", nKLMMultistripHitsFWDEndcap, R
"DOC(
1746[Eventbased] Returns the number of multi-strip hits in the KLM forward endcap.
1749 REGISTER_VARIABLE("nKLMMultistripHitsBarrel", nKLMMultistripHitsBarrel, R
"DOC(
1750[Eventbased] Returns the number of multi-strip hits in the KLM barrel.
1753 REGISTER_VARIABLE("nKLMMultistripHitsBWDEndcap", nKLMMultistripHitsBWDEndcap, R
"DOC(
1754[Eventbased] Returns the number of multi-strip hits in the KLM backward endcap.
1757 REGISTER_VARIABLE("nKLMMultistripHits", nKLMMultistripHits, R
"DOC(
1758[Eventbased] Returns the number of multi-strip hits in the KLM.
1761 REGISTER_VARIABLE("nECLShowersFWDEndcap", nECLShowersFWDEndcap, R
"DOC(
1762[Eventbased] Returns the number of ECLShowers in the forward endcap.
1765 REGISTER_VARIABLE("nECLShowersBarrel", nECLShowersBarrel, R
"DOC(
1766[Eventbased] Returns the number of ECLShowers in the barrel.
1769 REGISTER_VARIABLE("nECLShowersBWDEndcap", nECLShowersBWDEndcap, R
"DOC(
1770[Eventbased] Returns the number of ECLShowers in the backward endcap.
1773 REGISTER_VARIABLE("nECLShowers", nECLShowers, R
"DOC(
1774[Eventbased] Returns the number of ECLShowers.
1777 REGISTER_VARIABLE("nECLLocalMaximumsFWDEndcap", nECLLocalMaximumsFWDEndcap, R
"DOC(
1778[Eventbased] Returns the number of LocalMaximums in the ECL forward endcap.
1781 REGISTER_VARIABLE("nECLLocalMaximumsBarrel", nECLLocalMaximumsBarrel, R
"DOC(
1782[Eventbased] Returns the number of LocalMaximums in the ECL barrel.
1785 REGISTER_VARIABLE("nECLLocalMaximumsBWDEndcap", nECLLocalMaximumsBWDEndcap, R
"DOC(
1786[Eventbased] Returns the number of LocalMaximums in the ECL backward endcap.
1789 REGISTER_VARIABLE("nECLLocalMaximums", nECLLocalMaximums, R
"DOC(
1790[Eventbased] Returns the number of LocalMaximums in the ECL.
1793 REGISTER_VARIABLE("nECLTriggerCellsFWDEndcap", nECLTriggerCellsFWDEndcap, R
"DOC(
1794[Eventbased] Returns the number of ECL trigger cells above 100 MeV in the forward endcap.
1797 REGISTER_VARIABLE("nECLTriggerCellsBarrel", nECLTriggerCellsBarrel, R
"DOC(
1798[Eventbased] Returns the number of ECL trigger cells above 100 MeV in the barrel.
1801 REGISTER_VARIABLE("nECLTriggerCellsBWDEndcap", nECLTriggerCellsBWDEndcap, R
"DOC(
1802[Eventbased] Returns the number of ECL trigger cells above 100 MeV in the backward endcap.
1805 REGISTER_VARIABLE("nECLTriggerCells", nECLTriggerCells, R
"DOC(
1806[Eventbased] Returns the number of ECL trigger cells above 100 MeV.
1809 REGISTER_VARIABLE("eclClusterOnlyInvariantMass", eclClusterOnlyInvariantMass, R
"DOC(
1810[Expert] The invariant mass calculated from all ECLCluster daughters (i.e. photons) and
1811cluster-matched tracks using the cluster 4-momenta.
1813Used for ECL-based dark sector physics and debugging track-cluster matching.
1815)DOC","GeV/:math:`\\text{c}^2`");
1817 REGISTER_METAVARIABLE("photonHasOverlap(cutString, photonlistname, tracklistname)", photonHasOverlap, R"DOC(
1818 Returns true if the connected ECL region of the particle's cluster is shared by another particle's cluster.
1819 Neutral and charged cluster are considered.
1820 A cut string can be provided to ignore cluster that do not satisfy the given criteria.
1821 By default, the ParticleList ``gamma:all`` is used for the check of neutral ECL cluster,
1822 and the ParticleList ``e-:all`` for the check of charged ECL cluster.
1823 However, one can customize the name of the ParticleLists via additional arguments.
1824 If no argument or only a cut string is provided and ``gamma:all`` or ``e-:all`` does not exist
1825 or if the variable is requested for a particle that is not a photon, NaN is returned.
1826 )DOC", Manager::VariableDataType::c_double);
1828 REGISTER_VARIABLE("clusterUncorrE", eclClusterUncorrectedE, R
"DOC(
1829[Expert] [Calibration] Returns ECL cluster's uncorrected energy. That is, before leakage corrections.
1830This variable should only be used for study of the ECL. Please see :b2:var:`clusterE`.
1834 REGISTER_VARIABLE("distanceToMcKl",distanceToMcKl,R"DOC(
1835Returns the distance to the nearest truth KL particle, extrapolated to the cluster radius. To use
1836this variable, it is required to run getNeutralHadronGeomMatches function. Optionally, it can return
1837negative values to indicate that the ECL cluster should be removed from the analysis to correct for data
1838to MC difference in KL efficiency.
1842 REGISTER_VARIABLE(
"distanceToMcNeutron",distanceToMcNeutron,R
"DOC(
1843Returns the distance to the nearest truth (anti)neutron, extrapolated to the cluster radius. To use
1844this variable, it is required to run getNeutralHadronGeomMatches function. Optionally, it can return
1845negative values to indicate that the ECL cluster should be removed from the analysis to correct for data
1846to MC difference in KL efficiency.
1850 REGISTER_VARIABLE(
"mdstIndexMcKl",mdstIndexMcKl,R
"DOC(
1851 Returns the mdst index of the nearest truth KL, extrapolated to the cluster radius, if it is
1852 within the matching cone. To use this variable, it is required to run getNeutralHadronGeomMatches function.
1855 REGISTER_VARIABLE("mdstIndexMcNeutron",mdstIndexMcNeutron,R
"DOC(
1856 Returns the mdst index of the nearest truth (anti)neutron, extrapolated to the cluster radius, if it is
1857 within the matching cone. To use this variable, it is required to run getNeutralHadronGeomMatches function.
1859 REGISTER_VARIABLE("clusterTimeNorm90", eclClusterTimeNorm90,
1861 Returns ECL cluster's timing normalized such that :math:`90\%` of real photons will
1862 have :math:`|\text{clusterTimeNorm90}| < 1`. Normalization depends on energy, background
1863 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.
Abstract base class for different kinds of events.