Belle II Software  release-06-00-14
SkimSampleCalculator.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <hlt/softwaretrigger/calculations/SkimSampleCalculator.h>
9 #include <hlt/softwaretrigger/calculations/utilities.h>
10 #include <analysis/utility/PCmsLabTransform.h>
11 #include <analysis/ClusterUtility/ClusterUtils.h>
12 #include <analysis/dataobjects/Particle.h>
13 #include <mdst/dataobjects/KLMCluster.h>
14 #include <mdst/dataobjects/Track.h>
15 #include <analysis/utility/ReferenceFrame.h>
16 #include <mdst/dataobjects/TrackFitResult.h>
17 #include <mdst/dataobjects/HitPatternCDC.h>
18 #include <reconstruction/dataobjects/CDCDedxTrack.h>
19 #include <analysis/ContinuumSuppression/FoxWolfram.h>
20 #include <numeric>
21 #include <TDatabasePDG.h>
22 #include <analysis/variables/BelleVariables.h>
23 #include <analysis/variables/ECLVariables.h>
24 #include <mdst/dataobjects/PIDLikelihood.h>
25 #include <analysis/variables/AcceptanceVariables.h>
26 #include <analysis/variables/FlightInfoVariables.h>
27 #include <mdst/dataobjects/SoftwareTriggerResult.h>
28 
29 using namespace Belle2;
30 using namespace SoftwareTrigger;
31 
33  m_pionParticles("pi+:skim"), m_gammaParticles("gamma:skim"), m_pionHadParticles("pi+:hadb"), m_pionTauParticles("pi+:tau"),
34  m_KsParticles("K_S0:merged"), m_LambdaParticles("Lambda0:merged"), m_DstParticles("D*+:d0pi"), m_offIpParticles("pi+:offip"),
35  m_filterL1TrgNN("software_trigger_cut&filter&L1_trigger_nn_info")
36 {
37 
38 }
39 
41 {
42  m_pionParticles.isRequired();
43  m_gammaParticles.isRequired();
44  m_pionHadParticles.isRequired();
45  m_pionTauParticles.isRequired();
46  m_KsParticles.isOptional();
47  m_LambdaParticles.isOptional();
48  m_DstParticles.isOptional();
49  m_offIpParticles.isRequired();
50 
51 };
52 
53 void SkimSampleCalculator::doCalculation(SoftwareTriggerObject& calculationResult)
54 {
55  // Prefetch some later needed objects/values
56  const Particle* gammaWithMaximumRho = getElementWithMaximumRho<Particle>(m_gammaParticles);
57  const Particle* gammaWithSecondMaximumRho = getElementWithMaximumRhoBelow<Particle>(m_gammaParticles,
58  getRho(gammaWithMaximumRho));
59  const Particle* trackWithMaximumRho = getElementWithMaximumRho<Particle>(m_pionParticles);
60  const Particle* trackWithSecondMaximumRho = getElementWithMaximumRhoBelow<Particle>(m_pionParticles,
61  getRho(trackWithMaximumRho));
62 
63  const double& rhoOfECLClusterWithMaximumRho = getRhoOfECLClusterWithMaximumRho(m_pionParticles, m_gammaParticles);
64  const double& rhoOfECLClusterWithSecondMaximumRho = getRhoOfECLClusterWithMaximumRhoBelow(m_pionParticles,
66  rhoOfECLClusterWithMaximumRho);
67 
68  const double& rhoOfTrackWithMaximumRho = getRho(trackWithMaximumRho);
69  const double& rhoOfTrackWithSecondMaximumRho = getRho(trackWithSecondMaximumRho);
70  const double& rhoOfGammaWithMaximumRho = getRho(gammaWithMaximumRho);
71  const double& rhoOfGammaWithSecondMaximumRho = getRho(gammaWithSecondMaximumRho);
72 
73  // Simple to calculate variables
74  // EC1CMSLE
75  calculationResult["EC1CMSLE"] = rhoOfECLClusterWithMaximumRho;
76 
77  // EC2CMSLE
78  calculationResult["EC2CMSLE"] = rhoOfECLClusterWithSecondMaximumRho;
79 
80  // EC12CMSLE
81  calculationResult["EC12CMSLE"] = rhoOfECLClusterWithMaximumRho + rhoOfECLClusterWithSecondMaximumRho;
82 
83  // nTracksLE
84  calculationResult["nTracksLE"] = m_pionParticles->getListSize();
85 
86  // nTracksTAU
87  calculationResult["nTracksTAU"] = m_pionTauParticles->getListSize();
88 
89  // nGammasLE
90  calculationResult["nGammasLE"] = m_gammaParticles->getListSize();
91 
92  // P1CMSBhabhaLE
93  calculationResult["P1CMSBhabhaLE"] = rhoOfTrackWithMaximumRho;
94 
95  // P1CMSBhabhaLE/E_beam
96  calculationResult["P1OEbeamCMSBhabhaLE"] = rhoOfTrackWithMaximumRho / BeamEnergyCMS();
97 
98  // P2CMSBhabhaLE
99  calculationResult["P2CMSBhabhaLE"] = rhoOfTrackWithSecondMaximumRho;
100 
101  // P2CMSBhabhaLE/E_beam
102  calculationResult["P2OEbeamCMSBhabhaLE"] = rhoOfTrackWithSecondMaximumRho / BeamEnergyCMS();
103 
104  // P12CMSBhabhaLE
105  calculationResult["P12CMSBhabhaLE"] = rhoOfTrackWithMaximumRho + rhoOfTrackWithSecondMaximumRho;
106 
107  //G1CMSLE, the largest energy of gamma in CMS
108  calculationResult["G1CMSBhabhaLE"] = rhoOfGammaWithMaximumRho;
109  //G1OEbeamCMSLE, the largest energy of gamma in CMS over beam energy
110  calculationResult["G1OEbeamCMSBhabhaLE"] = rhoOfGammaWithMaximumRho / BeamEnergyCMS();
111 
112  //G2CMSLE, the secondary largest energy of gamma in CMS
113  calculationResult["G2CMSBhabhaLE"] = rhoOfGammaWithSecondMaximumRho;
114  //G2OEbeamCMSLE, the largest energy of gamma in CMS over beam energy
115  calculationResult["G2OEbeamCMSBhabhaLE"] = rhoOfGammaWithSecondMaximumRho / BeamEnergyCMS();
116 
117  //G12CMSLE, the secondary largest energy of gamma in CMS
118  calculationResult["G12CMSBhabhaLE"] = rhoOfGammaWithMaximumRho + rhoOfGammaWithSecondMaximumRho;
119  //G12CMSLE, the secondary largest energy of gamma in CMS over beam energy
120  calculationResult["G12OEbeamCMSBhabhaLE"] =
121  (rhoOfGammaWithMaximumRho + rhoOfGammaWithSecondMaximumRho) / BeamEnergyCMS();
122 
123 
124  // Medium hard to calculate variables
125  // ENeutralLE
126  if (gammaWithMaximumRho) {
127  calculationResult["ENeutralLE"] = getRho(gammaWithMaximumRho);
128  } else {
129  calculationResult["ENeutralLE"] = -1;
130  }
131 
132  // nECLMatchTracksLE
133  const unsigned int numberOfTracksWithECLMatch = std::count_if(m_pionParticles->begin(), m_pionParticles->end(),
134  [](const Particle & particle) {
135  return particle.getECLCluster() != nullptr;
136  });
137  calculationResult["nECLMatchTracksLE"] = numberOfTracksWithECLMatch;
138 
139  //nECLClustersLE
140  double neclClusters = -1.;
141  double eneclClusters = 0.;
142  StoreArray<ECLCluster> eclClusters;
143  ClusterUtils Cl;
144  double PzGamma = 0.;
145  double EsumGamma = 0.;
146  if (eclClusters.isValid()) {
147  const unsigned int numberOfECLClusters = std::count_if(eclClusters.begin(), eclClusters.end(),
148  [](const ECLCluster & eclcluster) {
149  return (eclcluster.hasHypothesis(
150  ECLCluster::EHypothesisBit::c_nPhotons)
151  and eclcluster.getEnergy(
152  ECLCluster::EHypothesisBit::c_nPhotons) > 0.1);
153  });
154  neclClusters = numberOfECLClusters;
155 
156  for (int ncl = 0; ncl < eclClusters.getEntries(); ncl++) {
157  if (eclClusters[ncl]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)
158  && eclClusters[ncl]->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons) > 0.1) {
159  eneclClusters += eclClusters[ncl]->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
160  if (!eclClusters[ncl]->getRelatedFrom<Track>()) {
161  TLorentzVector V4Gamma_CMS = PCmsLabTransform::labToCms(Cl.Get4MomentumFromCluster(eclClusters[ncl],
163  EsumGamma += V4Gamma_CMS.E();
164  PzGamma += V4Gamma_CMS.Pz();
165  }
166  }
167  }
168  }
169  calculationResult["nECLClustersLE"] = neclClusters;
170 
171  int nb2bcc_PhiHigh = 0;
172  int nb2bcc_PhiLow = 0;
173  int nb2bcc_3D = 0;
174  ClusterUtils C;
175  for (int i = 0; i < eclClusters.getEntries() - 1; i++) {
176  if (!eclClusters[i]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
177  continue;
178  TLorentzVector V4g1 = C.Get4MomentumFromCluster(eclClusters[i], ECLCluster::EHypothesisBit::c_nPhotons);
179  double Eg1 = V4g1.E();
180  for (int j = i + 1; j < eclClusters.getEntries(); j++) {
181  if (!eclClusters[j]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
182  continue;
183  TLorentzVector V4g2 = C.Get4MomentumFromCluster(eclClusters[j], ECLCluster::EHypothesisBit::c_nPhotons);
184  double Eg2 = V4g2.E();
185  const TVector3 V3g1 = (PCmsLabTransform::labToCms(V4g1)).Vect();
186  const TVector3 V3g2 = (PCmsLabTransform::labToCms(V4g2)).Vect();
187  double Thetag1 = (PCmsLabTransform::labToCms(V4g1)).Theta() * 180. / 3.1415926;
188  double Thetag2 = (PCmsLabTransform::labToCms(V4g2)).Theta() * 180. / 3.1415926;
189  double deltphi = fabs(V3g1.DeltaPhi(V3g2) * 180. / 3.1415926);
190  double Tsum = Thetag1 + Thetag2;
191  if (deltphi > 170. && (Eg1 > 0.25 && Eg2 > 0.25)) nb2bcc_PhiHigh++;
192  if (deltphi > 170. && (Eg1 < 0.25 || Eg2 < 0.25)) nb2bcc_PhiLow++;
193  if (deltphi > 160. && (Tsum > 160. && Tsum < 200.)) nb2bcc_3D++;
194  }
195  }
196 
197  calculationResult["nB2BCCPhiHighLE"] = nb2bcc_PhiHigh;
198  calculationResult["nB2BCCPhiLowLE"] = nb2bcc_PhiLow;
199  calculationResult["nB2BCC3DLE"] = nb2bcc_3D;
200 
201 
202  // AngleGTLE
203  double angleGTLE = -10.;
204  if (gammaWithMaximumRho) {
205  const TLorentzVector& V4g1 = gammaWithMaximumRho->get4Vector();
206  if (trackWithMaximumRho) {
207  const TLorentzVector& V4p1 = trackWithMaximumRho->get4Vector();
208  const double theta1 = (V4g1.Vect()).Angle(V4p1.Vect());
209  if (angleGTLE < theta1) angleGTLE = theta1;
210  }
211  if (trackWithSecondMaximumRho) {
212  const TLorentzVector& V4p2 = trackWithSecondMaximumRho->get4Vector();
213  const double theta2 = (V4g1.Vect()).Angle(V4p2.Vect());
214  if (angleGTLE < theta2) angleGTLE = theta2;
215  }
216  }
217 
218  calculationResult["AngleGTLE"] = angleGTLE;
219 
220  // AngleG1G2LE
221  double angleG1G2CMSLE = -10.;
222  if (gammaWithMaximumRho) {
223  const TLorentzVector& V4p1 = gammaWithMaximumRho->get4Vector();
224  if (gammaWithSecondMaximumRho) {
225  const TLorentzVector& V4p2 = gammaWithSecondMaximumRho->get4Vector();
226  const TVector3 V3p1 = (PCmsLabTransform::labToCms(V4p1)).Vect();
227  const TVector3 V3p2 = (PCmsLabTransform::labToCms(V4p2)).Vect();
228  angleG1G2CMSLE = V3p1.Angle(V3p2);
229  }
230  }
231 
232  calculationResult["AngleG1G2CMSLE"] = angleG1G2CMSLE;
233 
234  // maxAngleTTLE
235  double maxAngleTTLE = -10.;
236  int nJpsi = 0;
237  double Jpsi = 0.;
238  const double jPsiMasswindow = 0.11;
239  if (m_pionParticles->getListSize() >= 2) {
240  for (unsigned int i = 0; i < m_pionParticles->getListSize() - 1; i++) {
241  Particle* par1 = m_pionParticles->getParticle(i);
242  for (unsigned int j = i + 1; j < m_pionParticles->getListSize(); j++) {
243  Particle* par2 = m_pionParticles->getParticle(j);
244  TLorentzVector V4p1 = par1->get4Vector();
245  TLorentzVector V4p2 = par2->get4Vector();
246  TLorentzVector V4pSum = V4p1 + V4p2;
247  const auto chSum = par1->getCharge() + par2->getCharge();
248  const double mSum = V4pSum.M();
249  const double JpsidM = mSum - TDatabasePDG::Instance()->GetParticle(443)->Mass();
250  if (abs(JpsidM) < jPsiMasswindow && chSum == 0) nJpsi++;
251  const TVector3 V3p1 = (PCmsLabTransform::labToCms(V4p1)).Vect();
252  const TVector3 V3p2 = (PCmsLabTransform::labToCms(V4p2)).Vect();
253  const double temp = V3p1.Angle(V3p2);
254  if (maxAngleTTLE < temp) maxAngleTTLE = temp;
255  }
256  }
257  }
258 
259  if (nJpsi != 0) Jpsi = 1;
260 
261  calculationResult["maxAngleTTLE"] = maxAngleTTLE;
262  calculationResult["Jpsi"] = Jpsi;
263 
264  //maxAngleGGLE
265  double maxAngleGGLE = -10.;
266  if (m_gammaParticles->getListSize() >= 2) {
267  for (unsigned int i = 0; i < m_gammaParticles->getListSize() - 1; i++) {
268  Particle* par1 = m_gammaParticles->getParticle(i);
269  for (unsigned int j = i + 1; j < m_gammaParticles->getListSize(); j++) {
270  Particle* par2 = m_gammaParticles->getParticle(j);
271  TLorentzVector V4p1 = par1->get4Vector();
272  TLorentzVector V4p2 = par2->get4Vector();
273  const TVector3 V3p1 = (PCmsLabTransform::labToCms(V4p1)).Vect();
274  const TVector3 V3p2 = (PCmsLabTransform::labToCms(V4p2)).Vect();
275  const double temp = V3p1.Angle(V3p2);
276  if (maxAngleGGLE < temp) maxAngleGGLE = temp;
277  }
278  }
279  }
280 
281  calculationResult["maxAngleGGLE"] = maxAngleGGLE;
282 
283  // nEidLE
284  const unsigned int nEidLE = std::count_if(m_pionParticles->begin(), m_pionParticles->end(),
285  [](const Particle & p) {
286  const double& momentum = p.getMomentumMagnitude();
287  const double& r_rho = getRho(&p);
288  const ECLCluster* eclTrack = p.getECLCluster();
289  if (eclTrack) {
290  const double& energyOverMomentum = eclTrack->getEnergy(
291  ECLCluster::EHypothesisBit::c_nPhotons) / momentum;
292  double r_rhotoebeam = r_rho / BeamEnergyCMS();
293  return (r_rhotoebeam) > 0.35 && energyOverMomentum > 0.8;
294  }
295  return false;
296  });
297 
298  calculationResult["nEidLE"] = nEidLE;
299 
300 
301  // VisibleEnergyLE
302  const double visibleEnergyTracks = std::accumulate(m_pionParticles->begin(), m_pionParticles->end(), 0.0,
303  [](const double & visibleEnergy, const Particle & p) {
304  return visibleEnergy + p.getMomentumMagnitude();
305  });
306 
307  const double visibleEnergyGammas = std::accumulate(m_gammaParticles->begin(), m_gammaParticles->end(), 0.0,
308  [](const double & visibleEnergy, const Particle & p) {
309  return visibleEnergy + p.getMomentumMagnitude();
310  });
311 
312  calculationResult["VisibleEnergyLE"] = visibleEnergyTracks + visibleEnergyGammas;
313 
314  // EtotLE
315  const double eTotTracks = std::accumulate(m_pionParticles->begin(), m_pionParticles->end(), 0.0,
316  [](const double & eTot, const Particle & p) {
317  const ECLCluster* eclCluster = p.getECLCluster();
318  if (eclCluster) {
319  const double eclEnergy = eclCluster->getEnergy(
320  ECLCluster::EHypothesisBit::c_nPhotons);
321  if (eclEnergy > 0.1) {
322  return eTot + eclCluster->getEnergy(
323  ECLCluster::EHypothesisBit::c_nPhotons);
324  }
325  }
326  return eTot;
327  });
328 
329  const double eTotGammas = std::accumulate(m_gammaParticles->begin(), m_gammaParticles->end(), 0.0,
330  [](const double & eTot, const Particle & p) {
331  return eTot + p.getEnergy();
332  });
333  double Etot = eTotTracks + eTotGammas;
334  calculationResult["EtotLE"] = Etot;
335 
336  //KLM inforamtion
337  // The clusters with the largest pentrate layers in KLM.
338  double numMaxLayerKLM = -1.;
339  double numSecMaxLayerKLM = -1.;
340  StoreArray<KLMCluster> klmClusters;
341  if (klmClusters.isValid()) {
342  for (const auto& klmCluster : klmClusters) {
343  double klmClusterLayer = klmCluster.getLayers();
344  if (numMaxLayerKLM < klmClusterLayer) {
345  numSecMaxLayerKLM = numMaxLayerKLM;
346  numMaxLayerKLM = klmClusterLayer;
347  } else if (numSecMaxLayerKLM < klmClusterLayer)
348  numSecMaxLayerKLM = klmClusterLayer;
349  }
350  }
351  calculationResult["N1KLMLayer"] = numMaxLayerKLM;
352  calculationResult["N2KLMLayer"] = numSecMaxLayerKLM;
353 
354  //define bhabha_2trk, bhabha_1trk, eclbhabha
355  int charget1 = -10;
356  if (trackWithMaximumRho) charget1 = trackWithMaximumRho->getCharge();
357  int charget2 = -10;
358  if (trackWithSecondMaximumRho) charget2 = trackWithSecondMaximumRho->getCharge();
359 
360  double Bhabha2Trk = 0.;
361  int ntrk_bha = m_pionParticles->getListSize();
362  double rp1ob = rhoOfTrackWithMaximumRho / BeamEnergyCMS();
363  double rp2ob = rhoOfTrackWithSecondMaximumRho / BeamEnergyCMS();
364  bool bhabha2trk_tag =
365  ntrk_bha >= 2 && maxAngleTTLE > 2.88 && nEidLE >= 1 && rp1ob > 0.35 && rp2ob > 0.35 && (Etot) > 4.0
366  && (abs(charget1) == 1 && abs(charget2) == 1 && (charget1 + charget2) == 0);
367  if (bhabha2trk_tag) Bhabha2Trk = 1;
368  calculationResult["Bhabha2Trk"] = Bhabha2Trk;
369 
370  double Bhabha1Trk = 0.;
371  double rc1ob = rhoOfGammaWithMaximumRho / BeamEnergyCMS();
372  double rc2ob = rhoOfGammaWithSecondMaximumRho / BeamEnergyCMS();
373  bool bhabha1trk_tag = ntrk_bha == 1 && rp1ob > 0.35 && rc1ob > 0.35 && angleGTLE > 2.618;
374  if (bhabha1trk_tag) Bhabha1Trk = 1;
375  calculationResult["Bhabha1Trk"] = Bhabha1Trk;
376 
377  double ggSel = 0.;
378  bool gg_tag = ntrk_bha <= 1 && nEidLE == 0 && rc1ob > 0.35 && rc2ob > 0.2 && Etot > 4.0 && maxAngleGGLE > 2.618;
379  if (gg_tag) ggSel = 1;
380  calculationResult["GG"] = ggSel;
381 
382  // Bhabha skim with ECL information only (bhabhaecl)
383  double BhabhaECL = 0.;
384  ClusterUtils Cls;
385  for (int i = 0; i < eclClusters.getEntries() - 1; i++) {
386  if (!eclClusters[i]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
387  continue;
388 
389  TLorentzVector V4g1 = PCmsLabTransform::labToCms(Cls.Get4MomentumFromCluster(eclClusters[i],
391  double Eg1ob = V4g1.E() / (2 * BeamEnergyCMS());
392  for (int j = i + 1; j < eclClusters.getEntries(); j++) {
393  if (!eclClusters[j]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
394  continue;
395  TLorentzVector V4g2 = PCmsLabTransform::labToCms(Cls.Get4MomentumFromCluster(eclClusters[j],
397  double Eg2ob = V4g2.E() / (2 * BeamEnergyCMS());
398  const TVector3 V3g1 = V4g1.Vect();
399  const TVector3 V3g2 = V4g2.Vect();
400  double Thetag1 = V4g1.Theta() * TMath::RadToDeg();
401  double Thetag2 = V4g2.Theta() * TMath::RadToDeg();
402  double deltphi = fabs(V3g1.DeltaPhi(V3g2) * TMath::RadToDeg());
403  double Tsum = Thetag1 + Thetag2;
404  if ((deltphi > 165. && deltphi < 178.5) && (Eg1ob > 0.4 && Eg2ob > 0.4 && (Eg1ob > 0.45 || Eg2ob > 0.45)) && (Tsum > 178.
405  && Tsum < 182.)) BhabhaECL = 1;
406  }
407  }
408  calculationResult["BhabhaECL"] = BhabhaECL;
409 
410  // Radiative Bhabha skim (radee) for CDC dE/dx calib studies
411  double radee = 0.;
412  const double lowdEdxEdge = 0.70, highdEdxEdge = 1.30;
413  const double lowEoPEdge = 0.70, highEoPEdge = 1.30;
414 
415  if (m_pionParticles->getListSize() == 2) {
416 
417  //------------First track variables----------------
418  for (unsigned int i = 0; i < m_pionParticles->getListSize() - 1; i++) {
419 
420  Particle* part1 = m_pionParticles->getParticle(i);
421  if (!part1) continue;
422 
423  const auto chargep1 = part1->getCharge();
424  if (abs(chargep1) != 1) continue;
425 
426  const ECLCluster* eclTrack1 = part1->getECLCluster();
427  if (!eclTrack1) continue;
428  if (!eclTrack1->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
429 
430  const double& momentum1 = part1->getMomentumMagnitude();
431  const double& energyOverMomentum1 = eclTrack1->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons) / momentum1;
432  if (energyOverMomentum1 <= lowEoPEdge || energyOverMomentum1 >= highEoPEdge) continue;
433 
434  const Track* track1 = part1->getTrack();
435  if (!track1) continue;
436 
437  const TrackFitResult* trackFit1 = track1->getTrackFitResultWithClosestMass(Const::pion);
438  if (!trackFit1) continue;
439  if (trackFit1->getHitPatternCDC().getNHits() <= 0) continue;
440 
441  const CDCDedxTrack* dedxTrack1 = track1->getRelatedTo<CDCDedxTrack>();
442  if (!dedxTrack1) continue;
443 
444  //------------Second track variables----------------
445  for (unsigned int j = i + 1; j < m_pionParticles->getListSize(); j++) {
446 
447  Particle* part2 = m_pionParticles->getParticle(j);
448  if (!part2) continue;
449 
450  const auto chargep2 = part2->getCharge();
451  if (abs(chargep2) != 1 || (chargep1 + chargep2 != 0)) continue;
452 
453  const ECLCluster* eclTrack2 = part2->getECLCluster();
454  if (!eclTrack2) continue;
455  if (!eclTrack2->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
456 
457  const double& momentum2 = part2->getMomentumMagnitude();
458  const double& energyOverMomentum2 = eclTrack2->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons) / momentum2;
459  if (energyOverMomentum2 <= lowEoPEdge || energyOverMomentum2 >= highEoPEdge) continue;
460 
461  const Track* track2 = part2->getTrack();
462  if (!track2) continue;
463 
464  const TrackFitResult* trackFit2 = track2->getTrackFitResultWithClosestMass(Const::pion);
465  if (!trackFit2) continue;
466  if (trackFit2->getHitPatternCDC().getNHits() <= 0) continue;
467 
468  CDCDedxTrack* dedxTrack2 = track2->getRelatedTo<CDCDedxTrack>();
469  if (!dedxTrack2) continue;
470 
471  double p1_dedxnosat = dedxTrack1->getDedxNoSat();
472  double p2_dedxnosat = dedxTrack2->getDedxNoSat();
473 
474  if ((p1_dedxnosat > lowdEdxEdge && p1_dedxnosat < highdEdxEdge) || (p2_dedxnosat > lowdEdxEdge
475  && p2_dedxnosat < highdEdxEdge))radee = 1;
476 
477  }
478  }
479  }
480 
481  calculationResult["Radee"] = radee;
482 
483  // Dimuon skim (mumutight) taken from the offline skim + Radiative dimuon (radmumu)
484  double mumutight = 0.;
485  double eMumuTotGammas = 0.;
486  int nTracks = 0;
487  double radmumu = 0.;
488  int nGammas = m_gammaParticles->getListSize();
489 
490  for (int t = 0; t < nGammas; t++) {
491  const Particle* part = m_gammaParticles->getParticle(t);
492  const auto& frame = ReferenceFrame::GetCurrent();
493  eMumuTotGammas += frame.getMomentum(part).E();
494  }
495 
496  StoreArray<Track> tracks;
497  nTracks = tracks.getEntries();
499  const TLorentzVector pIN = T.getBeamFourMomentum();
500  const auto& fr = ReferenceFrame::GetCurrent();
501 
502  if (m_pionParticles->getListSize() == 2) {
503 
504  //------------First track variables----------------
505  for (unsigned int k = 0; k < m_pionParticles->getListSize() - 1; k++) {
506 
507  Particle* part1 = m_pionParticles->getParticle(k);
508  if (!part1) continue;
509 
510  const auto chargep1 = part1->getCharge();
511  if (abs(chargep1) != 1) continue;
512 
513  const ECLCluster* eclTrack1 = part1->getECLCluster();
514  if (!eclTrack1) continue;
515  if (!eclTrack1->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
516 
517  const Track* track1 = part1->getTrack();
518  if (!track1) continue;
519 
520  const TrackFitResult* trackFit1 = track1->getTrackFitResultWithClosestMass(Const::pion);
521  if (!trackFit1) continue;
522 
523  const TLorentzVector V4p1 = trackFit1->get4Momentum();
524  const TVector3 V3p1 = (PCmsLabTransform::labToCms(V4p1)).Vect();
525 
526  const double p1MomLab = V4p1.P();
527  double highestP = p1MomLab;
528  const double p1CDChits = trackFit1->getHitPatternCDC().getNHits();
529  const PIDLikelihood* p1Pid = part1->getPIDLikelihood();
530  bool p1hasKLMid = 0;
531  if (p1Pid) p1hasKLMid = p1Pid->isAvailable(Const::KLM);
532  const double p1isInCDC = Variable::inCDCAcceptance(part1);
533  const double p1clusPhi = Variable::eclClusterPhi(part1);
534 
535  const double Pp1 = V3p1.Mag();
536  const double Thetap1 = (V3p1).Theta() * TMath::RadToDeg();
537  const double Phip1 = (V3p1).Phi() * TMath::RadToDeg();
538 
539  const double enECLTrack1 = eclTrack1->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
540 
541  const bool goodTrk1 = enECLTrack1 > 0 && enECLTrack1 < 0.5 && p1CDChits > 0
542  && ((p1hasKLMid == 0 && enECLTrack1 < 0.25 && p1MomLab < 2.0) || p1hasKLMid == 1) && p1isInCDC == 1;
543 
544  //------------Second track variables----------------
545  for (unsigned int l = k + 1; l < m_pionParticles->getListSize(); l++) {
546 
547  Particle* part2 = m_pionParticles->getParticle(l);
548  if (!part2) continue;
549 
550  const auto chargep2 = part2->getCharge();
551  if (abs(chargep2) != 1 || (chargep1 + chargep2 != 0)) continue;
552 
553  const ECLCluster* eclTrack2 = part2->getECLCluster();
554  if (!eclTrack2) continue;
555  if (!eclTrack2->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
556 
557  const Track* track2 = part2->getTrack();
558  if (!track2) continue;
559 
560  const TrackFitResult* trackFit2 = track2->getTrackFitResultWithClosestMass(Const::pion);
561  if (!trackFit2) continue;
562 
563  const TLorentzVector V4p2 = trackFit2->get4Momentum();
564  const TVector3 V3p2 = (PCmsLabTransform::labToCms(V4p2)).Vect();
565 
566  const double p2MomLab = V4p2.P();
567  double lowestP = p2MomLab;
568  const double p2CDChits = trackFit2->getHitPatternCDC().getNHits();
569  const PIDLikelihood* p2Pid = part2->getPIDLikelihood();
570  bool p2hasKLMid = 0;
571  if (p2Pid) p2hasKLMid = p2Pid->isAvailable(Const::KLM);
572  const double p2isInCDC = Variable::inCDCAcceptance(part2);
573  const double p2clusPhi = Variable::eclClusterPhi(part2);
574 
575  const double Pp2 = V3p2.Mag();
576  const double Thetap2 = (V3p2).Theta() * TMath::RadToDeg();
577  const double Phip2 = (V3p2).Phi() * TMath::RadToDeg();
578 
579  const double acopPhi = fabs(180 - fabs(Phip1 - Phip2));
580  const double acopTheta = fabs(fabs(Thetap1 + Thetap2) - 180);
581 
582  const double enECLTrack2 = eclTrack2->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
583 
584  const bool goodTrk2 = enECLTrack2 > 0 && enECLTrack2 < 0.5 && p2CDChits > 0
585  && ((p2hasKLMid == 0 && enECLTrack2 < 0.25 && p2MomLab < 2.0) || p2hasKLMid == 1) && p2isInCDC == 1;
586 
587  double eTotMumuTracks = enECLTrack1 + enECLTrack2;
588  double EMumutot = eTotMumuTracks + eMumuTotGammas;
589 
590  bool mumutight_tag = enECLTrack1 < 0.5 && enECLTrack2 < 0.5 && EMumutot < 2 && acopPhi < 10 && acopTheta < 10 && nTracks == 2
591  && Pp1 > 0.5 && Pp2 > 0.5;
592 
593  if (mumutight_tag) mumutight = 1;
594 
595  if (p1MomLab < p2MomLab) {
596  lowestP = highestP;
597  highestP = p2MomLab;
598  }
599 
600  double diffPhi = p1clusPhi - p2clusPhi;
601  if (fabs(diffPhi) > M_PI) {
602  if (diffPhi > M_PI) {
603  diffPhi = diffPhi - 2 * M_PI;
604  } else {
605  diffPhi = 2 * M_PI + diffPhi;
606  }
607  }
608 
609  const double recoilP = fr.getMomentum(pIN - V4p1 - V4p2).P();
610 
611  const bool radmumu_tag = nTracks < 4 && goodTrk1 == 1 && goodTrk2 == 1 && highestP > 1 && lowestP < 3 && (p1hasKLMid == 1
612  || p2hasKLMid == 1) && abs(diffPhi) >= 0.5 * M_PI && recoilP > 0.1 && (enECLTrack1 <= 0.25 || enECLTrack2 <= 0.25);
613 
614  if (radmumu_tag) radmumu = 1;
615 
616  }
617  }
618  }
619 
620  calculationResult["MumuTight"] = mumutight;
621  calculationResult["Radmumu"] = radmumu;
622 
623  //Retrieve variables for HadronB skims
624  double EsumPiHad = 0;
625  double PzPiHad = 0;
626  int nHadTracks = m_pionHadParticles->getListSize();
627  double hadronb = 0;
628  double hadronb1 = 0;
629  double hadronb2 = 0;
630  std::vector<TVector3> m_pionHadv3;
631 
632  for (int nPiHad = 0; nPiHad < nHadTracks; nPiHad++) {
633  Particle* parPiHad = m_pionHadParticles->getParticle(nPiHad);
634  TLorentzVector V4PiHad = PCmsLabTransform::labToCms(parPiHad->get4Vector());
635  m_pionHadv3.push_back(parPiHad->getMomentum());
636  EsumPiHad += V4PiHad.E();
637  PzPiHad += V4PiHad.Pz();
638  }
639 
640  double visibleEnergyCMSnorm = (EsumPiHad + EsumGamma) / (BeamEnergyCMS() * 2.0);
641  double EsumCMSnorm = eneclClusters / (BeamEnergyCMS() * 2.0);
642  double PzTotCMSnorm = (PzPiHad + PzGamma) / (BeamEnergyCMS() * 2.0);
643 
644  bool hadronb_tag = nHadTracks >= 3 && visibleEnergyCMSnorm > 0.2 && abs(PzTotCMSnorm) < 0.5 && neclClusters > 1
645  && EsumCMSnorm > 0.1 && EsumCMSnorm < 0.8;
646 
647  if (hadronb_tag) {
648  hadronb = 1;
649  FoxWolfram fw(m_pionHadv3);
650  fw.calculateBasicMoments();
651  double R2 = fw.getR(2);
652  if (R2 < 0.4) hadronb1 = 1;
653  if (hadronb1 && nHadTracks >= 5) hadronb2 = 1;
654  }
655 
656  calculationResult["HadronB"] = hadronb;
657  calculationResult["HadronB1"] = hadronb1;
658  calculationResult["HadronB2"] = hadronb2;
659 
660  // nKshort
661  int nKshort = 0;
662  double Kshort = 0.;
663  const double KsMassLow = 0.468;
664  const double KsMassHigh = 0.528;
665 
666  if (m_KsParticles.isValid()) {
667  for (unsigned int i = 0; i < m_KsParticles->getListSize(); i++) {
668  const Particle* mergeKsCand = m_KsParticles->getParticle(i);
669  const double isKsCandGood = Variable::goodBelleKshort(mergeKsCand);
670  const double KsCandMass = mergeKsCand->getMass();
671  if (KsCandMass > KsMassLow && KsCandMass < KsMassHigh && isKsCandGood == 1.) nKshort++;
672  }
673  }
674 
675  if (nKshort != 0) Kshort = 1;
676 
677  calculationResult["Kshort"] = Kshort;
678 
679  // 4 leptons skim
680  int nFourLep = 0;
681  double fourLep = 0.;
682 
683  const double visibleEnergyCMS = visibleEnergyCMSnorm * BeamEnergyCMS() * 2.0;
684  const unsigned int n_particles = m_pionHadParticles->getListSize();
685 
686  if (n_particles >= 2) {
687  for (unsigned int i = 0; i < n_particles - 1; i++) {
688  Particle* par1 = m_pionHadParticles->getParticle(i);
689  for (unsigned int j = i + 1; j < n_particles; j++) {
690  Particle* par2 = m_pionHadParticles->getParticle(j);
691  const auto chSum = par1->getCharge() + par2->getCharge();
692  const TLorentzVector V4p1 = par1->get4Vector();
693  const TLorentzVector V4p2 = par2->get4Vector();
694  const double opAng = V4p1.Theta() - V4p2.Theta();
695  const TLorentzVector V4pSum = V4p1 + V4p2;
696  const TLorentzVector V4pSumCMS = PCmsLabTransform::labToCms(V4pSum);
697  const double ptCMS = V4pSumCMS.Pt();
698  const double pzCMS = V4pSumCMS.Pz();
699  const double mSum = V4pSum.M();
700 
701  const bool fourLepCand = chSum == 0 && (V4p1.P() > 0.4 && V4p2.P() > 0.4) && cos(opAng) > -0.997 && ptCMS < 0.15 && abs(pzCMS) < 2.5
702  && mSum < 6;
703 
704  if (fourLepCand) nFourLep++;
705  }
706  }
707  }
708 
709  if (nFourLep != 0 && visibleEnergyCMS < 6) fourLep = 1;
710 
711  calculationResult["FourLep"] = fourLep;
712 
713  // nLambda
714  unsigned int nLambda = 0;
715 
716  if (m_LambdaParticles.isValid()) {
717  for (unsigned int i = 0; i < m_LambdaParticles->getListSize(); i++) {
718  const Particle* mergeLambdaCand = m_LambdaParticles->getParticle(i);
719  const double flightDist = Variable::flightDistance(mergeLambdaCand);
720  const double flightDistErr = Variable::flightDistanceErr(mergeLambdaCand);
721  const double flightSign = flightDist / flightDistErr;
722  const Particle* protCand = mergeLambdaCand->getDaughter(0);
723  const Particle* pionCand = mergeLambdaCand->getDaughter(1);
724  const double protMom = protCand->getMomentum().Mag();
725  const double pionMom = pionCand->getMomentum().Mag();
726  const double asymPDaughters = (protMom - pionMom) / (protMom + pionMom);
727  if (flightSign > 10 && asymPDaughters > 0.41) nLambda++;
728  }
729  }
730 
731  if (nLambda > 0) {
732  calculationResult["Lambda"] = 1;
733  } else {
734  calculationResult["Lambda"] = 0;
735  }
736 
737  // nDstp
738  unsigned int nDstp1 = 0;
739  unsigned int nDstp2 = 0;
740  unsigned int nDstp3 = 0;
741  unsigned int nDstp4 = 0;
742 
743  if (m_DstParticles.isValid() && (ntrk_bha >= 3 && Bhabha2Trk == 0)) {
744  for (unsigned int i = 0; i < m_DstParticles->getListSize(); i++) {
745  const Particle* allDstCand = m_DstParticles->getParticle(i);
746  const double dstDecID = allDstCand->getExtraInfo("decayModeID");
747  if (dstDecID == 1.) nDstp1++;
748  if (dstDecID == 2.) nDstp2++;
749  if (dstDecID == 3.) nDstp3++;
750  if (dstDecID == 4.) nDstp4++;
751  }
752  }
753 
754 
755  if (nDstp1 > 0) {
756  calculationResult["Dstp1"] = 1;
757  } else {
758  calculationResult["Dstp1"] = 0;
759  }
760 
761  if (nDstp2 > 0) {
762  calculationResult["Dstp2"] = 1;
763  } else {
764  calculationResult["Dstp2"] = 0;
765  }
766 
767  if (nDstp3 > 0) {
768  calculationResult["Dstp3"] = 1;
769  } else {
770  calculationResult["Dstp3"] = 0;
771  }
772 
773  if (nDstp4 > 0) {
774  calculationResult["Dstp4"] = 1;
775  } else {
776  calculationResult["Dstp4"] = 0;
777  }
778 
779  // nTracksOffIP
780  calculationResult["nTracksOffIP"] = m_offIpParticles->getListSize();
781 
782  // Flag for events with Trigger B2Link information
783  calculationResult["NeuroTRG"] = 0;
784 
786  if (filter_result.isValid()) {
787  const std::map<std::string, int>& nonPrescaledResults = filter_result->getNonPrescaledResults();
788  if (nonPrescaledResults.find(m_filterL1TrgNN) != nonPrescaledResults.end()) {
789  const bool hasNN = (filter_result->getNonPrescaledResult(m_filterL1TrgNN) == SoftwareTriggerCutResult::c_accept);
790  if (hasNN) calculationResult["NeuroTRG"] = 1;
791  }
792  }
793 
794  //Dimuon skim with invariant mass cut allowing at most one track not to be associated with ECL clusters
795 
796  double mumuHighMass = 0.;
797 
798  if (trackWithMaximumRho && trackWithSecondMaximumRho) {
799  int hasClus = 0;
800  double eclE1 = 0., eclE2 = 0.;
801 
802  const auto charge1 = trackWithMaximumRho->getCharge();
803  const auto charge2 = trackWithSecondMaximumRho->getCharge();
804  const auto chSum = charge1 + charge2;
805 
806  const ECLCluster* eclTrack1 = trackWithMaximumRho->getECLCluster();
807  if (eclTrack1) {
808  hasClus++;
810  }
811 
812  const ECLCluster* eclTrack2 = trackWithSecondMaximumRho->getECLCluster();
813  if (eclTrack2) {
814  hasClus++;
816  }
817  const TLorentzVector V4p1 = PCmsLabTransform::labToCms(trackWithMaximumRho->get4Vector());
818  const TLorentzVector V4p2 = PCmsLabTransform::labToCms(trackWithSecondMaximumRho->get4Vector());
819 
820  const TLorentzVector V4pSum = V4p1 + V4p2;
821  const double mSum = V4pSum.M();
822 
823  const double thetaSumCMS = (V4p1.Theta() + V4p2.Theta()) * TMath::RadToDeg();
824  const double phi1CMS = V4p1.Phi() * TMath::RadToDeg();
825  const double phi2CMS = V4p2.Phi() * TMath::RadToDeg();
826 
827  double diffPhi = phi1CMS - phi2CMS;
828  if (fabs(diffPhi) > 180) {
829  if (diffPhi > 180) {
830  diffPhi = diffPhi - 2 * 180;
831  } else {
832  diffPhi = 2 * 180 + diffPhi;
833  }
834  }
835  const double delThetaCMS = fabs(fabs(thetaSumCMS) - 180);
836  const double delPhiCMS = fabs(180 - fabs(diffPhi));
837 
838  const bool mumuHighMassCand = chSum == 0 && (mSum > 8. && mSum < 12.) && hasClus > 0 && eclE1 <= 1
839  && eclE2 <= 1 && delThetaCMS < 10 && delPhiCMS < 10;
840 
841  if (mumuHighMassCand) mumuHighMass = 1;
842 
843  }
844 
845  calculationResult["MumuHighM"] = mumuHighMass;
846 }
Debug output for CDCDedxPID module.
Definition: CDCDedxTrack.h:25
double getDedxNoSat() const
Get dE/dx truncated mean without the saturation correction for this track.
Definition: CDCDedxTrack.h:106
Class to provide momentum-related information from ECLClusters.
Definition: ClusterUtils.h:34
const TLorentzVector Get4MomentumFromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns four momentum vector.
Definition: ClusterUtils.cc:24
static const ChargedStable pion
charged pion particle
Definition: Const.h:542
ECL cluster data.
Definition: ECLCluster.h:27
bool hasHypothesis(EHypothesisBit bitmask) const
Return if specific hypothesis bit is set.
Definition: ECLCluster.h:348
double getEnergy(EHypothesisBit hypothesis) const
Return Energy (GeV).
Definition: ECLCluster.cc:19
@ c_nPhotons
CR is split into n photons (N1)
Class to calculate the Fox-Wolfram moments up to order 8.
Definition: FoxWolfram.h:28
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
Class to hold Lorentz transformations from/to CMS and boost vector.
TLorentzVector getBeamFourMomentum() const
Returns LAB four-momentum of e+e-.
static TLorentzVector labToCms(const TLorentzVector &vec)
Transforms Lorentz vector into CM System.
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Definition: PIDLikelihood.h:26
bool isAvailable(Const::PIDDetectorSet set) const
Check whether PID information from a given set of detectors is available.
Definition: PIDLikelihood.h:50
Class to store reconstructed particles.
Definition: Particle.h:74
const Track * getTrack() const
Returns the pointer to the Track object that was used to create this Particle (ParticleType == c_Trac...
Definition: Particle.cc:814
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition: Particle.cc:860
float getExtraInfo(const std::string &name) const
Return given value if set.
Definition: Particle.cc:1242
float getMass() const
Returns invariant mass (= nominal for FS particles)
Definition: Particle.h:445
TVector3 getMomentum() const
Returns momentum vector.
Definition: Particle.h:488
const PIDLikelihood * getPIDLikelihood() const
Returns the pointer to the PIDLikelihood object that is related to the Track, which was used to creat...
Definition: Particle.cc:840
float getCharge(void) const
Returns particle charge.
Definition: Particle.cc:630
TLorentzVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:477
float getMomentumMagnitude() const
Returns momentum magnitude.
Definition: Particle.h:497
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
Definition: Particle.cc:639
static const ReferenceFrame & GetCurrent()
Get current rest frame.
StoreObjPtr< ParticleList > m_pionParticles
Internal storage of the tracks as particles.
StoreObjPtr< ParticleList > m_gammaParticles
Internal storage of the ECL clusters as particles.
StoreObjPtr< ParticleList > m_LambdaParticles
Internal storage of the Lambda0's.
StoreObjPtr< ParticleList > m_pionHadParticles
Internal storage of the tracks as particles (definition for hadronb).
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.
SkimSampleCalculator()
Set the default names for the store object particle lists.
StoreObjPtr< ParticleList > m_KsParticles
Internal storage of the K_S0's.
StoreObjPtr< ParticleList > m_DstParticles
Internal storage of the D*'s.
StoreObjPtr< ParticleList > m_pionTauParticles
Internal storage of the tracks as particles (definition for tau skims).
StoreObjPtr< ParticleList > m_offIpParticles
Internal storage of the tracks for alignment calibration.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
bool isValid() const
Check wether the array was registered.
Definition: StoreArray.h:288
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
iterator end()
Return iterator to last entry +1.
Definition: StoreArray.h:320
iterator begin()
Return iterator to first entry.
Definition: StoreArray.h:318
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:110
Values of the result of a track fit with a given particle hypothesis.
TLorentzVector get4Momentum() const
Getter for the 4Momentum at the closest approach of the track in the r/phi projection.
HitPatternCDC getHitPatternCDC() const
Getter for the hit pattern in the CDC;.
Class that bundles various TrackFitResults.
Definition: Track.h:25
@ c_accept
Accept this event.
Abstract base class for different kinds of events.