10 #include <hlt/softwaretrigger/calculations/FilterCalculator.h>
11 #include <hlt/softwaretrigger/calculations/utilities.h>
13 #include <TLorentzVector.h>
15 #include <mdst/dataobjects/TrackFitResult.h>
16 #include <mdst/dataobjects/HitPatternCDC.h>
21 using namespace SoftwareTrigger;
30 double clusterEnergySumCMS = 0;
32 double clusterEnergySumLab = 0;
48 double energyCMS = NAN;
50 double energyLab = NAN;
58 double clusterTime = NAN;
62 const double flatBoundaries[10] = {0., 19., 22., 25., 30., 35., 45., 60., 90., 180.};
80 calculationResult[
"nTrkLoose"] = 0;
81 calculationResult[
"nTrkTight"] = 0;
82 calculationResult[
"ee2leg"] = 0;
83 calculationResult[
"nEmedium"] = 0;
84 calculationResult[
"nElow"] = 0;
85 calculationResult[
"nEhigh"] = 0;
86 calculationResult[
"nE180Lab"] = 0;
87 calculationResult[
"nE300Lab"] = 0;
88 calculationResult[
"nE500Lab"] = 0;
89 calculationResult[
"nE2000CMS"] = 0;
90 calculationResult[
"nE4000CMS"] = 0;
91 calculationResult[
"nE250Lab"] = 0;
92 calculationResult[
"nMaxEPhotonAcc"] = 0;
93 calculationResult[
"dphiCmsClust"] = NAN;
95 calculationResult[
"netChargeLoose"] = 0;
96 calculationResult[
"maximumPCMS"] = NAN;
97 calculationResult[
"eexx"] = 0;
98 calculationResult[
"ee1leg1trk"] = 0;
99 calculationResult[
"nEhighLowAng"] = 0;
100 calculationResult[
"nEsingleClust"] = 0;
101 calculationResult[
"nEsinglePhotonBarrel"] = 0;
102 calculationResult[
"nEsinglePhotonExtendedBarrel"] = 0;
103 calculationResult[
"nEsinglePhotonEndcap"] = 0;
104 calculationResult[
"nEsingleElectronBarrel"] = 0;
105 calculationResult[
"nEsingleElectronExtendedBarrel"] = 0;
106 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] = 0;
107 calculationResult[
"nVetoClust"] = 0;
108 calculationResult[
"chrgClust2GeV"] = 0;
109 calculationResult[
"neutClust045GeVAcc"] = 0;
110 calculationResult[
"neutClust045GeVBarrel"] = 0;
111 calculationResult[
"singleTagLowMass"] = 0;
112 calculationResult[
"singleTagHighMass"] = 0;
113 calculationResult[
"n2GeVNeutBarrel"] = 0;
114 calculationResult[
"n2GeVNeutEndcap"] = 0;
115 calculationResult[
"n2GeVChrg"] = 0;
116 calculationResult[
"n2GeVPhotonBarrel"] = 0;
117 calculationResult[
"n2GeVPhotonEndcap"] = 0;
118 calculationResult[
"ee1leg"] = 0;
119 calculationResult[
"ee1leg1clst"] = 0;
120 calculationResult[
"ee1leg1e"] = 0;
121 calculationResult[
"ee2clst"] = 0;
122 calculationResult[
"gg2clst"] = 0;
123 calculationResult[
"eeee"] = 0;
124 calculationResult[
"eemm"] = 0;
125 calculationResult[
"eexxSelect"] = 0;
126 calculationResult[
"radBhabha"] = 0;
127 calculationResult[
"eeBrem"] = 0;
128 calculationResult[
"isrRadBhabha"] = 0;
129 calculationResult[
"muonPairECL"] = 0;
130 calculationResult[
"selectee1leg1trk"] = 0;
131 calculationResult[
"selectee1leg1clst"] = 0;
132 calculationResult[
"selectee"] = 0;
133 calculationResult[
"ggBarrelVL"] = 0;
134 calculationResult[
"ggBarrelLoose"] = 0;
135 calculationResult[
"ggBarrelTight"] = 0;
136 calculationResult[
"ggEndcapVL"] = 0;
137 calculationResult[
"ggEndcapLoose"] = 0;
138 calculationResult[
"ggEndcapTight"] = 0;
139 calculationResult[
"muonPairV"] = 0;
140 calculationResult[
"selectmumu"] = 0;
141 calculationResult[
"singleMuon"] = 0;
142 calculationResult[
"cosmic"] = 0;
143 calculationResult[
"eeFlat0"] = 0;
144 calculationResult[
"eeFlat1"] = 0;
145 calculationResult[
"eeFlat2"] = 0;
146 calculationResult[
"eeFlat3"] = 0;
147 calculationResult[
"eeFlat4"] = 0;
148 calculationResult[
"eeFlat5"] = 0;
149 calculationResult[
"eeFlat6"] = 0;
150 calculationResult[
"eeFlat7"] = 0;
151 calculationResult[
"eeFlat8"] = 0;
152 calculationResult[
"eeOneClust"] = 0;
155 calculationResult[
"l1_trigger_random"] =
m_l1Trigger->getTimType() == TRGSummary::ETimingType::TTYP_RAND;
156 calculationResult[
"l1_trigger_delayed_bhabha"] =
m_l1Trigger->getTimType() == TRGSummary::ETimingType::TTYP_DPHY;
157 calculationResult[
"l1_trigger_poisson"] =
m_l1Trigger->getTimType() == TRGSummary::ETimingType::TTYP_POIS;
159 calculationResult[
"bha3d"] =
m_l1Trigger->testPsnm(
"bha3d");
160 calculationResult[
"bhapur"] =
m_l1Trigger->testPsnm(
"bhapur");
163 calculationResult[
"l1_trigger_random"] = 1;
164 calculationResult[
"l1_trigger_delayed_bhabha"] = 0;
165 calculationResult[
"l1_trigger_poisson"] = 0;
166 calculationResult[
"bha3d"] = 0;
167 calculationResult[
"bhapur"] = 0;
168 calculationResult[
"bhapur_lml1"] = 0;
172 calculationResult[
"l1_trg_NN_info"] = 0;
173 if (
m_bitsNN.isValid() and
m_bitsNN.getEntries() > 0) {calculationResult[
"l1_trg_NN_info"] = 1;}
175 calculationResult[
"true"] = 1;
176 calculationResult[
"false"] = 0;
183 TLorentzVector p4ofCOM;
184 p4ofCOM.SetPxPyPzE(0, 0, 0, boostrotate.
getCMSEnergy());
187 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracks = {
192 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracksWithoutZCut = {
199 if (not trackFitResult) {
205 if (trackFitResult->getHitPatternCDC().getNHits() == 0) {
210 const double z0 = trackFitResult->getZ0();
212 calculationResult[
"nTrkTight"] += 1;
216 const short charge = trackFitResult->getChargeSign();
221 const TLorentzVector& momentumLab = trackFitResult->get4Momentum();
222 const TLorentzVector momentumCMS = boostrotate.
rotateLabToCms() * momentumLab;
223 double pCMS = momentumCMS.Rho();
226 const double pT = trackFitResult->getTransverseMomentum();
227 const auto& currentMaximum = maximumPtTracksWithoutZCut.at(charge);
228 if (not currentMaximum or pT > currentMaximum->pT) {
231 newMaximum.
track = &track;
232 newMaximum.
pCMS = pCMS;
233 newMaximum.
pLab = momentumLab.Rho();
234 newMaximum.
p4CMS = momentumCMS;
235 newMaximum.
p4Lab = momentumLab;
236 maximumPtTracksWithoutZCut[charge] = newMaximum;
241 calculationResult[
"nTrkLoose"] += 1;
242 calculationResult[
"netChargeLoose"] += charge;
244 if (std::isnan(calculationResult[
"maximumPCMS"]) or pCMS > calculationResult[
"maximumPCMS"]) {
245 calculationResult[
"maximumPCMS"] = pCMS;
249 const double pTLoose = trackFitResult->getTransverseMomentum();
250 const auto& currentMaximumLoose = maximumPtTracks.at(charge);
251 if (not currentMaximumLoose or pTLoose > currentMaximumLoose->pT) {
253 newMaximum.
pT = pTLoose;
254 newMaximum.
track = &track;
255 newMaximum.
pCMS = pCMS;
256 newMaximum.
pLab = momentumLab.Rho();
257 newMaximum.
p4CMS = momentumCMS;
258 newMaximum.
p4Lab = momentumLab;
259 maximumPtTracks[charge] = newMaximum;
265 std::vector<SelectedECLCluster> selectedClusters;
268 const double time = cluster.getTime();
270 std::abs(time) > 200 or
275 const double dt99 = cluster.getDeltaTime99();
282 selectedCluster.
cluster = &cluster;
286 selectedCluster.
isTrack = cluster.isTrack();
288 selectedClusters.push_back(selectedCluster);
291 calculationResult[
"nElow"] += 1;
294 calculationResult[
"nEmedium"] += 1;
297 calculationResult[
"nEhigh"] += 1;
301 calculationResult[
"nVetoClust"] += 1;
306 const double thetaLab = selectedCluster.
p4Lab.Theta() * TMath::RadToDeg();
307 const double zmva = cluster.getZernikeMVA();
308 const bool photon = zmva > 0.5 and not selectedCluster.
isTrack;
309 const bool electron = zmva > 0.5 and selectedCluster.
isTrack;
313 calculationResult[
"chrgClust2GeV"] += 1;
316 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
317 if (isInAcceptance) {calculationResult[
"neutClust045GeVAcc"] += 1;}
318 const bool isInBarrel = 30. < thetaLab and thetaLab < 130.;
319 if (isInBarrel) {calculationResult[
"neutClust045GeVBarrel"] += 1;}
324 const bool notInHighBackgroundEndcapRegion = 18.5 < thetaLab and thetaLab < 139.3;
326 calculationResult[
"nE180Lab"] += 1;
330 calculationResult[
"nE300Lab"] += 1;
334 calculationResult[
"nE500Lab"] += 1;
337 if (selectedCluster.
energyCMS >
m_Ehigh and notInHighBackgroundEndcapRegion) {
338 calculationResult[
"nE2000CMS"] += 1;
343 calculationResult[
"nE250Lab"] += 1;
346 calculationResult[
"nE4000CMS"] += 1;
351 calculationResult[
"nEsingleClust"] += 1;
353 const bool barrelRegion = thetaLab > 45 and thetaLab < 115;
354 const bool extendedBarrelRegion = thetaLab > 30 and thetaLab < 130;
355 const bool endcapRegion = (thetaLab > 22 and thetaLab < 45) or (thetaLab > 115 and thetaLab < 145);
357 if (photon and barrelRegion) {
358 calculationResult[
"nEsinglePhotonBarrel"] += 1;
361 if (photon and extendedBarrelRegion) {
362 calculationResult[
"nEsinglePhotonExtendedBarrel"] += 1;
365 if (electron and barrelRegion) {
366 calculationResult[
"nEsingleElectronBarrel"] += 1;
369 if (electron and extendedBarrelRegion) {
370 calculationResult[
"nEsingleElectronExtendedBarrel"] += 1;
373 if (photon and endcapRegion) {
374 calculationResult[
"nEsinglePhotonEndcap"] += 1;
379 const bool reducedBarrelRegion = thetaLab > 44 and thetaLab < 98;
381 if (photon and reducedBarrelRegion) {
382 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] += 1;
388 const bool barrelRegion = thetaLab > 32 and thetaLab < 130;
389 const bool endcapRegion = (thetaLab > 22 and thetaLab < 32) or (thetaLab > 130 and thetaLab < 145);
390 const bool lowAngleRegion = thetaLab < 22 or thetaLab > 145;
392 if (not selectedCluster.
isTrack and barrelRegion) {
393 calculationResult[
"n2GeVNeutBarrel"] += 1;
395 if (not selectedCluster.
isTrack and endcapRegion) {
396 calculationResult[
"n2GeVNeutEndcap"] += 1;
398 if (selectedCluster.
isTrack and not lowAngleRegion) {
399 calculationResult[
"n2GeVChrg"] += 1;
401 if (lowAngleRegion) {
402 calculationResult[
"nEhighLowAng"] += 1;
404 if (photon and barrelRegion) {
405 calculationResult[
"n2GeVPhotonBarrel"] += 1;
407 if (photon and endcapRegion) {
408 calculationResult[
"n2GeVPhotonEndcap"] += 1;
412 std::sort(selectedClusters.begin(), selectedClusters.end(), [](
const auto & lhs,
const auto & rhs) {
413 return lhs.energyCMS > rhs.energyCMS;
417 for (
short charge : { -1, 1}) {
418 auto& maximumPtTrack = maximumPtTracks.at(charge);
419 if (not maximumPtTrack) {
425 for (
auto& cluster : maximumPtTrack->track->getRelationsTo<
ECLCluster>()) {
430 maximumPtTrack->clusterEnergySumCMS =
431 maximumPtTrack->clusterEnergySumLab * maximumPtTrack->pCMS / maximumPtTrack->pLab;
434 if (maximumPtTrack->clusterEnergySumCMS > 4.5) {
435 calculationResult[
"ee1leg"] = 1;
439 if (maximumPtTrack->pCMS > 3 and maximumPtTrack->clusterEnergySumLab > 0. and maximumPtTrack->clusterEnergySumLab < 1.) {
440 calculationResult[
"singleMuon"] = 1;
445 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
449 double dphi = std::abs(negativeTrack.
p4CMS.Phi() - positiveTrack.
p4CMS.Phi()) * TMath::RadToDeg();
456 const double negativeP = negativeTrack.
pCMS;
459 const double positiveP = positiveTrack.
pCMS;
462 const double thetaSum = (negativeTrack.
p4CMS.Theta() + positiveTrack.
p4CMS.Theta()) * TMath::RadToDeg();
463 const double dthetaSum = std::abs(thetaSum - 180);
464 const auto back2back = dphi > 175 and dthetaSum < 15;
465 if (back2back and negativeClusterSum > 3 and positiveClusterSum > 3 and
466 (negativeClusterSum > 4.5 or positiveClusterSum > 4.5)) {
467 calculationResult[
"ee2leg"] = 1;
471 if (back2back and ((negativeClusterSum > 4.5 and positiveP > 3) or (positiveClusterSum > 4.5 and negativeP > 3))) {
472 calculationResult[
"ee1leg1trk"] = 1;
477 if ((negativeClusterSum > 4.5 and positiveClusterSum > 0.8 * positiveP) or
478 (positiveClusterSum > 4.5 and negativeClusterSum > 0.8 * negativeP)) {
479 calculationResult[
"ee1leg1e"] = 1;
483 const TLorentzVector p4Miss = p4ofCOM - negativeTrack.
p4CMS - positiveTrack.
p4CMS;
484 const double pmissTheta = p4Miss.Theta() * TMath::RadToDeg();
485 const double pmissp = p4Miss.Rho();
486 const double relMissAngle0 = negativeTrack.
p4CMS.Angle(p4Miss.Vect()) * TMath::RadToDeg();
487 const double relMissAngle1 = positiveTrack.
p4CMS.Angle(p4Miss.Vect()) * TMath::RadToDeg();
489 const bool electronEP = positiveClusterSum > 0.8 * positiveP or negativeClusterSum > 0.8 * negativeP;
490 const bool notMuonPair = negativeClusterSumLab > 1 or positiveClusterSumLab > 1;
491 const double highp = std::max(negativeP, positiveP);
492 const double lowp = std::min(negativeP, positiveP);
493 const bool lowEdep = negativeClusterSumLab < 0.5 and positiveClusterSumLab < 0.5;
496 if (calculationResult[
"maximumPCMS"] < 2 and dphi > 160 and (pmissTheta < 25. or pmissTheta > 155.)) {
497 calculationResult[
"eexxSelect"] = 1;
499 calculationResult[
"eeee"] = 1;
501 calculationResult[
"eemm"] = 1;
504 if (1. < negativeP and 1. < positiveP and 2 == calculationResult[
"nTrkLoose"] and
505 calculationResult[
"nTrkTight"] >= 1 and dphi < 170. and
506 10. < pmissTheta and pmissTheta < 170. and 1. < pmissp and electronEP) {
507 calculationResult[
"radBhabha"] = 1;
510 if (2. < negativeP and 2. < positiveP and 2 == calculationResult[
"nTrkLoose"] and
511 calculationResult[
"nTrkTight"] >= 1 and 175. < dphi and
512 (pmissTheta < 5. or pmissTheta > 175.) and electronEP) {
513 calculationResult[
"isrRadBhabha"] = 1;
515 if ((pmissTheta < 20. or pmissTheta > 160.) and
516 ((calculationResult[
"maximumPCMS"] < 1.2 and dphi > 150.) or
517 (calculationResult[
"maximumPCMS"] < 2. and 175. < dphi))) {
518 calculationResult[
"eexx"] = 1;
520 if (calculationResult[
"nTrkLoose"] == 2 and highp > 4.5 and notMuonPair and pmissp > 1. and
521 (relMissAngle0 < 5. or relMissAngle1 < 5.)) {
522 calculationResult[
"eeBrem"] = 1;
525 if (calculationResult[
"nTrkLoose"] == 2 and highp > 4.5 and lowEdep and dphi > 175. and 175. < thetaSum and
527 calculationResult[
"muonPairV"] = 1;
529 if (3. < highp and 2.5 < lowp and 165. < dphi and
530 ((negativeClusterSumLab > 0. and negativeClusterSumLab < 1.) or
531 (positiveClusterSumLab > 0. and positiveClusterSumLab < 1.))) {
532 calculationResult[
"selectmumu"] = 1;
536 if (selectedClusters.size() >= 2) {
541 double dphi = std::abs(firstCluster.
p4CMS.Phi() - secondCluster.
p4CMS.Phi()) * TMath::RadToDeg();
545 double thetaSum = (firstCluster.
p4CMS.Theta() + secondCluster.
p4CMS.Theta()) * TMath::RadToDeg();
546 double dthetaSum = std::abs(thetaSum - 180);
549 calculationResult[
"dphiCmsClust"] = dphi;
550 for (
int ic = 0; ic < 2; ic++) {
551 const double thetaLab = selectedClusters[ic].p4Lab.Theta() * TMath::RadToDeg();
552 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
553 const ECLCluster* cluster = selectedClusters[ic].cluster;
554 const double zmva = cluster->getZernikeMVA();
555 const bool photon = zmva > 0.5 and not selectedClusters[ic].isTrack;
556 if (isInAcceptance and photon) {calculationResult[
"nMaxEPhotonAcc"] += 1;}
559 const double firstEnergy = firstCluster.
p4CMS.E();
560 const double secondEnergy = secondCluster.
p4CMS.E();
562 const bool highEnergetic = firstEnergy > 3 and secondEnergy > 3 and (firstEnergy > 4.5 or secondEnergy > 4.5);
564 if (dphi > 160 and dphi < 178 and dthetaSum < 15 and highEnergetic) {
565 calculationResult[
"ee2clst"] = 1;
568 if (dphi > 178 and dthetaSum < 15 and highEnergetic) {
569 calculationResult[
"gg2clst"] = 1;
572 if ((calculationResult[
"ee2clst"] == 1 or calculationResult[
"gg2clst"] == 1) and
573 calculationResult[
"ee1leg"] == 1) {
574 calculationResult[
"ee1leg1clst"] = 1;
577 const double Elab0 = firstCluster.
p4Lab.E();
578 const double Elab1 = secondCluster.
p4Lab.E();
581 if (firstEnergy > 2 and secondEnergy > 2) {
582 const double thetaLab0 = firstCluster.
p4Lab.Theta() * TMath::RadToDeg();
583 const double thetaLab1 = secondCluster.
p4Lab.Theta() * TMath::RadToDeg();
585 const bool barrel0 = 32. < thetaLab0 and thetaLab0 < 130.;
586 const bool barrel1 = 32. < thetaLab1 and thetaLab1 < 130.;
587 const bool oneClustersAbove4 = firstEnergy > 4 or secondEnergy > 4;
588 const bool oneIsNeutral = not firstCluster.
isTrack or not secondCluster.
isTrack;
589 const bool bothAreNeutral = not firstCluster.
isTrack and not secondCluster.
isTrack;
590 const bool oneIsBarrel = barrel0 or barrel1;
591 const bool dphiCutExtraLoose = dphi > 175;
592 const bool dphiCutLoose = dphi > 177;
593 const bool dphiCutTight = dphi > 177.5;
595 if (dphiCutExtraLoose and oneIsNeutral and oneIsBarrel) {
596 calculationResult[
"ggBarrelVL"] = 1;
598 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and oneIsBarrel) {
599 calculationResult[
"ggBarrelLoose"] = 1;
601 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and oneIsBarrel) {
602 calculationResult[
"ggBarrelTight"] = 1;
604 if (dphiCutExtraLoose and oneIsNeutral and not oneIsBarrel) {
605 calculationResult[
"ggEndcapVL"] = 1;
607 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and not oneIsBarrel) {
608 calculationResult[
"ggEndcapLoose"] = 1;
610 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and not oneIsBarrel) {
611 calculationResult[
"ggEndcapTight"] = 1;
615 const double minEnergy = std::min(Elab0, Elab1);
616 const double maxEnergy = std::max(Elab0, Elab1);
617 if (dphi > 155 and thetaSum > 165 and thetaSum < 195 and minEnergy > 0.15 and minEnergy < 0.5 and
618 maxEnergy > 0.15 and maxEnergy < 0.5) {
619 calculationResult[
"muonPairECL"] = 1;
626 double thetaFlatten = 0;
629 for (
short charge : { -1, 1}) {
630 const auto& maximumPtTrack = maximumPtTracks.at(charge);
631 if (not maximumPtTrack) {
635 if (maximumPtTrack->clusterEnergySumCMS > 1.5) {
637 double tempFlatten = 0.;
639 double tempInvMass = (maximumPtTrack->p4Lab + cluster.p4Lab).M();
640 if (tempInvMass > invMass) {
641 invMass = tempInvMass;
643 tempFlatten = cluster.p4Lab.Theta() * TMath::RadToDeg();
648 tempFlatten = maximumPtTrack->p4Lab.Theta() * TMath::RadToDeg();
650 if (invMass > 5.29) {
651 calculationResult[
"selectee1leg1clst"] = 1;
652 thetaFlatten = tempFlatten;
658 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
661 const double invMass = (negativeTrack.
p4Lab + positiveTrack.
p4Lab).M();
663 calculationResult[
"selectee1leg1trk"] = 1;
666 thetaFlatten = negativeTrack.
p4Lab.Theta() * TMath::RadToDeg();
671 if ((invMass > 9.) and (missNegClust or missPosClust)) {
672 calculationResult[
"eeOneClust"] = 1;
676 if (calculationResult[
"selectee1leg1trk"] == 1 or calculationResult[
"selectee1leg1clst"] == 1) {
677 for (
int iflat = 0; iflat < 9; iflat++) {
678 const std::string& eeFlatName =
"eeFlat" + std::to_string(iflat);
679 calculationResult[eeFlatName] =
680 thetaFlatten > flatBoundaries[iflat] and thetaFlatten < flatBoundaries[iflat + 1];
681 if (calculationResult[eeFlatName]) {
682 calculationResult[
"selectee"] = 1;
688 if (calculationResult[
"nTrkLoose"] == 1 and calculationResult[
"maximumPCMS"] > 0.8 and selectedClusters.size() >= 2) {
690 decltype(selectedClusters) selectedSingleTagClusters(selectedClusters.size());
691 auto lastItem = std::copy_if(selectedClusters.begin(), selectedClusters.end(), selectedSingleTagClusters.begin(),
693 const bool isNeutralCluster = not cluster.isTrack;
694 const bool hasEnoughEnergy = cluster.energyLab > 0.1;
695 const double clusterThetaLab = cluster.p4Lab.Theta() * TMath::RadToDeg();
696 const bool isInAcceptance = 17 < clusterThetaLab and clusterThetaLab < 150.;
697 return isNeutralCluster and hasEnoughEnergy and isInAcceptance;
699 selectedSingleTagClusters.resize(std::distance(selectedSingleTagClusters.begin(), lastItem));
701 if (selectedSingleTagClusters.size() >= 2) {
703 const auto& track = maximumPtTracks.at(-1) ? *maximumPtTracks.at(-1) : *maximumPtTracks.at(1);
705 const auto& firstCluster = selectedSingleTagClusters[0];
706 const auto& secondCluster = selectedSingleTagClusters[1];
708 const TLorentzVector trackP4CMS = track.p4CMS;
709 const TLorentzVector pi0P4CMS = firstCluster.p4CMS + secondCluster.p4CMS;
711 const bool passPi0ECMS = pi0P4CMS.E() > 1. and pi0P4CMS.E() < 0.525 * p4ofCOM.M();
712 const double thetaSumCMS = (pi0P4CMS.Theta() + trackP4CMS.Theta()) * TMath::RadToDeg();
713 const bool passThetaSum = thetaSumCMS < 170. or thetaSumCMS > 190.;
715 double dphiCMS = std::abs(trackP4CMS.Phi() - pi0P4CMS.Phi()) * TMath::RadToDeg();
717 dphiCMS = 360 - dphiCMS;
719 const bool passdPhi = dphiCMS > 160.;
721 if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() < 0.7) {
722 calculationResult[
"singleTagLowMass"] = 1;
723 }
else if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() > 0.7) {
724 calculationResult[
"singleTagHighMass"] = 1;
732 const auto negTrack = maximumPtTracksWithoutZCut.at(-1);
733 const auto posTrack = maximumPtTracksWithoutZCut.at(1);
735 if (negTrack and posTrack) {
737 const double maxNegpT = negTrack->pT;
738 const double maxPospT = posTrack->pT;
740 auto accumulatePhotonEnergy = [](
double result,
const auto & cluster) {
745 const auto& clustersOfNegTrack = negTrack->track->getRelationsTo<
ECLCluster>();
748 const double maxClusterENeg = std::accumulate(clustersOfNegTrack.begin(), clustersOfNegTrack.end(), 0.0, accumulatePhotonEnergy);
749 const double maxClusterEPos = std::accumulate(clustersOfPosTrack.begin(), clustersOfPosTrack.end(), 0.0, accumulatePhotonEnergy);
751 const TLorentzVector& momentumLabNeg(negTrack->p4Lab);
752 const TLorentzVector& momentumLabPos(posTrack->p4Lab);
754 const double& z0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
755 const double& d0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
756 const double& z0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
757 const double& d0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
764 double dphiLab = std::abs(momentumLabNeg.Phi() - momentumLabPos.Phi()) * TMath::RadToDeg();
766 dphiLab = 360 - dphiLab;
769 const double thetaSumLab = (momentumLabNeg.Theta() + momentumLabPos.Theta()) * TMath::RadToDeg();
771 constexpr
double phiBackToBackTolerance = 2.;
772 constexpr
double thetaBackToBackTolerance = 2.;
773 if ((180 - dphiLab) < phiBackToBackTolerance and std::abs(180 - thetaSumLab) < thetaBackToBackTolerance) {
774 calculationResult[
"cosmic"] = 1;