8#include <hlt/softwaretrigger/calculations/FilterCalculator.h>
9#include <hlt/softwaretrigger/calculations/utilities.h>
11#include <Math/Vector3D.h>
12#include <Math/Vector4D.h>
13#include <Math/VectorUtil.h>
15#include <mdst/dataobjects/TrackFitResult.h>
16#include <mdst/dataobjects/HitPatternCDC.h>
18#include <analysis/dataobjects/Particle.h>
19#include <analysis/VertexFitting/KFit/VertexFitKFit.h>
21#include <framework/logging/Logger.h>
29using namespace SoftwareTrigger;
46 ROOT::Math::PxPyPzEVector
p4CMS;
48 ROOT::Math::PxPyPzEVector
p4Lab;
60 ROOT::Math::PxPyPzEVector
p4CMS;
62 ROOT::Math::PxPyPzEVector
p4Lab;
70const double flatBoundaries[10] = {0., 19., 22., 25., 30., 35., 45., 60., 90., 180.};
88 calculationResult[
"nTrkLoose"] = 0;
89 calculationResult[
"nTrkTight"] = 0;
90 calculationResult[
"ee2leg"] = 0;
91 calculationResult[
"nEmedium"] = 0;
92 calculationResult[
"nElow"] = 0;
93 calculationResult[
"nEhigh"] = 0;
94 calculationResult[
"nE180Lab"] = 0;
95 calculationResult[
"nE300Lab"] = 0;
96 calculationResult[
"nE500Lab"] = 0;
97 calculationResult[
"nE2000CMS"] = 0;
98 calculationResult[
"nE4000CMS"] = 0;
99 calculationResult[
"nE250Lab"] = 0;
100 calculationResult[
"nMaxEPhotonAcc"] = 0;
101 calculationResult[
"dphiCmsClust"] = NAN;
103 calculationResult[
"netChargeLoose"] = 0;
104 calculationResult[
"maximumPCMS"] = NAN;
105 calculationResult[
"maximumPLab"] = NAN;
106 calculationResult[
"eexx"] = 0;
107 calculationResult[
"ee1leg1trk"] = 0;
108 calculationResult[
"nEhighLowAng"] = 0;
109 calculationResult[
"nEsingleClust"] = 0;
110 calculationResult[
"nEsinglePhotonBarrel"] = 0;
111 calculationResult[
"nEsinglePhotonExtendedBarrel"] = 0;
112 calculationResult[
"nEsinglePhotonEndcap"] = 0;
113 calculationResult[
"nEsingleElectronBarrel"] = 0;
114 calculationResult[
"nEsingleElectronExtendedBarrel"] = 0;
115 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] = 0;
116 calculationResult[
"nVetoClust"] = 0;
117 calculationResult[
"chrgClust2GeV"] = 0;
118 calculationResult[
"neutClust045GeVAcc"] = 0;
119 calculationResult[
"neutClust045GeVBarrel"] = 0;
120 calculationResult[
"singleTagLowMass"] = 0;
121 calculationResult[
"singleTagHighMass"] = 0;
122 calculationResult[
"n2GeVNeutBarrel"] = 0;
123 calculationResult[
"n2GeVNeutEndcap"] = 0;
124 calculationResult[
"n2GeVChrg"] = 0;
125 calculationResult[
"n2GeVPhotonBarrel"] = 0;
126 calculationResult[
"n2GeVPhotonEndcap"] = 0;
127 calculationResult[
"ee1leg"] = 0;
128 calculationResult[
"ee1leg1clst"] = 0;
129 calculationResult[
"ee1leg1e"] = 0;
130 calculationResult[
"ee2clst"] = 0;
131 calculationResult[
"gg2clst"] = 0;
132 calculationResult[
"eeee"] = 0;
133 calculationResult[
"eemm"] = 0;
134 calculationResult[
"eexxSelect"] = 0;
135 calculationResult[
"radBhabha"] = 0;
136 calculationResult[
"eeBrem"] = 0;
137 calculationResult[
"isrRadBhabha"] = 0;
138 calculationResult[
"muonPairECL"] = 0;
139 calculationResult[
"ggHighPt"] = 0;
140 calculationResult[
"selectee1leg1trk"] = 0;
141 calculationResult[
"selectee1leg1clst"] = 0;
142 calculationResult[
"selectee"] = 0;
143 calculationResult[
"ggBarrelVL"] = 0;
144 calculationResult[
"ggBarrelLoose"] = 0;
145 calculationResult[
"ggBarrelTight"] = 0;
146 calculationResult[
"ggEndcapVL"] = 0;
147 calculationResult[
"ggEndcapLoose"] = 0;
148 calculationResult[
"ggEndcapTight"] = 0;
149 calculationResult[
"muonPairV"] = 0;
150 calculationResult[
"selectmumu"] = 0;
151 calculationResult[
"singleMuon"] = 0;
152 calculationResult[
"cosmic"] = 0;
153 calculationResult[
"displacedVertex"] = 0;
154 calculationResult[
"eeFlat0"] = 0;
155 calculationResult[
"eeFlat1"] = 0;
156 calculationResult[
"eeFlat2"] = 0;
157 calculationResult[
"eeFlat3"] = 0;
158 calculationResult[
"eeFlat4"] = 0;
159 calculationResult[
"eeFlat5"] = 0;
160 calculationResult[
"eeFlat6"] = 0;
161 calculationResult[
"eeFlat7"] = 0;
162 calculationResult[
"eeFlat8"] = 0;
163 calculationResult[
"eeOneClust"] = 0;
166 calculationResult[
"nTrkLooseB"] = 0;
167 calculationResult[
"nTrkTightB"] = 0;
168 calculationResult[
"maximumPCMSB"] = NAN;
169 calculationResult[
"netChargeLooseB"] = 0;
170 calculationResult[
"muonPairVB"] = 0;
171 calculationResult[
"eeBremB"] = 0;
172 calculationResult[
"singleTagLowMassB"] = 0;
173 calculationResult[
"singleTagHighMassB"] = 0;
174 calculationResult[
"radBhabhaB"] = 0;
185 }
catch (
const std::exception&) {
191 }
catch (
const std::exception&) {
197 }
catch (
const std::exception&) {
203 }
catch (
const std::exception&) {
209 }
catch (
const std::exception&) {
212 calculationResult[
"bha3d"] = bha3d;
213 calculationResult[
"bhapur"] = bhapurPsnm;
214 calculationResult[
"bhapur_lml1"] = lml1 and bhapurFtdl;
215 calculationResult[
"l1_bit_f"] = l1_bit_f;
217 calculationResult[
"l1_trigger_random"] = 1;
218 calculationResult[
"l1_trigger_delayed_bhabha"] = 0;
219 calculationResult[
"l1_trigger_poisson"] = 0;
220 calculationResult[
"bha3d"] = 0;
221 calculationResult[
"bhapur"] = 0;
222 calculationResult[
"bhapur_lml1"] = 0;
223 calculationResult[
"l1_bit_f"] = 0;
227 calculationResult[
"l1_trg_NN_info"] = 0;
228 if (
m_bitsNN.isValid() and
m_bitsNN.getEntries() > 0) {calculationResult[
"l1_trg_NN_info"] = 1;}
230 calculationResult[
"true"] = 1;
231 calculationResult[
"false"] = 0;
236 const ROOT::Math::XYZVector clustervertex = cUtil.
GetIPPosition();
238 ROOT::Math::PxPyPzEVector p4ofCOM;
239 p4ofCOM.SetPxPyPzE(0, 0, 0, boostrotate.
getCMSEnergy());
242 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracks = {
247 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracksWithoutZCut = {
254 if (not trackFitResult) {
265 const double z0 = trackFitResult->
getZ0();
267 calculationResult[
"nTrkTight"] += 1;
276 const ROOT::Math::PxPyPzEVector& momentumLab = trackFitResult->
get4Momentum();
277 const ROOT::Math::PxPyPzEVector momentumCMS = boostrotate.
rotateLabToCms() * momentumLab;
278 double pCMS = momentumCMS.P();
279 double pLab = momentumLab.P();
283 const auto& currentMaximum = maximumPtTracksWithoutZCut.at(charge);
284 if (not currentMaximum or pT > currentMaximum->pT) {
287 newMaximum.
track = &track;
288 newMaximum.
pCMS = pCMS;
289 newMaximum.
pLab = pLab;
290 newMaximum.
p4CMS = momentumCMS;
291 newMaximum.
p4Lab = momentumLab;
292 maximumPtTracksWithoutZCut[charge] = newMaximum;
297 calculationResult[
"nTrkLoose"] += 1;
298 calculationResult[
"netChargeLoose"] += charge;
300 if (std::isnan(calculationResult[
"maximumPCMS"]) or pCMS > calculationResult[
"maximumPCMS"]) {
301 calculationResult[
"maximumPCMS"] = pCMS;
304 if (std::isnan(calculationResult[
"maximumPLab"]) or pLab > calculationResult[
"maximumPLab"]) {
305 calculationResult[
"maximumPLab"] = pLab;
310 const auto& currentMaximumLoose = maximumPtTracks.at(charge);
311 if (not currentMaximumLoose or pTLoose > currentMaximumLoose->pT) {
313 newMaximum.
pT = pTLoose;
314 newMaximum.
track = &track;
315 newMaximum.
pCMS = pCMS;
316 newMaximum.
pLab = momentumLab.P();
317 newMaximum.
p4CMS = momentumCMS;
318 newMaximum.
p4Lab = momentumLab;
319 maximumPtTracks[charge] = newMaximum;
326 if (std::abs(z0) < 1.) {calculationResult[
"nTrkTightB"] += 1;}
327 if (std::abs(z0) < 5.) {
328 calculationResult[
"nTrkLooseB"] += 1;
329 calculationResult[
"netChargeLooseB"] += charge;
330 if (std::isnan(calculationResult[
"maximumPCMSB"]) or pCMS > calculationResult[
"maximumPCMSB"]) {
331 calculationResult[
"maximumPCMSB"] = pCMS;
341 std::vector<SelectedECLCluster> selectedClusters;
344 const double time = cluster.getTime();
346 std::abs(time) > 200 or
351 const double dt99 = cluster.getDeltaTime99();
358 selectedCluster.
cluster = &cluster;
362 selectedCluster.
isTrack = cluster.isTrack();
364 selectedClusters.push_back(selectedCluster);
367 calculationResult[
"nElow"] += 1;
370 calculationResult[
"nEmedium"] += 1;
373 calculationResult[
"nEhigh"] += 1;
377 calculationResult[
"nVetoClust"] += 1;
382 const double thetaLab = selectedCluster.
p4Lab.Theta() * TMath::RadToDeg();
383 const double zmva = cluster.getZernikeMVA();
384 const bool photon = zmva > 0.5 and not selectedCluster.
isTrack;
385 const bool electron = zmva > 0.5 and selectedCluster.
isTrack;
389 calculationResult[
"chrgClust2GeV"] += 1;
392 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
393 if (isInAcceptance) {calculationResult[
"neutClust045GeVAcc"] += 1;}
394 const bool isInBarrel = 30. < thetaLab and thetaLab < 130.;
395 if (isInBarrel) {calculationResult[
"neutClust045GeVBarrel"] += 1;}
400 const bool notInHighBackgroundEndcapRegion = 18.5 < thetaLab and thetaLab < 139.3;
402 calculationResult[
"nE180Lab"] += 1;
406 calculationResult[
"nE300Lab"] += 1;
410 calculationResult[
"nE500Lab"] += 1;
413 if (selectedCluster.
energyCMS >
m_Ehigh and notInHighBackgroundEndcapRegion) {
414 calculationResult[
"nE2000CMS"] += 1;
419 calculationResult[
"nE250Lab"] += 1;
422 calculationResult[
"nE4000CMS"] += 1;
427 calculationResult[
"nEsingleClust"] += 1;
429 const bool barrelRegion = thetaLab > 45 and thetaLab < 115;
430 const bool extendedBarrelRegion = thetaLab > 30 and thetaLab < 130;
431 const bool endcapRegion = (thetaLab > 22 and thetaLab < 45) or (thetaLab > 115 and thetaLab < 145);
433 if (photon and barrelRegion) {
434 calculationResult[
"nEsinglePhotonBarrel"] += 1;
437 if (photon and extendedBarrelRegion) {
438 calculationResult[
"nEsinglePhotonExtendedBarrel"] += 1;
441 if (electron and barrelRegion) {
442 calculationResult[
"nEsingleElectronBarrel"] += 1;
445 if (electron and extendedBarrelRegion) {
446 calculationResult[
"nEsingleElectronExtendedBarrel"] += 1;
449 if (photon and endcapRegion) {
450 calculationResult[
"nEsinglePhotonEndcap"] += 1;
455 const bool reducedBarrelRegion = thetaLab > 44 and thetaLab < 98;
457 if (photon and reducedBarrelRegion) {
458 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] += 1;
464 const bool barrelRegion = thetaLab > 32 and thetaLab < 130;
465 const bool endcapRegion = (thetaLab > 22 and thetaLab < 32) or (thetaLab > 130 and thetaLab < 145);
466 const bool lowAngleRegion = thetaLab < 22 or thetaLab > 145;
468 if (not selectedCluster.
isTrack and barrelRegion) {
469 calculationResult[
"n2GeVNeutBarrel"] += 1;
471 if (not selectedCluster.
isTrack and endcapRegion) {
472 calculationResult[
"n2GeVNeutEndcap"] += 1;
474 if (selectedCluster.
isTrack and not lowAngleRegion) {
475 calculationResult[
"n2GeVChrg"] += 1;
477 if (lowAngleRegion) {
478 calculationResult[
"nEhighLowAng"] += 1;
480 if (photon and barrelRegion) {
481 calculationResult[
"n2GeVPhotonBarrel"] += 1;
483 if (photon and endcapRegion) {
484 calculationResult[
"n2GeVPhotonEndcap"] += 1;
490 std::sort(selectedClusters.begin(), selectedClusters.end(), [](
const auto & lhs,
const auto & rhs) {
491 return lhs.energyCMS > rhs.energyCMS;
495 for (
short charge : { -1, 1}) {
496 auto& maximumPtTrack = maximumPtTracks.at(charge);
497 if (not maximumPtTrack) {
503 for (
auto& cluster : maximumPtTrack->track->getRelationsTo<
ECLCluster>()) {
508 maximumPtTrack->clusterEnergySumCMS =
509 maximumPtTrack->clusterEnergySumLab * maximumPtTrack->pCMS / maximumPtTrack->pLab;
512 if (maximumPtTrack->clusterEnergySumCMS > 4.5) {
513 calculationResult[
"ee1leg"] = 1;
517 if (maximumPtTrack->pCMS > 3 and maximumPtTrack->clusterEnergySumLab > 0. and maximumPtTrack->clusterEnergySumLab < 1.) {
518 calculationResult[
"singleMuon"] = 1;
523 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
527 double dphi = std::abs(negativeTrack.
p4CMS.Phi() - positiveTrack.
p4CMS.Phi()) * TMath::RadToDeg();
534 const double negativeP = negativeTrack.
pCMS;
537 const double positiveP = positiveTrack.
pCMS;
540 const double thetaSum = (negativeTrack.
p4CMS.Theta() + positiveTrack.
p4CMS.Theta()) * TMath::RadToDeg();
541 const double dthetaSum = std::abs(thetaSum - 180);
542 const auto back2back = dphi > 175 and dthetaSum < 15;
543 if (back2back and negativeClusterSum > 3 and positiveClusterSum > 3 and
544 (negativeClusterSum > 4.5 or positiveClusterSum > 4.5)) {
545 calculationResult[
"ee2leg"] = 1;
549 if (back2back and ((negativeClusterSum > 4.5 and positiveP > 3) or (positiveClusterSum > 4.5 and negativeP > 3))) {
550 calculationResult[
"ee1leg1trk"] = 1;
555 if ((negativeClusterSum > 4.5 and positiveClusterSum > 0.8 * positiveP) or
556 (positiveClusterSum > 4.5 and negativeClusterSum > 0.8 * negativeP)) {
557 calculationResult[
"ee1leg1e"] = 1;
561 const ROOT::Math::PxPyPzEVector p4Miss = p4ofCOM - negativeTrack.
p4CMS - positiveTrack.
p4CMS;
562 const double pmissTheta = p4Miss.Theta() * TMath::RadToDeg();
563 const double pmissp = p4Miss.P();
564 const double relMissAngle0 = ROOT::Math::VectorUtil::Angle(negativeTrack.
p4CMS, p4Miss) * TMath::RadToDeg();
565 const double relMissAngle1 = ROOT::Math::VectorUtil::Angle(positiveTrack.
p4CMS, p4Miss) * TMath::RadToDeg();
567 const bool electronEP = positiveClusterSum > 0.8 * positiveP or negativeClusterSum > 0.8 * negativeP;
568 const bool notMuonPair = negativeClusterSumLab > 1 or positiveClusterSumLab > 1;
569 const double highp = std::max(negativeP, positiveP);
570 const double lowp = std::min(negativeP, positiveP);
571 const bool lowEdep = negativeClusterSumLab < 0.5 and positiveClusterSumLab < 0.5;
574 if (calculationResult[
"maximumPCMS"] < 2 and dphi > 160 and (pmissTheta < 25. or pmissTheta > 155.)) {
575 calculationResult[
"eexxSelect"] = 1;
577 calculationResult[
"eeee"] = 1;
579 calculationResult[
"eemm"] = 1;
584 if ((pmissTheta < 20. or pmissTheta > 160.) and
585 ((calculationResult[
"maximumPCMS"] < 1.2 and dphi > 150.) or
586 (calculationResult[
"maximumPCMS"] < 2. and 175. < dphi))) {
587 calculationResult[
"eexx"] = 1;
591 if (negativeP > 1. and pmissTheta > 10. and pmissTheta < 170. and positiveP > 1. and dphi < 170. and pmissp > 1. and electronEP) {
592 if (calculationResult[
"nTrkLoose"] == 2 and calculationResult[
"nTrkTight"] >= 1) {
593 calculationResult[
"radBhabha"] = 1;
595 if (calculationResult[
"nTrkLooseB"] == 2 and calculationResult[
"nTrkTightB"] >= 1) {
596 calculationResult[
"radBhabhaB"] = 1;
601 if (negativeP > 2. and positiveP > 2. and 2 == calculationResult[
"nTrkLoose"] and
602 calculationResult[
"nTrkTight"] >= 1 and dphi > 175. and
603 (pmissTheta < 5. or pmissTheta > 175.) and electronEP) {
604 calculationResult[
"isrRadBhabha"] = 1;
608 if (highp > 4.5 and notMuonPair and pmissp > 1. and (relMissAngle0 < 5. or relMissAngle1 < 5.)) {
609 if (calculationResult[
"nTrkLoose"] == 2) { calculationResult[
"eeBrem"] = 1;}
610 if (calculationResult[
"nTrkLooseB"] >= 1) { calculationResult[
"eeBremB"] = 1;}
614 if (highp > 4.5 and lowEdep and thetaSum > 175. and thetaSum < 185. and dphi > 175.) {
615 if (calculationResult[
"nTrkLoose"] == 2) {calculationResult[
"muonPairV"] = 1;}
616 if (calculationResult[
"nTrkLooseB"] == 2) {calculationResult[
"muonPairVB"] = 1;}
620 if (highp > 3. and lowp > 2.5 and dphi > 165. and
621 ((negativeClusterSumLab > 0. and negativeClusterSumLab < 1.) or
622 (positiveClusterSumLab > 0. and positiveClusterSumLab < 1.))) {
623 calculationResult[
"selectmumu"] = 1;
628 if (selectedClusters.size() >= 2) {
632 double dphi = std::abs(firstCluster.
p4CMS.Phi() - secondCluster.
p4CMS.Phi()) * TMath::RadToDeg();
636 double thetaSum = (firstCluster.
p4CMS.Theta() + secondCluster.
p4CMS.Theta()) * TMath::RadToDeg();
637 double dthetaSum = std::abs(thetaSum - 180);
640 calculationResult[
"dphiCmsClust"] = dphi;
641 for (
int ic = 0; ic < 2; ic++) {
642 const double thetaLab = selectedClusters[ic].p4Lab.Theta() * TMath::RadToDeg();
643 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
644 const ECLCluster* cluster = selectedClusters[ic].cluster;
645 const double zmva = cluster->getZernikeMVA();
646 const bool photon = zmva > 0.5 and not selectedClusters[ic].isTrack;
647 if (isInAcceptance and photon) {calculationResult[
"nMaxEPhotonAcc"] += 1;}
650 const double firstEnergy = firstCluster.
p4CMS.E();
651 const double secondEnergy = secondCluster.
p4CMS.E();
653 const bool highEnergetic = firstEnergy > 3 and secondEnergy > 3 and (firstEnergy > 4.5 or secondEnergy > 4.5);
655 if (dphi > 160 and dphi < 178 and dthetaSum < 15 and highEnergetic) {
656 calculationResult[
"ee2clst"] = 1;
659 if (dphi > 178 and dthetaSum < 15 and highEnergetic) {
660 calculationResult[
"gg2clst"] = 1;
663 if ((calculationResult[
"ee2clst"] == 1 or calculationResult[
"gg2clst"] == 1) and
664 calculationResult[
"ee1leg"] == 1) {
665 calculationResult[
"ee1leg1clst"] = 1;
668 const double Elab0 = firstCluster.
p4Lab.E();
669 const double Elab1 = secondCluster.
p4Lab.E();
672 if (firstEnergy > 2 and secondEnergy > 2) {
673 const double thetaLab0 = firstCluster.
p4Lab.Theta() * TMath::RadToDeg();
674 const double thetaLab1 = secondCluster.
p4Lab.Theta() * TMath::RadToDeg();
676 const bool barrel0 = 32. < thetaLab0 and thetaLab0 < 130.;
677 const bool barrel1 = 32. < thetaLab1 and thetaLab1 < 130.;
678 const bool oneClustersAbove4 = firstEnergy > 4 or secondEnergy > 4;
679 const bool oneIsNeutral = not firstCluster.
isTrack or not secondCluster.
isTrack;
680 const bool bothAreNeutral = not firstCluster.
isTrack and not secondCluster.
isTrack;
681 const bool oneIsBarrel = barrel0 or barrel1;
682 const bool dphiCutExtraLoose = dphi > 175;
683 const bool dphiCutLoose = dphi > 177;
684 const bool dphiCutTight = dphi > 177.5;
686 if (dphiCutExtraLoose and oneIsNeutral and oneIsBarrel) {
687 calculationResult[
"ggBarrelVL"] = 1;
689 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and oneIsBarrel) {
690 calculationResult[
"ggBarrelLoose"] = 1;
692 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and oneIsBarrel) {
693 calculationResult[
"ggBarrelTight"] = 1;
695 if (dphiCutExtraLoose and oneIsNeutral and not oneIsBarrel) {
696 calculationResult[
"ggEndcapVL"] = 1;
698 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and not oneIsBarrel) {
699 calculationResult[
"ggEndcapLoose"] = 1;
701 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and not oneIsBarrel) {
702 calculationResult[
"ggEndcapTight"] = 1;
706 const double minEnergy = std::min(Elab0, Elab1);
707 const double maxEnergy = std::max(Elab0, Elab1);
708 if (dphi > 155 and thetaSum > 165 and thetaSum < 195 and minEnergy > 0.15 and minEnergy < 0.5 and
709 maxEnergy > 0.15 and maxEnergy < 0.5) {
710 calculationResult[
"muonPairECL"] = 1;
714 const double thetaLab0 = firstCluster.
p4Lab.Theta() * TMath::RadToDeg();
715 const double thetaLab1 = secondCluster.
p4Lab.Theta() * TMath::RadToDeg();
716 const bool inHieRegion0 = thetaLab0 > 26. and thetaLab0 < 130.;
717 const bool inHieRegion1 = thetaLab1 > 26. and thetaLab1 < 130.;
718 const bool firstIsNeutral = not firstCluster.
isTrack;
719 const bool secondIsNeutral = not secondCluster.
isTrack;
721 if (secondEnergy > 0.3 and inHieRegion0 and inHieRegion1 and firstIsNeutral and secondIsNeutral) {
722 const ROOT::Math::PxPyPzEVector ggP4CMS = firstCluster.
p4CMS + secondCluster.
p4CMS;
723 if (ggP4CMS.pt() > 1.) {calculationResult[
"ggHighPt"] = 1;}
730 double thetaFlatten = 0;
733 for (
short charge : { -1, 1}) {
734 const auto& maximumPtTrack = maximumPtTracks.at(charge);
735 if (not maximumPtTrack) {
739 if (maximumPtTrack->clusterEnergySumCMS > 1.5) {
741 double tempFlatten = 0.;
743 double tempInvMass = (maximumPtTrack->p4Lab + cluster.p4Lab).M();
744 if (tempInvMass > invMass) {
745 invMass = tempInvMass;
747 tempFlatten = cluster.p4Lab.Theta() * TMath::RadToDeg();
752 tempFlatten = maximumPtTrack->p4Lab.Theta() * TMath::RadToDeg();
754 if (invMass > 5.29) {
755 calculationResult[
"selectee1leg1clst"] = 1;
756 thetaFlatten = tempFlatten;
762 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
765 const double invMass = (negativeTrack.
p4Lab + positiveTrack.
p4Lab).M();
767 calculationResult[
"selectee1leg1trk"] = 1;
770 thetaFlatten = negativeTrack.
p4Lab.Theta() * TMath::RadToDeg();
775 if ((invMass > 9.) and (missNegClust or missPosClust)) {
776 calculationResult[
"eeOneClust"] = 1;
780 if (calculationResult[
"selectee1leg1trk"] == 1 or calculationResult[
"selectee1leg1clst"] == 1) {
781 for (
int iflat = 0; iflat < 9; iflat++) {
782 const std::string& eeFlatName =
"eeFlat" + std::to_string(iflat);
783 calculationResult[eeFlatName] =
784 thetaFlatten > flatBoundaries[iflat] and thetaFlatten < flatBoundaries[iflat + 1];
785 if (calculationResult[eeFlatName]) {
786 calculationResult[
"selectee"] = 1;
792 if (calculationResult[
"nTrkLoose"] == 1 and calculationResult[
"maximumPCMS"] > 0.8 and selectedClusters.size() >= 2) {
794 decltype(selectedClusters) selectedSingleTagClusters(selectedClusters.size());
795 auto lastItem = std::copy_if(selectedClusters.begin(), selectedClusters.end(), selectedSingleTagClusters.begin(),
797 const bool isNeutralCluster = not cluster.isTrack;
798 const bool hasEnoughEnergy = cluster.energyLab > 0.1;
799 const double clusterThetaLab = cluster.p4Lab.Theta() * TMath::RadToDeg();
800 const bool isInAcceptance = 17 < clusterThetaLab and clusterThetaLab < 150.;
801 return isNeutralCluster and hasEnoughEnergy and isInAcceptance;
803 selectedSingleTagClusters.resize(std::distance(selectedSingleTagClusters.begin(), lastItem));
805 if (selectedSingleTagClusters.size() >= 2) {
807 const auto& track = maximumPtTracks.at(-1) ? *maximumPtTracks.at(-1) : *maximumPtTracks.at(1);
809 const auto& firstCluster = selectedSingleTagClusters[0];
810 const auto& secondCluster = selectedSingleTagClusters[1];
812 const ROOT::Math::PxPyPzEVector trackP4CMS = track.p4CMS;
813 const ROOT::Math::PxPyPzEVector pi0P4CMS = firstCluster.p4CMS + secondCluster.p4CMS;
815 const bool passPi0ECMS = pi0P4CMS.E() > 1. and pi0P4CMS.E() < 0.525 * p4ofCOM.M();
816 const double thetaSumCMS = (pi0P4CMS.Theta() + trackP4CMS.Theta()) * TMath::RadToDeg();
817 const bool passThetaSum = thetaSumCMS < 170. or thetaSumCMS > 190.;
819 double dphiCMS = std::abs(trackP4CMS.Phi() - pi0P4CMS.Phi()) * TMath::RadToDeg();
821 dphiCMS = 360 - dphiCMS;
823 const bool passdPhi = dphiCMS > 160.;
825 if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() < 0.7) {
826 calculationResult[
"singleTagLowMass"] = 1;
827 }
else if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() > 0.7) {
828 calculationResult[
"singleTagHighMass"] = 1;
834 if (calculationResult[
"nTrkLooseB"] == 1 and calculationResult[
"maximumPCMSB"] > 0.8 and selectedClusters.size() >= 2) {
836 decltype(selectedClusters) selectedSingleTagClusters(selectedClusters.size());
837 auto lastItem = std::copy_if(selectedClusters.begin(), selectedClusters.end(), selectedSingleTagClusters.begin(),
839 const bool isNeutralCluster = not cluster.isTrack;
840 const bool hasEnoughEnergy = cluster.energyLab > 0.1;
841 const double clusterThetaLab = cluster.p4Lab.Theta() * TMath::RadToDeg();
842 const bool isInAcceptance = 17 < clusterThetaLab and clusterThetaLab < 150.;
843 return isNeutralCluster and hasEnoughEnergy and isInAcceptance;
845 selectedSingleTagClusters.resize(std::distance(selectedSingleTagClusters.begin(), lastItem));
847 if (selectedSingleTagClusters.size() >= 2) {
849 const auto& track = maximumPtTracks.at(-1) ? *maximumPtTracks.at(-1) : *maximumPtTracks.at(1);
851 const auto& firstCluster = selectedSingleTagClusters[0];
852 const auto& secondCluster = selectedSingleTagClusters[1];
854 const ROOT::Math::PxPyPzEVector trackP4CMS = track.p4CMS;
855 const ROOT::Math::PxPyPzEVector pi0P4CMS = firstCluster.p4CMS + secondCluster.p4CMS;
857 const bool passPi0ECMS = pi0P4CMS.E() > 1. and pi0P4CMS.E() < 0.525 * p4ofCOM.M();
858 const double thetaSumCMS = (pi0P4CMS.Theta() + trackP4CMS.Theta()) * TMath::RadToDeg();
859 const bool passThetaSum = thetaSumCMS < 170. or thetaSumCMS > 190.;
861 double dphiCMS = std::abs(trackP4CMS.Phi() - pi0P4CMS.Phi()) * TMath::RadToDeg();
863 dphiCMS = 360 - dphiCMS;
865 const bool passdPhi = dphiCMS > 160.;
867 if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() < 0.7) {
868 calculationResult[
"singleTagLowMassB"] = 1;
869 }
else if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() > 0.7) {
870 calculationResult[
"singleTagHighMassB"] = 1;
878 const auto negTrack = maximumPtTracksWithoutZCut.at(-1);
879 const auto posTrack = maximumPtTracksWithoutZCut.at(1);
881 if (negTrack and posTrack) {
883 const double maxNegpT = negTrack->pT;
884 const double maxPospT = posTrack->pT;
886 auto accumulatePhotonEnergy = [](
double result,
const auto & cluster) {
891 const auto& clustersOfNegTrack = negTrack->track->getRelationsTo<
ECLCluster>();
894 const double maxClusterENeg = std::accumulate(clustersOfNegTrack.begin(), clustersOfNegTrack.end(), 0.0, accumulatePhotonEnergy);
895 const double maxClusterEPos = std::accumulate(clustersOfPosTrack.begin(), clustersOfPosTrack.end(), 0.0, accumulatePhotonEnergy);
897 const ROOT::Math::PxPyPzEVector& momentumLabNeg(negTrack->p4Lab);
898 const ROOT::Math::PxPyPzEVector& momentumLabPos(posTrack->p4Lab);
900 const double& z0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
901 const double& d0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
902 const double& z0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
903 const double& d0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
910 double dphiLab = std::abs(momentumLabNeg.Phi() - momentumLabPos.Phi()) * TMath::RadToDeg();
912 dphiLab = 360 - dphiLab;
915 const double thetaSumLab = (momentumLabNeg.Theta() + momentumLabPos.Theta()) * TMath::RadToDeg();
917 constexpr double phiBackToBackTolerance = 2.;
918 constexpr double thetaBackToBackTolerance = 2.;
919 if ((180 - dphiLab) < phiBackToBackTolerance and std::abs(180 - thetaSumLab) < thetaBackToBackTolerance) {
920 calculationResult[
"cosmic"] = 1;
928 if (maximumPtTracksWithoutZCut.at(-1) and maximumPtTracksWithoutZCut.at(1)) {
931 const auto nTrack = maximumPtTracksWithoutZCut.at(-1)->track;
934 const auto pTrack = maximumPtTracksWithoutZCut.at(1)->track;
944 const double chisq = vertexFit->
getCHIsq();
945 const int ndf = vertexFit->
getNDF();
946 const double vertexProb = TMath::Prob(chisq, ndf);
947 const auto vertexLocation = vertexFit->
getVertex();
948 const double vertexXY = vertexLocation.perp();
949 const double vertexTheta = vertexLocation.theta() * TMath::RadToDeg();
955 const ROOT::Math::PxPyPzEVector& momentumLabNeg(maximumPtTracksWithoutZCut.at(-1)->p4Lab);
956 const ROOT::Math::PxPyPzEVector& momentumLabPos(maximumPtTracksWithoutZCut.at(1)->p4Lab);
957 const double thetaSumLab = (momentumLabNeg.Theta() + momentumLabPos.Theta()) * TMath::RadToDeg();
958 double dPhiLab = std::abs(momentumLabNeg.Phi() - momentumLabPos.Phi()) * TMath::RadToDeg();
960 dPhiLab = 360 - dPhiLab;
962 const double backToBackTolerance = 10.;
963 const bool backToBackLab = std::abs(thetaSumLab - 180.) < backToBackTolerance and std::abs(dPhiLab - 180.) < backToBackTolerance;
966 const double minProbChiVertex = 0.005;
967 const double minXYVertex = 3.;
968 const double maxXYVertex = 60.;
969 const double minThetaVertex = 30.;
970 const double maxThetaVertex = 120.;
971 if (vertexProb > minProbChiVertex and vertexXY > minXYVertex and vertexXY < maxXYVertex and vertexTheta > minThetaVertex
972 and vertexTheta < maxThetaVertex
973 and not backToBackLab) {calculationResult[
"displacedVertex"] = 1;}
Class to provide momentum-related information from ECLClusters.
const ROOT::Math::PxPyPzEVector Get4MomentumFromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns four momentum vector.
const ROOT::Math::XYZVector GetIPPosition()
Returns default IP position from beam parameters.
static const ChargedStable pion
charged pion particle
@ c_nPhotons
CR is split into n photons (N1)
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
Class to store reconstructed particles.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
double m_EminLab
which lab energy defines nE180Lab
double m_reducedEsinglePhoton
which CMS energy defines nReducedEsingle clusters
StoreObjPtr< TRGSummary > m_l1Trigger
Store Object with the trigger result.
double m_E0min
which CMS energy defines nEmedium
void requireStoreArrays() override
Require the particle list. We do not need more here.
void doCalculation(SoftwareTriggerObject &calculationResult) override
Actually write out the variables into the map.
double m_goodMagneticRegionZ0
maximum z0 for well understood magnetic field (cm)
double m_cosmicMinPt
which LAB pt defines a cosmic
double m_EsinglePhoton
which CMS energy defines nEsingleClust
double m_E2min
which CMS energy defines nElow
double m_tightTrkZ0
which Z0 defines a tight track
StoreArray< Track > m_tracks
Store Array of the tracks to be used.
double m_EminLab3Cluster
which lab energy defines nE500Lab
double m_Ehigh
which CMS energy defines nEhigh
StoreArray< ECLCluster > m_eclClusters
Store Array of the ecl clusters to be used.
double m_EminLab4Cluster
which lab energy defines nE300Lab
StoreArray< CDCTriggerUnpacker::NNBitStream > m_bitsNN
Store Object with the trigger NN bits.
FilterCalculator()
Set the default names for the store object particle lists.
double m_cosmicMaxClusterEnergy
which LAB cluster energy vetoes a cosmic candidate
double m_goodMagneticRegionD0
minimum d0 for well understood magnetic field, if z0 is large (cm)
double m_looseTrkZ0
which Z0 defines a loose track
@ TTYP_DPHY
delayed physics events for background
@ TTYP_POIS
poisson random trigger
@ TTYP_RAND
random trigger events
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
ROOT::Math::PxPyPzEVector get4Momentum() const
Getter for the 4Momentum at the closest approach of the track in the r/phi projection.
double getTransverseMomentum() const
Getter for the absolute value of the transverse momentum at the perigee.
double getZ0() const
Getter for z0.
HitPatternCDC getHitPatternCDC() const
Getter for the hit pattern in the CDC;.
Class that bundles various TrackFitResults.
virtual int getNDF(void) const
Get an NDF of the fit.
enum KFitError::ECode addParticle(const Particle *particle)
Add a particle to the fitter.
VertexFitKFit is a derived class from KFitBase to perform vertex-constraint kinematical fit.
double getCHIsq(void) const override
Get a chi-square of the fit.
enum KFitError::ECode doFit(void)
Perform a vertex-constraint fit.
const HepPoint3D getVertex(const int flag=KFitConst::kAfterFit) const
Get a vertex position.
Abstract base class for different kinds of events.
Temporary data structure holding the track(s) with the maximum pT.
double pLab
the momentum magnitude in lab system
double pT
the pT of the track
ROOT::Math::PxPyPzEVector p4CMS
the 4 momentum in CMS system
double clusterEnergySumLab
the sum of related cluster energies in lab system
ROOT::Math::PxPyPzEVector p4Lab
the 4 momentum in lab system
double clusterEnergySumCMS
the sum of related cluster energies in CMS system
double pCMS
the momentum magnitude in CMS system
const Track * track
the track
Temporary data structure holding the ECL clusters used for this analysis.
double energyLab
the energy in Lab system
double clusterTime
the time of the cluster
ROOT::Math::PxPyPzEVector p4CMS
the 4 momentum in CMS system
ROOT::Math::PxPyPzEVector p4Lab
the 4 momentum in lab system
const ECLCluster * cluster
The ECL cluster.
bool isTrack
is this ECL cluster likely from a track (or a photon) = is it charged?
double energyCMS
the energy in CMS system