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>
28using namespace SoftwareTrigger;
45 ROOT::Math::PxPyPzEVector
p4CMS;
47 ROOT::Math::PxPyPzEVector
p4Lab;
59 ROOT::Math::PxPyPzEVector
p4CMS;
61 ROOT::Math::PxPyPzEVector
p4Lab;
69const double flatBoundaries[10] = {0., 19., 22., 25., 30., 35., 45., 60., 90., 180.};
87 calculationResult[
"nTrkLoose"] = 0;
88 calculationResult[
"nTrkTight"] = 0;
89 calculationResult[
"ee2leg"] = 0;
90 calculationResult[
"nEmedium"] = 0;
91 calculationResult[
"nElow"] = 0;
92 calculationResult[
"nEhigh"] = 0;
93 calculationResult[
"nE180Lab"] = 0;
94 calculationResult[
"nE300Lab"] = 0;
95 calculationResult[
"nE500Lab"] = 0;
96 calculationResult[
"nE2000CMS"] = 0;
97 calculationResult[
"nE4000CMS"] = 0;
98 calculationResult[
"nE250Lab"] = 0;
99 calculationResult[
"nMaxEPhotonAcc"] = 0;
100 calculationResult[
"dphiCmsClust"] = NAN;
102 calculationResult[
"netChargeLoose"] = 0;
103 calculationResult[
"maximumPCMS"] = NAN;
104 calculationResult[
"maximumPLab"] = NAN;
105 calculationResult[
"eexx"] = 0;
106 calculationResult[
"ee1leg1trk"] = 0;
107 calculationResult[
"nEhighLowAng"] = 0;
108 calculationResult[
"nEsingleClust"] = 0;
109 calculationResult[
"nEsinglePhotonBarrel"] = 0;
110 calculationResult[
"nEsinglePhotonExtendedBarrel"] = 0;
111 calculationResult[
"nEsinglePhotonEndcap"] = 0;
112 calculationResult[
"nEsingleElectronBarrel"] = 0;
113 calculationResult[
"nEsingleElectronExtendedBarrel"] = 0;
114 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] = 0;
115 calculationResult[
"nVetoClust"] = 0;
116 calculationResult[
"chrgClust2GeV"] = 0;
117 calculationResult[
"neutClust045GeVAcc"] = 0;
118 calculationResult[
"neutClust045GeVBarrel"] = 0;
119 calculationResult[
"singleTagLowMass"] = 0;
120 calculationResult[
"singleTagHighMass"] = 0;
121 calculationResult[
"n2GeVNeutBarrel"] = 0;
122 calculationResult[
"n2GeVNeutEndcap"] = 0;
123 calculationResult[
"n2GeVChrg"] = 0;
124 calculationResult[
"n2GeVPhotonBarrel"] = 0;
125 calculationResult[
"n2GeVPhotonEndcap"] = 0;
126 calculationResult[
"ee1leg"] = 0;
127 calculationResult[
"ee1leg1clst"] = 0;
128 calculationResult[
"ee1leg1e"] = 0;
129 calculationResult[
"ee2clst"] = 0;
130 calculationResult[
"gg2clst"] = 0;
131 calculationResult[
"eeee"] = 0;
132 calculationResult[
"eemm"] = 0;
133 calculationResult[
"eexxSelect"] = 0;
134 calculationResult[
"radBhabha"] = 0;
135 calculationResult[
"eeBrem"] = 0;
136 calculationResult[
"isrRadBhabha"] = 0;
137 calculationResult[
"muonPairECL"] = 0;
138 calculationResult[
"ggHighPt"] = 0;
139 calculationResult[
"selectee1leg1trk"] = 0;
140 calculationResult[
"selectee1leg1clst"] = 0;
141 calculationResult[
"selectee"] = 0;
142 calculationResult[
"ggBarrelVL"] = 0;
143 calculationResult[
"ggBarrelLoose"] = 0;
144 calculationResult[
"ggBarrelTight"] = 0;
145 calculationResult[
"ggEndcapVL"] = 0;
146 calculationResult[
"ggEndcapLoose"] = 0;
147 calculationResult[
"ggEndcapTight"] = 0;
148 calculationResult[
"muonPairV"] = 0;
149 calculationResult[
"selectmumu"] = 0;
150 calculationResult[
"singleMuon"] = 0;
151 calculationResult[
"cosmic"] = 0;
152 calculationResult[
"displacedVertex"] = 0;
153 calculationResult[
"eeFlat0"] = 0;
154 calculationResult[
"eeFlat1"] = 0;
155 calculationResult[
"eeFlat2"] = 0;
156 calculationResult[
"eeFlat3"] = 0;
157 calculationResult[
"eeFlat4"] = 0;
158 calculationResult[
"eeFlat5"] = 0;
159 calculationResult[
"eeFlat6"] = 0;
160 calculationResult[
"eeFlat7"] = 0;
161 calculationResult[
"eeFlat8"] = 0;
162 calculationResult[
"eeOneClust"] = 0;
165 calculationResult[
"nTrkLooseB"] = 0;
166 calculationResult[
"nTrkTightB"] = 0;
167 calculationResult[
"maximumPCMSB"] = NAN;
168 calculationResult[
"netChargeLooseB"] = 0;
169 calculationResult[
"muonPairVB"] = 0;
170 calculationResult[
"eeBremB"] = 0;
171 calculationResult[
"singleTagLowMassB"] = 0;
172 calculationResult[
"singleTagHighMassB"] = 0;
173 calculationResult[
"radBhabhaB"] = 0;
176 calculationResult[
"nTrackC"] = 0;
177 calculationResult[
"maximumPCMSC"] = NAN;
178 calculationResult[
"pCmsNegC"] = NAN;
179 calculationResult[
"clusterENegC"] = NAN;
180 calculationResult[
"pCmsPosC"] = NAN;
181 calculationResult[
"clusterEPosC"] = NAN;
182 calculationResult[
"dPhiCmsC"] = NAN;
185 calculationResult[
"Prefilter_InjectionStrip"] = 0;
186 calculationResult[
"Prefilter_CDCECLthreshold"] = 0;
196 }
catch (
const std::exception&) {
202 }
catch (
const std::exception&) {
208 }
catch (
const std::exception&) {
214 }
catch (
const std::exception&) {
220 }
catch (
const std::exception&) {
223 calculationResult[
"bha3d"] = bha3d;
224 calculationResult[
"bhapur"] = bhapurPsnm;
225 calculationResult[
"bhapur_lml1"] = lml1 and bhapurFtdl;
226 calculationResult[
"l1_bit_f"] = l1_bit_f;
228 calculationResult[
"l1_trigger_random"] = 1;
229 calculationResult[
"l1_trigger_delayed_bhabha"] = 0;
230 calculationResult[
"l1_trigger_poisson"] = 0;
231 calculationResult[
"bha3d"] = 0;
232 calculationResult[
"bhapur"] = 0;
233 calculationResult[
"bhapur_lml1"] = 0;
234 calculationResult[
"l1_bit_f"] = 0;
238 calculationResult[
"l1_trg_NN_info"] = 0;
239 if (
m_bitsNN.isValid() and
m_bitsNN.getEntries() > 0) {calculationResult[
"l1_trg_NN_info"] = 1;}
241 calculationResult[
"true"] = 1;
242 calculationResult[
"false"] = 0;
247 const ROOT::Math::XYZVector clustervertex = cUtil.
GetIPPosition();
249 ROOT::Math::PxPyPzEVector p4ofCOM;
250 p4ofCOM.SetPxPyPzE(0, 0, 0, boostrotate.
getCMSEnergy());
253 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracks = {
258 std::map<short, std::optional<MaximumPtTrack>> maximumPtTracksWithoutZCut = {
263 std::map<short, std::optional<MaximumPtTrack>> maximumPCmsTracksC = {
271 if (not trackFitResult) {
278 if (charge == 0) {
continue;}
279 const double z0 = trackFitResult->
getZ0();
280 const ROOT::Math::PxPyPzEVector& momentumLab = trackFitResult->
get4Momentum();
281 const ROOT::Math::PxPyPzEVector momentumCMS = boostrotate.
rotateLabToCms() * momentumLab;
282 const double pCMS = momentumCMS.P();
283 const double pLab = momentumLab.P();
284 const double trackTime = track.getTrackTime();
287 double clusterELab = 0.;
288 for (
auto& cluster : track.getRelationsTo<
ECLCluster>()) {
293 const double clusterECMS = clusterELab * pCMS / pLab;
298 bool goodTrackCTime =
true;
299 if (std::abs(trackTime) > 15.) {goodTrackCTime =
false;}
300 if (std::abs(z0) < 1. and goodTrackCTime and pCMS > 0.2) {
301 calculationResult[
"nTrackC"] += 1;
302 if (std::isnan(calculationResult[
"maximumPCMSC"]) or pCMS > calculationResult[
"maximumPCMSC"]) {
303 calculationResult[
"maximumPCMSC"] = pCMS;
308 const auto& currentMaximumC = maximumPCmsTracksC.at(charge);
309 if (not currentMaximumC or pCMS > currentMaximumC->pCMS) {
312 newMaximum.
track = &track;
313 newMaximum.
pCMS = pCMS;
314 newMaximum.
pLab = pLab;
315 newMaximum.
p4CMS = momentumCMS;
316 newMaximum.
p4Lab = momentumLab;
319 maximumPCmsTracksC[charge] = newMaximum;
331 calculationResult[
"nTrkTight"] += 1;
337 const auto& currentMaximum = maximumPtTracksWithoutZCut.at(charge);
338 if (not currentMaximum or pT > currentMaximum->pT) {
341 newMaximum.
track = &track;
342 newMaximum.
pCMS = pCMS;
343 newMaximum.
pLab = pLab;
344 newMaximum.
p4CMS = momentumCMS;
345 newMaximum.
p4Lab = momentumLab;
348 maximumPtTracksWithoutZCut[charge] = newMaximum;
355 calculationResult[
"nTrkLoose"] += 1;
356 calculationResult[
"netChargeLoose"] += charge;
358 if (std::isnan(calculationResult[
"maximumPCMS"]) or pCMS > calculationResult[
"maximumPCMS"]) {
359 calculationResult[
"maximumPCMS"] = pCMS;
362 if (std::isnan(calculationResult[
"maximumPLab"]) or pLab > calculationResult[
"maximumPLab"]) {
363 calculationResult[
"maximumPLab"] = pLab;
368 const auto& currentMaximumLoose = maximumPtTracks.at(charge);
369 if (not currentMaximumLoose or pTLoose > currentMaximumLoose->pT) {
371 newMaximum.
pT = pTLoose;
372 newMaximum.
track = &track;
373 newMaximum.
pCMS = pCMS;
374 newMaximum.
pLab = momentumLab.P();
375 newMaximum.
p4CMS = momentumCMS;
376 newMaximum.
p4Lab = momentumLab;
379 maximumPtTracks[charge] = newMaximum;
386 if (std::abs(z0) < 1.) {calculationResult[
"nTrkTightB"] += 1;}
387 if (std::abs(z0) < 5.) {
388 calculationResult[
"nTrkLooseB"] += 1;
389 calculationResult[
"netChargeLooseB"] += charge;
390 if (std::isnan(calculationResult[
"maximumPCMSB"]) or pCMS > calculationResult[
"maximumPCMSB"]) {
391 calculationResult[
"maximumPCMSB"] = pCMS;
402 for (
short charge : { -1, 1}) {
403 auto& maximumPcmsTrackC = maximumPCmsTracksC.at(charge);
404 if (not maximumPcmsTrackC) {
410 calculationResult[
"pCmsNegC"] = maximumPcmsTrackC->pCMS;
411 calculationResult[
"clusterENegC"] = maximumPcmsTrackC->clusterEnergySumLab;
413 calculationResult[
"pCmsPosC"] = maximumPcmsTrackC->pCMS;
414 calculationResult[
"clusterEPosC"] = maximumPcmsTrackC->clusterEnergySumLab;
419 if (maximumPCmsTracksC.at(-1) and maximumPCmsTracksC.at(1)) {
423 calculationResult[
"dPhiCmsC"] = std::abs(ROOT::Math::VectorUtil::DeltaPhi(negativeTrack.
p4CMS,
424 positiveTrack.
p4CMS)) * TMath::RadToDeg();
430 std::vector<SelectedECLCluster> selectedClusters;
433 const double time = cluster.getTime();
435 std::abs(time) > 200 or
440 const double dt99 = cluster.getDeltaTime99();
447 selectedCluster.
cluster = &cluster;
451 selectedCluster.
isTrack = cluster.isTrack();
453 selectedClusters.push_back(selectedCluster);
456 calculationResult[
"nElow"] += 1;
459 calculationResult[
"nEmedium"] += 1;
462 calculationResult[
"nEhigh"] += 1;
466 calculationResult[
"nVetoClust"] += 1;
471 const double thetaLab = selectedCluster.
p4Lab.Theta() * TMath::RadToDeg();
472 const double zmva = cluster.getZernikeMVA();
473 const bool photon = zmva > 0.5 and not selectedCluster.
isTrack;
474 const bool electron = zmva > 0.5 and selectedCluster.
isTrack;
478 calculationResult[
"chrgClust2GeV"] += 1;
481 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
482 if (isInAcceptance) {calculationResult[
"neutClust045GeVAcc"] += 1;}
483 const bool isInBarrel = 30. < thetaLab and thetaLab < 130.;
484 if (isInBarrel) {calculationResult[
"neutClust045GeVBarrel"] += 1;}
489 const bool notInHighBackgroundEndcapRegion = 18.5 < thetaLab and thetaLab < 139.3;
491 calculationResult[
"nE180Lab"] += 1;
495 calculationResult[
"nE300Lab"] += 1;
499 calculationResult[
"nE500Lab"] += 1;
502 if (selectedCluster.
energyCMS >
m_Ehigh and notInHighBackgroundEndcapRegion) {
503 calculationResult[
"nE2000CMS"] += 1;
508 calculationResult[
"nE250Lab"] += 1;
511 calculationResult[
"nE4000CMS"] += 1;
516 calculationResult[
"nEsingleClust"] += 1;
518 const bool barrelRegion = thetaLab > 45 and thetaLab < 115;
519 const bool extendedBarrelRegion = thetaLab > 30 and thetaLab < 130;
520 const bool endcapRegion = (thetaLab > 22 and thetaLab < 45) or (thetaLab > 115 and thetaLab < 145);
522 if (photon and barrelRegion) {
523 calculationResult[
"nEsinglePhotonBarrel"] += 1;
526 if (photon and extendedBarrelRegion) {
527 calculationResult[
"nEsinglePhotonExtendedBarrel"] += 1;
530 if (electron and barrelRegion) {
531 calculationResult[
"nEsingleElectronBarrel"] += 1;
534 if (electron and extendedBarrelRegion) {
535 calculationResult[
"nEsingleElectronExtendedBarrel"] += 1;
538 if (photon and endcapRegion) {
539 calculationResult[
"nEsinglePhotonEndcap"] += 1;
544 const bool reducedBarrelRegion = thetaLab > 44 and thetaLab < 98;
546 if (photon and reducedBarrelRegion) {
547 calculationResult[
"nReducedEsinglePhotonReducedBarrel"] += 1;
553 const bool barrelRegion = thetaLab > 32 and thetaLab < 130;
554 const bool endcapRegion = (thetaLab > 22 and thetaLab < 32) or (thetaLab > 130 and thetaLab < 145);
555 const bool lowAngleRegion = thetaLab < 22 or thetaLab > 145;
557 if (not selectedCluster.
isTrack and barrelRegion) {
558 calculationResult[
"n2GeVNeutBarrel"] += 1;
560 if (not selectedCluster.
isTrack and endcapRegion) {
561 calculationResult[
"n2GeVNeutEndcap"] += 1;
563 if (selectedCluster.
isTrack and not lowAngleRegion) {
564 calculationResult[
"n2GeVChrg"] += 1;
566 if (lowAngleRegion) {
567 calculationResult[
"nEhighLowAng"] += 1;
569 if (photon and barrelRegion) {
570 calculationResult[
"n2GeVPhotonBarrel"] += 1;
572 if (photon and endcapRegion) {
573 calculationResult[
"n2GeVPhotonEndcap"] += 1;
579 std::sort(selectedClusters.begin(), selectedClusters.end(), [](
const auto & lhs,
const auto & rhs) {
580 return lhs.energyCMS > rhs.energyCMS;
584 for (
short charge : { -1, 1}) {
585 auto& maximumPtTrack = maximumPtTracks.at(charge);
586 if (not maximumPtTrack) {
591 if (maximumPtTrack->clusterEnergySumCMS > 4.5) {
592 calculationResult[
"ee1leg"] = 1;
596 if (maximumPtTrack->pCMS > 3 and maximumPtTrack->clusterEnergySumLab > 0. and maximumPtTrack->clusterEnergySumLab < 1.) {
597 calculationResult[
"singleMuon"] = 1;
602 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
606 double dphi = std::abs(negativeTrack.
p4CMS.Phi() - positiveTrack.
p4CMS.Phi()) * TMath::RadToDeg();
613 const double negativeP = negativeTrack.
pCMS;
616 const double positiveP = positiveTrack.
pCMS;
619 const double thetaSum = (negativeTrack.
p4CMS.Theta() + positiveTrack.
p4CMS.Theta()) * TMath::RadToDeg();
620 const double dthetaSum = std::abs(thetaSum - 180);
621 const auto back2back = dphi > 175 and dthetaSum < 15;
622 if (back2back and negativeClusterSum > 3 and positiveClusterSum > 3 and
623 (negativeClusterSum > 4.5 or positiveClusterSum > 4.5)) {
624 calculationResult[
"ee2leg"] = 1;
628 if (back2back and ((negativeClusterSum > 4.5 and positiveP > 3) or (positiveClusterSum > 4.5 and negativeP > 3))) {
629 calculationResult[
"ee1leg1trk"] = 1;
634 if ((negativeClusterSum > 4.5 and positiveClusterSum > 0.8 * positiveP) or
635 (positiveClusterSum > 4.5 and negativeClusterSum > 0.8 * negativeP)) {
636 calculationResult[
"ee1leg1e"] = 1;
640 const ROOT::Math::PxPyPzEVector p4Miss = p4ofCOM - negativeTrack.
p4CMS - positiveTrack.
p4CMS;
641 const double pmissTheta = p4Miss.Theta() * TMath::RadToDeg();
642 const double pmissp = p4Miss.P();
646 const bool electronEP = positiveClusterSum > 0.8 * positiveP or negativeClusterSum > 0.8 * negativeP;
647 const bool notMuonPair = negativeClusterSumLab > 1 or positiveClusterSumLab > 1;
648 const double highp = std::max(negativeP, positiveP);
649 const double lowp = std::min(negativeP, positiveP);
650 const bool lowEdep = negativeClusterSumLab < 0.5 and positiveClusterSumLab < 0.5;
653 if (calculationResult[
"maximumPCMS"] < 2 and dphi > 160 and (pmissTheta < 25. or pmissTheta > 155.)) {
654 calculationResult[
"eexxSelect"] = 1;
656 calculationResult[
"eeee"] = 1;
658 calculationResult[
"eemm"] = 1;
663 if ((pmissTheta < 20. or pmissTheta > 160.) and
664 ((calculationResult[
"maximumPCMS"] < 1.2 and dphi > 150.) or
665 (calculationResult[
"maximumPCMS"] < 2. and 175. < dphi))) {
666 calculationResult[
"eexx"] = 1;
670 if (negativeP > 1. and pmissTheta > 10. and pmissTheta < 170. and positiveP > 1. and dphi < 170. and pmissp > 1. and electronEP) {
671 if (calculationResult[
"nTrkLoose"] == 2 and calculationResult[
"nTrkTight"] >= 1) {
672 calculationResult[
"radBhabha"] = 1;
674 if (calculationResult[
"nTrkLooseB"] == 2 and calculationResult[
"nTrkTightB"] >= 1) {
675 calculationResult[
"radBhabhaB"] = 1;
680 if (negativeP > 2. and positiveP > 2. and 2 == calculationResult[
"nTrkLoose"] and
681 calculationResult[
"nTrkTight"] >= 1 and dphi > 175. and
682 (pmissTheta < 5. or pmissTheta > 175.) and electronEP) {
683 calculationResult[
"isrRadBhabha"] = 1;
687 if (highp > 4.5 and notMuonPair and pmissp > 1. and (relMissAngle0 < 5. or relMissAngle1 < 5.)) {
688 if (calculationResult[
"nTrkLoose"] == 2) { calculationResult[
"eeBrem"] = 1;}
689 if (calculationResult[
"nTrkLooseB"] >= 1) { calculationResult[
"eeBremB"] = 1;}
693 if (highp > 4.5 and lowEdep and thetaSum > 175. and thetaSum < 185. and dphi > 175.) {
694 if (calculationResult[
"nTrkLoose"] == 2) {calculationResult[
"muonPairV"] = 1;}
695 if (calculationResult[
"nTrkLooseB"] == 2) {calculationResult[
"muonPairVB"] = 1;}
699 if (highp > 3. and lowp > 2.5 and dphi > 165. and
700 ((negativeClusterSumLab > 0. and negativeClusterSumLab < 1.) or
701 (positiveClusterSumLab > 0. and positiveClusterSumLab < 1.))) {
702 calculationResult[
"selectmumu"] = 1;
707 if (selectedClusters.size() >= 2) {
711 double dphi = std::abs(firstCluster.
p4CMS.Phi() - secondCluster.
p4CMS.Phi()) * TMath::RadToDeg();
715 double thetaSum = (firstCluster.
p4CMS.Theta() + secondCluster.
p4CMS.Theta()) * TMath::RadToDeg();
716 double dthetaSum = std::abs(thetaSum - 180);
719 calculationResult[
"dphiCmsClust"] = dphi;
720 for (
int ic = 0; ic < 2; ic++) {
721 const double thetaLab = selectedClusters[ic].p4Lab.Theta() * TMath::RadToDeg();
722 const bool isInAcceptance = 17. < thetaLab and thetaLab < 150.;
723 const ECLCluster* cluster = selectedClusters[ic].cluster;
724 const double zmva = cluster->getZernikeMVA();
725 const bool photon = zmva > 0.5 and not selectedClusters[ic].isTrack;
726 if (isInAcceptance and photon) {calculationResult[
"nMaxEPhotonAcc"] += 1;}
729 const double firstEnergy = firstCluster.
p4CMS.E();
730 const double secondEnergy = secondCluster.
p4CMS.E();
732 const bool highEnergetic = firstEnergy > 3 and secondEnergy > 3 and (firstEnergy > 4.5 or secondEnergy > 4.5);
734 if (dphi > 160 and dphi < 178 and dthetaSum < 15 and highEnergetic) {
735 calculationResult[
"ee2clst"] = 1;
738 if (dphi > 178 and dthetaSum < 15 and highEnergetic) {
739 calculationResult[
"gg2clst"] = 1;
742 if ((calculationResult[
"ee2clst"] == 1 or calculationResult[
"gg2clst"] == 1) and
743 calculationResult[
"ee1leg"] == 1) {
744 calculationResult[
"ee1leg1clst"] = 1;
747 const double Elab0 = firstCluster.
p4Lab.E();
748 const double Elab1 = secondCluster.
p4Lab.E();
751 if (firstEnergy > 2 and secondEnergy > 2) {
752 const double thetaLab0 = firstCluster.
p4Lab.Theta() * TMath::RadToDeg();
753 const double thetaLab1 = secondCluster.
p4Lab.Theta() * TMath::RadToDeg();
755 const bool barrel0 = 32. < thetaLab0 and thetaLab0 < 130.;
756 const bool barrel1 = 32. < thetaLab1 and thetaLab1 < 130.;
757 const bool oneClustersAbove4 = firstEnergy > 4 or secondEnergy > 4;
758 const bool oneIsNeutral = not firstCluster.
isTrack or not secondCluster.
isTrack;
759 const bool bothAreNeutral = not firstCluster.
isTrack and not secondCluster.
isTrack;
760 const bool oneIsBarrel = barrel0 or barrel1;
761 const bool dphiCutExtraLoose = dphi > 175;
762 const bool dphiCutLoose = dphi > 177;
763 const bool dphiCutTight = dphi > 177.5;
765 if (dphiCutExtraLoose and oneIsNeutral and oneIsBarrel) {
766 calculationResult[
"ggBarrelVL"] = 1;
768 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and oneIsBarrel) {
769 calculationResult[
"ggBarrelLoose"] = 1;
771 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and oneIsBarrel) {
772 calculationResult[
"ggBarrelTight"] = 1;
774 if (dphiCutExtraLoose and oneIsNeutral and not oneIsBarrel) {
775 calculationResult[
"ggEndcapVL"] = 1;
777 if (oneClustersAbove4 and dphiCutLoose and oneIsNeutral and not oneIsBarrel) {
778 calculationResult[
"ggEndcapLoose"] = 1;
780 if (oneClustersAbove4 and dphiCutTight and bothAreNeutral and not oneIsBarrel) {
781 calculationResult[
"ggEndcapTight"] = 1;
785 const double minEnergy = std::min(Elab0, Elab1);
786 const double maxEnergy = std::max(Elab0, Elab1);
787 if (dphi > 155 and thetaSum > 165 and thetaSum < 195 and minEnergy > 0.15 and minEnergy < 0.5 and
788 maxEnergy > 0.15 and maxEnergy < 0.5) {
789 calculationResult[
"muonPairECL"] = 1;
793 const double thetaLab0 = firstCluster.
p4Lab.Theta() * TMath::RadToDeg();
794 const double thetaLab1 = secondCluster.
p4Lab.Theta() * TMath::RadToDeg();
795 const bool inHieRegion0 = thetaLab0 > 26. and thetaLab0 < 130.;
796 const bool inHieRegion1 = thetaLab1 > 26. and thetaLab1 < 130.;
797 const bool firstIsNeutral = not firstCluster.
isTrack;
798 const bool secondIsNeutral = not secondCluster.
isTrack;
800 if (secondEnergy > 0.3 and inHieRegion0 and inHieRegion1 and firstIsNeutral and secondIsNeutral) {
801 const ROOT::Math::PxPyPzEVector ggP4CMS = firstCluster.
p4CMS + secondCluster.
p4CMS;
802 if (ggP4CMS.pt() > 1.) {calculationResult[
"ggHighPt"] = 1;}
809 double thetaFlatten = 0;
812 for (
short charge : { -1, 1}) {
813 const auto& maximumPtTrack = maximumPtTracks.at(charge);
814 if (not maximumPtTrack) {
818 if (maximumPtTrack->clusterEnergySumCMS > 1.5) {
820 double tempFlatten = 0.;
822 double tempInvMass = (maximumPtTrack->p4Lab + cluster.p4Lab).M();
823 if (tempInvMass > invMass) {
824 invMass = tempInvMass;
826 tempFlatten = cluster.p4Lab.Theta() * TMath::RadToDeg();
831 tempFlatten = maximumPtTrack->p4Lab.Theta() * TMath::RadToDeg();
833 if (invMass > 5.29) {
834 calculationResult[
"selectee1leg1clst"] = 1;
835 thetaFlatten = tempFlatten;
841 if (maximumPtTracks.at(-1) and maximumPtTracks.at(1)) {
844 const double invMass = (negativeTrack.
p4Lab + positiveTrack.
p4Lab).M();
846 calculationResult[
"selectee1leg1trk"] = 1;
849 thetaFlatten = negativeTrack.
p4Lab.Theta() * TMath::RadToDeg();
854 if ((invMass > 9.) and (missNegClust or missPosClust)) {
855 calculationResult[
"eeOneClust"] = 1;
859 if (calculationResult[
"selectee1leg1trk"] == 1 or calculationResult[
"selectee1leg1clst"] == 1) {
860 for (
int iflat = 0; iflat < 9; iflat++) {
861 const std::string& eeFlatName =
"eeFlat" + std::to_string(iflat);
862 calculationResult[eeFlatName] =
863 thetaFlatten >= flatBoundaries[iflat] and thetaFlatten < flatBoundaries[iflat + 1];
864 if (calculationResult[eeFlatName]) {
865 calculationResult[
"selectee"] = 1;
871 if (calculationResult[
"nTrkLoose"] == 1 and calculationResult[
"maximumPCMS"] > 0.8 and selectedClusters.size() >= 2) {
873 decltype(selectedClusters) selectedSingleTagClusters(selectedClusters.size());
874 auto lastItem = std::copy_if(selectedClusters.begin(), selectedClusters.end(), selectedSingleTagClusters.begin(),
876 const bool isNeutralCluster = not cluster.isTrack;
877 const bool hasEnoughEnergy = cluster.energyLab > 0.1;
878 const double clusterThetaLab = cluster.p4Lab.Theta() * TMath::RadToDeg();
879 const bool isInAcceptance = 17 < clusterThetaLab and clusterThetaLab < 150.;
880 return isNeutralCluster and hasEnoughEnergy and isInAcceptance;
882 selectedSingleTagClusters.resize(std::distance(selectedSingleTagClusters.begin(), lastItem));
884 if (selectedSingleTagClusters.size() >= 2) {
886 const auto& track = maximumPtTracks.at(-1) ? *maximumPtTracks.at(-1) : *maximumPtTracks.at(1);
888 const auto& firstCluster = selectedSingleTagClusters[0];
889 const auto& secondCluster = selectedSingleTagClusters[1];
891 const ROOT::Math::PxPyPzEVector trackP4CMS = track.p4CMS;
892 const ROOT::Math::PxPyPzEVector pi0P4CMS = firstCluster.p4CMS + secondCluster.p4CMS;
894 const bool passPi0ECMS = pi0P4CMS.E() > 1. and pi0P4CMS.E() < 0.525 * p4ofCOM.M();
895 const double thetaSumCMS = (pi0P4CMS.Theta() + trackP4CMS.Theta()) * TMath::RadToDeg();
896 const bool passThetaSum = thetaSumCMS < 170. or thetaSumCMS > 190.;
898 double dphiCMS = std::abs(trackP4CMS.Phi() - pi0P4CMS.Phi()) * TMath::RadToDeg();
900 dphiCMS = 360 - dphiCMS;
902 const bool passdPhi = dphiCMS > 160.;
904 if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() < 0.7) {
905 calculationResult[
"singleTagLowMass"] = 1;
906 }
else if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() > 0.7) {
907 calculationResult[
"singleTagHighMass"] = 1;
913 if (calculationResult[
"nTrkLooseB"] == 1 and calculationResult[
"maximumPCMSB"] > 0.8 and selectedClusters.size() >= 2) {
915 decltype(selectedClusters) selectedSingleTagClusters(selectedClusters.size());
916 auto lastItem = std::copy_if(selectedClusters.begin(), selectedClusters.end(), selectedSingleTagClusters.begin(),
918 const bool isNeutralCluster = not cluster.isTrack;
919 const bool hasEnoughEnergy = cluster.energyLab > 0.1;
920 const double clusterThetaLab = cluster.p4Lab.Theta() * TMath::RadToDeg();
921 const bool isInAcceptance = 17 < clusterThetaLab and clusterThetaLab < 150.;
922 return isNeutralCluster and hasEnoughEnergy and isInAcceptance;
924 selectedSingleTagClusters.resize(std::distance(selectedSingleTagClusters.begin(), lastItem));
926 if (selectedSingleTagClusters.size() >= 2) {
928 const auto& track = maximumPtTracks.at(-1) ? *maximumPtTracks.at(-1) : *maximumPtTracks.at(1);
930 const auto& firstCluster = selectedSingleTagClusters[0];
931 const auto& secondCluster = selectedSingleTagClusters[1];
933 const ROOT::Math::PxPyPzEVector trackP4CMS = track.p4CMS;
934 const ROOT::Math::PxPyPzEVector pi0P4CMS = firstCluster.p4CMS + secondCluster.p4CMS;
936 const bool passPi0ECMS = pi0P4CMS.E() > 1. and pi0P4CMS.E() < 0.525 * p4ofCOM.M();
937 const double thetaSumCMS = (pi0P4CMS.Theta() + trackP4CMS.Theta()) * TMath::RadToDeg();
938 const bool passThetaSum = thetaSumCMS < 170. or thetaSumCMS > 190.;
940 double dphiCMS = std::abs(trackP4CMS.Phi() - pi0P4CMS.Phi()) * TMath::RadToDeg();
942 dphiCMS = 360 - dphiCMS;
944 const bool passdPhi = dphiCMS > 160.;
946 if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() < 0.7) {
947 calculationResult[
"singleTagLowMassB"] = 1;
948 }
else if (passPi0ECMS and passThetaSum and passdPhi and pi0P4CMS.M() > 0.7) {
949 calculationResult[
"singleTagHighMassB"] = 1;
957 const auto negTrack = maximumPtTracksWithoutZCut.at(-1);
958 const auto posTrack = maximumPtTracksWithoutZCut.at(1);
960 if (negTrack and posTrack) {
962 const double maxNegpT = negTrack->pT;
963 const double maxPospT = posTrack->pT;
964 const double maxClusterENeg = negTrack->clusterEnergySumLab;
965 const double maxClusterEPos = posTrack->clusterEnergySumLab;
967 const ROOT::Math::PxPyPzEVector& momentumLabNeg(negTrack->p4Lab);
968 const ROOT::Math::PxPyPzEVector& momentumLabPos(posTrack->p4Lab);
970 const double& z0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
971 const double& d0Neg = negTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
972 const double& z0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getZ0();
973 const double& d0Pos = posTrack->track->getTrackFitResultWithClosestMass(
Const::pion)->getD0();
980 double dphiLab = std::abs(momentumLabNeg.Phi() - momentumLabPos.Phi()) * TMath::RadToDeg();
982 dphiLab = 360 - dphiLab;
985 const double thetaSumLab = (momentumLabNeg.Theta() + momentumLabPos.Theta()) * TMath::RadToDeg();
987 constexpr double phiBackToBackTolerance = 2.;
988 constexpr double thetaBackToBackTolerance = 2.;
989 if ((180 - dphiLab) < phiBackToBackTolerance and std::abs(180 - thetaSumLab) < thetaBackToBackTolerance) {
990 calculationResult[
"cosmic"] = 1;
998 if (maximumPtTracksWithoutZCut.at(-1) and maximumPtTracksWithoutZCut.at(1)) {
1001 const auto nTrack = maximumPtTracksWithoutZCut.at(-1)->track;
1004 const auto pTrack = maximumPtTracksWithoutZCut.at(1)->track;
1014 const double chisq = vertexFit->
getCHIsq();
1015 const int ndf = vertexFit->
getNDF();
1016 const double vertexProb = TMath::Prob(chisq, ndf);
1017 const auto vertexLocation = vertexFit->
getVertex();
1018 const double vertexXY = vertexLocation.perp();
1019 const double vertexTheta = vertexLocation.theta() * TMath::RadToDeg();
1025 const ROOT::Math::PxPyPzEVector& momentumLabNeg(maximumPtTracksWithoutZCut.at(-1)->p4Lab);
1026 const ROOT::Math::PxPyPzEVector& momentumLabPos(maximumPtTracksWithoutZCut.at(1)->p4Lab);
1027 const double thetaSumLab = (momentumLabNeg.Theta() + momentumLabPos.Theta()) * TMath::RadToDeg();
1028 double dPhiLab = std::abs(momentumLabNeg.Phi() - momentumLabPos.Phi()) * TMath::RadToDeg();
1029 if (dPhiLab > 180) {
1030 dPhiLab = 360 - dPhiLab;
1032 const double backToBackTolerance = 10.;
1033 const bool backToBackLab = std::abs(thetaSumLab - 180.) < backToBackTolerance and std::abs(dPhiLab - 180.) < backToBackTolerance;
1036 const double minProbChiVertex = 0.005;
1037 const double minXYVertex = 3.;
1038 const double maxXYVertex = 60.;
1039 const double minThetaVertex = 30.;
1040 const double maxThetaVertex = 120.;
1041 if (vertexProb > minProbChiVertex and vertexXY > minXYVertex and vertexXY < maxXYVertex and vertexTheta > minThetaVertex
1042 and vertexTheta < maxThetaVertex
1043 and not backToBackLab) {calculationResult[
"displacedVertex"] = 1;}
1055 B2FATAL(
"HLTprefilter parameters are not available.");
1076 if (
m_l1Trigger->testInput(
"passive_veto") == 1 &&
m_l1Trigger->testInput(
"cdcecl_veto") == 0) index = 1;
1077 }
catch (
const std::exception&) {
1084 calculationResult[
"Prefilter_InjectionStrip"] = 1;
1088 calculationResult[
"Prefilter_CDCECLthreshold"] = 1;
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
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)
uint32_t nECLDigitsMax
Maximum threshold for ECL Digits.
uint32_t nCDCHitsMax
Define thresholds for variables.
unsigned int prescale
Prescale for accepting HLTPrefilter lines, by default we randomly accept 1 out of every 1000 events.
double LERtimeSinceLastInjectionMin
Define thresholds for variables.
double HERtimeInBeamCycleMax
Maximum threshold of timeInBeamCycle for LER injection.
double HERtimeSinceLastInjectionMin
Minimum threshold of timeSinceLastInjection for HER injection.
double HERtimeSinceLastInjectionMax
Maximum threshold of timeSinceLastInjection for HER injection.
double LERtimeSinceLastInjectionMax
Maximum threshold of timeSinceLastInjection for LER injection.
double HERtimeInBeamCycleMin
Minimum threshold of timeInBeamCycle for HER injection.
double LERtimeInBeamCycleMax
Maximum threshold of timeInBeamCycle for LER injection.
unsigned int prescale
Prescale for accepting HLTPrefilter lines, by default we randomly accept 1 out of every 1000 events.
double LERtimeInBeamCycleMin
Minimum threshold of timeInBeamCycle for LER injection.
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
Class to store reconstructed particles.
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
DBObjPtr< HLTPrefilterParameters > m_hltPrefilterParameters
Objects relevant to HLTPrefilter monitoring HLTprefilterParameters Database OjbPtr.
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.
HLTPrefilter::TimingCutState m_timingPrefilter
Helper instance for timing based prefilter.
double m_cosmicMaxClusterEnergy
which LAB cluster energy vetoes a cosmic candidate
HLTPrefilter::CDCECLCutState m_cdceclPrefilter
Helper instance for CDC-ECL occupancy based prefilter.
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.
B2Vector3< double > B2Vector3D
typedef for common usage with double
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