ATLAS Offline Software
xAODBSignalFilter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // -----------------------------------------------------------------------------------------------
6 //
7 // xAODBSignalFilter.cxx
8 //
9 // Description: finds all B-chains, applies cuts specified in jobOptionsFile
10 //
11 // Author: Malte Muller <maltemlr@yahoo.co.uk>
12 // August 2002 Malte Muller
13 // Sept. 2002 M.Smizanska: minor updates in fill Ntuple
14 // Dec. 2003 M.Smizanska: filtering out events with B-hadrons
15 // left undecayed either in Pythia or in EvtGen.
16 // This is used as a method of selecting only wanted
17 // exclusive channels into persistent output. See PythiaB manual.
18 // Feb. 2004 J. Catmore LVL1/LVL2 cut facility added.
19 //
20 // Sept. 2013 C. Alpigiani - Removed the code that writes the ntuples
21 // - Wrote the code that implements the particle selection (pT, eta
22 // and invariant mass)
23 // -----------------------------------------------------------------------------------------------
24 
27 #include "CLHEP/Vector/LorentzVector.h"
29 
30 #include <sstream>
31 
32 xAODBSignalFilter::xAODBSignalFilter(const std::string &name, ISvcLocator *pSvcLocator) : GenFilter(name, pSvcLocator)
33 {
34  // ** Declare the algorithm's properties **
35  declareProperty("LVL1MuonCutOn", m_localLVL1MuonCutOn = false);
36  declareProperty("LVL2MuonCutOn", m_localLVL2MuonCutOn = false);
37  declareProperty("LVL2ElectronCutOn", m_localLVL2ElectronCutOn = false);
38  declareProperty("LVL1MuonCutPT", m_localLVL1MuonCutPT = 0.0);
39  declareProperty("LVL1MuonCutEta", m_localLVL1MuonCutEta = 102.5);
40  declareProperty("LVL2MuonCutPT", m_localLVL2MuonCutPT = 0.0);
41  declareProperty("LVL2MuonCutEta", m_localLVL2MuonCutEta = 102.5);
42  declareProperty("LVL2ElectronCutPT", m_localLVL2ElectronCutPT = 0.0);
43  declareProperty("LVL2ElectronCutEta", m_localLVL2ElectronCutEta = 102.5);
44  declareProperty("Cuts_Final_e_switch", m_cuts_f_e_on = false);
45  declareProperty("Cuts_Final_e_pT", m_cuts_f_e_pT = 0.);
46  declareProperty("Cuts_Final_e_eta", m_cuts_f_e_eta = 2.5);
47  declareProperty("Cuts_Final_mu_switch", m_cuts_f_mu_on = false);
48  declareProperty("Cuts_Final_mu_pT", m_cuts_f_mu_pT = 0.);
49  declareProperty("Cuts_Final_mu_eta", m_cuts_f_mu_eta = 102.5);
50  declareProperty("Cuts_Final_hadrons_switch", m_cuts_f_had_on = false);
51  declareProperty("Cuts_Final_hadrons_pT", m_cuts_f_had_pT = 0.);
52  declareProperty("Cuts_Final_hadrons_eta", m_cuts_f_had_eta = 102.5);
53  declareProperty("Cuts_Final_gamma_switch", m_cuts_f_gam_on = false);
54  declareProperty("Cuts_Final_gamma_pT", m_cuts_f_gam_pT = 0.);
55  declareProperty("Cuts_Final_gamma_eta", m_cuts_f_gam_eta = 102.5);
56  declareProperty("Cuts_Final_K0_switch", m_cuts_f_K0_on = false);
57  declareProperty("Cuts_Final_K0_pT", m_cuts_f_K0_pT = 0.);
58  declareProperty("Cuts_Final_K0_eta", m_cuts_f_K0_eta = 102.5);
59  //
60  // ** Declare the signal B-meson/hadron PDGid
61  declareProperty("B_PDGCode", m_B_pdgid = 0);
62  //
63  // ** Declare properties for mass filter **
64  declareProperty("InvMass_switch", m_InvMass_switch = false);
65  declareProperty("InvMass_PartId1", m_InvMass_PartId1 = 13);
67  declareProperty("InvMass_PartFakeMass1", m_InvMass_PartFakeMass1 = -1.);
68  declareProperty("InvMass_PartFakeMass2", m_InvMass_PartFakeMass2 = -1.);
69  declareProperty("InvMassMin", m_InvMassMin = 0.0);
70  declareProperty("InvMassMax", m_InvMassMax = 14000000.0);
71  declareProperty("TotalInvMass_switch", m_TotalInvMass_switch = false);
72  declareProperty("TotalInvMassMin", m_TotalInvMassMin = 0.0);
73  declareProperty("TotalInvMassMax", m_TotalInvMassMax = 14000000.0);
74 
75  // ** Initialise event counter **
76  m_EventCnt = 0;
77  m_LVL1Counter = 0;
78  m_LVL2Counter = 0;
80  m_rejectedAll = 0;
81 }
82 
84 {
85  ATH_MSG_INFO("");
86  ATH_MSG_INFO(" ---------------------------------- ");
87  ATH_MSG_INFO(" >>> xAODBSignalFilter::FilterEvent <<< ");
88  ATH_MSG_INFO(" ---------------------------------- ");
89  ATH_MSG_INFO("");
90 
91  // ** Return ERROR and exit if the user has not selected the PDGid of the B-meson/hadron signal **
93  if (m_B_pdgid == 0)
94  {
95  ATH_MSG_ERROR("");
96  ATH_MSG_ERROR(" ==>> 'B_PDGCode = 0'! Please define the PDGid of the B-meson/hadron signal!");
97  ATH_MSG_ERROR("");
98  return StatusCode::FAILURE;
99  }
100 // Retrieve TruthGen container from xAOD Gen slimmer, contains all particles witout barcode_zero and
101 // duplicated barcode ones
102  const xAOD::TruthParticleContainer* xTruthParticleContainer;
103  if (evtStore()->retrieve(xTruthParticleContainer, "TruthGen").isFailure()) {
104  ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthGen" << " found in StoreGate!");
105  return StatusCode::FAILURE;
106  }
107 
108 bool acceptEvent = true;
109 unsigned int nPart = xTruthParticleContainer->size();
110 // ** Check HepMC for particles activating LVL1 trigger, if that is what user wishes **
111 //
112 bool LVL1Passed = false;
113 const xAOD::TruthParticle* LVL1Muon = 0;
114 //
116  {
117  //
118 
119  // Loop over all particles in the event
120  for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
121  const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
122 
123  bool LVL1Result = LVL1_Mu_Trigger(part);
124  if (LVL1Result)
125  {
126  LVL1Passed = true;
127  LVL1Muon = part; // Remember the muon for LVL2 testing
128  break;
129  }
130  } // loop over TruthParticles
131  }
132 
133 // ** Check HepMC for particles activating LVL2 trigger, if that is what user wishes **
134 //
135 bool LVL2Passed = false;
136 //
137 if (LVL1Passed && (m_localLVL2MuonCutOn || m_localLVL2ElectronCutOn))
138  {
139  for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
140  const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
141  bool LVL2Result = LVL2_eMu_Trigger(part);
142  if (LVL2Result)
143  {
144  if (part != LVL1Muon) // Check the particle triggering LVL2 isn't
145  LVL2Passed = true; // the muon that triggered LVL1 --> Artificial,
146  // since, effectively, LVL2 trigger is not applied.
147  // This is needed to "trigger" the 2nd muon!
148  }
149  } //loop over particles
150  }
151 
152  // ** Flag event as passing LVL1 if it has passed **
153  //
154  if (m_localLVL1MuonCutOn && LVL1Passed)
155  {
156  ATH_MSG_DEBUG(" LVL1 Trigger activated for event " << m_EventCnt);
157  m_LVL1Counter++;
158  }
159  // ** Flag event as passing LVL2 if it has passed **
160  //
161  if ((m_localLVL2MuonCutOn || m_localLVL2ElectronCutOn) && LVL2Passed)
162  {
163  ATH_MSG_DEBUG(" LVL2 Trigger activated for event " << m_EventCnt);
164  m_LVL2Counter++;
165  }
166 
167  // ** If user hasn't requested triggers then set everything to true so nothing is thrown away **
168  //
170  {
171  LVL1Passed = true;
172  LVL2Passed = true;
173  }
175  LVL2Passed = true;
176 
177  // ** Reject event if an undecayed quark is found **
178  //
179  for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
180  const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
181  if (std::abs(part->pdgId()) <= 6 && MC::isStable(part))
182  {
183  acceptEvent = false;
184  ATH_MSG_WARNING(" Undecayed quark " << part);
185  }
186  }
187 
188  // ** Look for signal events **
189  //
190  bool SignalPassedCuts = false;
191  if (LVL1Passed && LVL2Passed)
192  {
193  // ** Loop on all particles **
194  for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
195  const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
196  const int particleID = part->pdgId();
197  //
198  bool motherIsB = false;
199  bool newBChain = false;
200 
201  if ((MC::isBottomMeson(particleID) || MC::isBottomBaryon(particleID)) && MC::isPhysical(part) )
202  {
203  // ** Reject whole event if any of B-hadrons in the event is not decayed **
204  if (MC::isStable(part) || part->status() == HepMC::EVTGENUNDECAYEDSTATUS)
205  {
206  acceptEvent = false;
207  }
208 
209  for(size_t thisParent_id=0; thisParent_id < part->prodVtx()->nIncomingParticles(); thisParent_id++)
210  {
211  auto parent = part->prodVtx()->incomingParticle(thisParent_id);
212  int parentID = parent->pdgId();
213  if (MC::isBottomMeson(parentID) || MC::isBottomBaryon(parentID))
214  motherIsB = true;
215  }
216  if (motherIsB)
217  {
218  newBChain = false; // Since the chain is not new
219  }
220  else
221  {
222  newBChain = true;
223  }
224  }
225  else
226  {
227  newBChain = false;
228  } // Since particle is not b
229 
230  // ** New B-signal found, output message and find whole decay tree **
231  if (newBChain)
232  {
233  const HepPDT::ParticleData *HadronData = particleData(particleID);
234  std::string HadronName = "unknown particle";
235  if (HadronData)
236  {
237  HadronName = HadronData->name();
238  if (particleID < 0)
239  HadronName = "anti - " + HadronName;
240  }
241  ATH_MSG_DEBUG("");
242  ATH_MSG_DEBUG(" ------------------------------------------ ");
243  ATH_MSG_DEBUG(" *** xAODBSignalFilter.cxx: B-signal found *** ");
244  ATH_MSG_DEBUG(" ------------------------------------------ ");
245  ATH_MSG_DEBUG("");
246  // cppcheck-suppress shiftNegative; false positive
247  ATH_MSG_DEBUG(" Event " << m_EventCnt << " --> B-hadron/B-meson (" << HadronName << ") " << part);
248  ATH_MSG_DEBUG("");
249 
250  // ** Looping on all children checking if they have passed the selection cuts defined by the user **
252  {
253  ATH_MSG_DEBUG(" *** KINEMATIC CUTS ON PARTICLES ACTIVATED *** ");
254  ATH_MSG_DEBUG("");
255  ATH_MSG_DEBUG(" --------------------------------- ");
256  ATH_MSG_DEBUG(" Started looping on all children ");
257  ATH_MSG_DEBUG(" --------------------------------- ");
258  ATH_MSG_DEBUG("");
259  //
260  bool isSignal = false;
261  bool havePassedCuts = true;
262  TLorentzVector CandPart1, CandPart2, total_4mom;
263  //
264  FindAllChildren(part, "", false, isSignal, havePassedCuts, CandPart1, CandPart2, false, total_4mom);
265  //
266  ATH_MSG_DEBUG("");
267  ATH_MSG_DEBUG(" ------------------------------- ");
268  ATH_MSG_DEBUG(" Ended looping on all children ");
269  ATH_MSG_DEBUG(" ------------------------------- ");
270  ATH_MSG_DEBUG("");
271 
272  SignalPassedCuts = (isSignal && havePassedCuts);
273 
274  // ** If signal event is found and InvMass_switch = true, check if the selected
275  // couple of particles has an invariant mass within the range set by the user **
276  if (m_InvMass_switch)
277  {
278  if (SignalPassedCuts)
279  {
280  bool accept_mass = false;
281  bool accept_total_mass = false;
282  ATH_MSG_DEBUG("");
283  ATH_MSG_DEBUG(" *** INVARIANT MASS CUTS ON PARTICLES ACTIVATED! *** ");
284  ATH_MSG_DEBUG("");
285  if (m_InvMass_switch)
286  ATH_MSG_DEBUG(" -- Mass cuts -->> " << m_InvMassMin << " < mass < " << m_InvMassMax << " MeV");
287  //
288  double invMass = (CandPart1 + CandPart2).M();
289  double invMass_total = total_4mom.M();
290  //
291 
292  if (m_InvMass_switch)
293  {
294  ATH_MSG_DEBUG(" -- Invariant mass of the couple of particles = " << invMass << " MeV");
296  {
297  ATH_MSG_DEBUG(" ==>> Event has passed the mass filter!");
298  ATH_MSG_DEBUG("");
299  accept_mass = true;
300  }
301  else
302  {
303  ATH_MSG_DEBUG(" ==>> Event has NOT passed the mass filter!");
304  ATH_MSG_DEBUG("");
305  }
306  SignalPassedCuts = SignalPassedCuts && accept_mass;
307  }
309  {
310  ATH_MSG_DEBUG(" -- Total invariant mass of the final-state particles = " << invMass_total << " MeV");
311  if (m_TotalInvMassMin < invMass_total && invMass_total < m_TotalInvMassMax)
312  {
313  ATH_MSG_DEBUG(" ==>> Event has passed the total mass filter!");
314  ATH_MSG_DEBUG("");
315  accept_total_mass = true;
316  }
317  else
318  {
319  ATH_MSG_DEBUG(" ==>> Event has NOT passed the total mass filter!");
320  ATH_MSG_DEBUG("");
321  }
322  SignalPassedCuts = SignalPassedCuts && accept_total_mass;
323  }
324  }
325  else
326  {
327  ATH_MSG_DEBUG("");
328  ATH_MSG_DEBUG(" *** INVARIANT MASS CUTS ON PARTICLES NOT APPLIED (since the event is not a signal that passed cuts)! *** ");
329  ATH_MSG_DEBUG("");
330  }
331  }
332  else
333  {
334  ATH_MSG_DEBUG(" *** INVARIANT MASS CUTS ON PARTICLES NOT ACTIVATED *** ");
335  ATH_MSG_DEBUG("");
336  }
337  }
338  else
339  {
340  SignalPassedCuts = true;
341  //
342  ATH_MSG_DEBUG(" *** KINEMATIC CUTS ON PARTICLES NOT ACTIVATED ==>> ACCEPT ALL EVENTS! *** ");
343  ATH_MSG_DEBUG("");
344  }
345  } // End newBChain
346  if (SignalPassedCuts)
347  break; // We have found the signal, we do not need to look for other particles
348  } // End particle iteration
349 
350  if (SignalPassedCuts)
351  {
352  ATH_MSG_DEBUG(" -->> All signal children have passed cuts on particles!");
353  }
354  else
355  {
356  ATH_MSG_DEBUG(" -->> Signal children have NOT passed cuts on particles!");
357  }
358  } // end of LVL1/LVL2 selection
359  else
360  {
361  ATH_MSG_DEBUG("");
362  ATH_MSG_DEBUG(" -->> Event has NOT passed the trigger!");
363  }
364  // ** Reject event if it has not passed triggers **
365  // --> If not requested by user these flags will be set
366  // to true so there will be no erroneous rejection
367  if ((!LVL1Passed) || (!LVL2Passed))
368  {
370  acceptEvent = false;
371  }
372 
373  // ** Check if all conditions are true **
374  // --> Accept the event if acceptEvent is true and the event is a signal event
375  acceptEvent = acceptEvent && SignalPassedCuts;
376 
377  // ** Print whether the event has passed or not **
378  //
379  ATH_MSG_DEBUG("");
380  if (!acceptEvent)
381  {
382  setFilterPassed(false);
383  m_rejectedAll++;
384  ATH_MSG_DEBUG(" ==========================");
385  ATH_MSG_DEBUG(" Event REJECTED by Filter ");
386  ATH_MSG_DEBUG(" ==========================");
387  }
388  else
389  {
390  setFilterPassed(true);
391  ATH_MSG_DEBUG(" ==========================");
392  ATH_MSG_DEBUG(" Event ACCEPTED by Filter ");
393  ATH_MSG_DEBUG(" ==========================");
394  }
395  ATH_MSG_DEBUG("");
396 
397  // End of execution for each event
398  return StatusCode::SUCCESS;
399 }
400 
401 bool xAODBSignalFilter::test_cuts(const double myPT, const double testPT, const double myEta, const double testEta) const
402 {
403  return ((myPT >= testPT) && (std::abs(myEta) <= testEta));
404 }
405 
407 {
408  bool accept = false;
409  int pID = child->pdgId();
410  double myPT = child->pt();
411  double myEta = child->eta();
412 
413  if ((std::abs(pID) == 13) && m_localLVL1MuonCutOn)
415 
416  return accept;
417 }
418 
420 {
421  bool accept = false;
422  int pID = child->pdgId();
423  double myPT = child->pt();
424  double myEta = child->eta();
425 
426  if ((std::abs(pID) == 11) && m_localLVL2ElectronCutOn)
428  if ((std::abs(pID) == 13) && m_localLVL2MuonCutOn)
430 
431  return accept;
432 }
433 
434 void xAODBSignalFilter::FindAllChildren(const xAOD::TruthParticle* mother, std::string treeIDStr,
435  bool fromFinalB, bool &foundSignal, bool &passedAllCuts,
436  TLorentzVector &p1, TLorentzVector &p2, bool fromSelectedB, TLorentzVector &total_4mom) const
437 {
438  int pID = mother->pdgId();
439  //
440  if (!(mother->decayVtx()) && MC::isStable(mother)) // i.e. this is a final state
441  {
442  bool hasChildGoodParent = fromFinalB && (fromSelectedB || m_B_pdgid == 0);
443  //
444  if (fromFinalB && hasChildGoodParent)
445  {
446  foundSignal = true;
447  bool passedCut = FinalStatePassedCuts(mother); // X = X && ... in case of multiple particles (e.g. KK)
448  if (m_cuts_f_e_on && std::abs(pID) == 11)
449  passedAllCuts = passedAllCuts && passedCut;
450  if (m_cuts_f_mu_on && std::abs(pID) == 13)
451  passedAllCuts = passedAllCuts && passedCut;
452  if (m_cuts_f_had_on && MC::isHadron(pID) && MC::isCharged(pID))
453  passedAllCuts = passedAllCuts && passedCut;
454  if (m_cuts_f_gam_on && std::abs(pID) == 22)
455  passedAllCuts = passedAllCuts && passedCut;
456  if (m_cuts_f_K0_on && std::abs(pID) == 311)
457  passedAllCuts = passedAllCuts && passedCut;
458  //
460  {
461  if (m_InvMass_PartFakeMass1 < 0.)
462  p1.SetPxPyPzE(mother->px(), mother->py(), mother->pz(), mother->e());
463  else
464  p1.SetXYZM(mother->px(), mother->py(), mother->pz(), m_InvMass_PartFakeMass1);
465  total_4mom = total_4mom + p1;
466  }
468  {
469  if (m_InvMass_PartFakeMass2 < 0.)
470  p2.SetPxPyPzE(mother->px(), mother->py(), mother->pz(), mother->e());
471  else
472  p2.SetXYZM(mother->px(), mother->py(), mother->pz(), m_InvMass_PartFakeMass2);
473  total_4mom = total_4mom + p2;
474  }
475  else if (m_TotalInvMass_switch)
476  {
477  TLorentzVector current_4p;
478  current_4p.SetPxPyPzE(mother->px(), mother->py(), mother->pz(), mother->e());
479  total_4mom = total_4mom + current_4p;
480  }
481  }
482  return;
483  }
484  else
485  {
486  if (!(mother->decayVtx())) // i.e. something is wrong in HepMC
487  {
488  if (MC::isDecayed(mother))
489  ATH_MSG_DEBUG(" Inconsistent entry in HepMC (status 2 particle not decayed), chain rejected!");
490  return;
491  }
492  }
493 
494  int childCnt = 0;
495  std::string childIDStr;
496  if (!(treeIDStr == ""))
497  treeIDStr = treeIDStr + ".";
498 
499  // ** Find out whether particle is child of final (non-excited) B, used for cuts **
500  if ((!fromFinalB) && (MC::isBottomMeson(pID) || MC::isBottomBaryon(pID)))
501  {
502  fromFinalB = true;
503  int pID;
504  for(size_t thisChild_id=0; thisChild_id < mother->decayVtx()->nOutgoingParticles(); thisChild_id++)
505  {
506  auto child = mother->decayVtx()->outgoingParticle(thisChild_id);
507  pID = child->pdgId();
508  if (MC::isBottomMeson(pID) || MC::isBottomBaryon(pID))
509  fromFinalB = false;
510  }
511  }
512 
513  // ** Main loop: iterate over all children, call method recursively.
514  for(size_t thisChild_id=0; thisChild_id < mother->decayVtx()->nOutgoingParticles(); thisChild_id++)
515  {
516  auto child = mother->decayVtx()->outgoingParticle(thisChild_id);
517  childCnt++;
518  std::stringstream childCntSS;
519  childCntSS << childCnt;
520  childIDStr = treeIDStr + childCntSS.str();
521  PrintChild(child, childIDStr, fromFinalB);
522  FindAllChildren(child, childIDStr, fromFinalB, foundSignal, passedAllCuts, p1, p2, (pID == m_B_pdgid) || fromSelectedB, total_4mom);
523  }
524 
525  return;
526 }
527 
529 {
530  bool accept = true;
531 
532  // ** Look if children has passed the cuts **
533  //
534  int pID = child->pdgId();
535  double myPT = child->pt();
536  double myEta = child->eta();
537 
538  ATH_MSG_DEBUG("");
539  ATH_MSG_DEBUG(" ** Found a child with: ");
540  ATH_MSG_DEBUG(" - id = " << pID);
541  ATH_MSG_DEBUG(" - pT = " << myPT << " MeV");
542  ATH_MSG_DEBUG(" - eta = " << myEta);
543  ATH_MSG_DEBUG("");
544 
545  if (m_cuts_f_e_on)
546  {
547  if (std::abs(pID) == 11)
548  {
549  ATH_MSG_DEBUG(" ** ( pT , eta ) cuts applied on the electron --> ( " << m_cuts_f_e_pT
550  << " , " << m_cuts_f_e_eta << " )");
551  if (test_cuts(myPT, m_cuts_f_e_pT, myEta, m_cuts_f_e_eta))
552  {
553  ATH_MSG_DEBUG(" ==>> Found an electron which passed the pT and eta cuts!");
554  ATH_MSG_DEBUG(" - Electron: pT = " << myPT << " MeV");
555  ATH_MSG_DEBUG(" - Electron: eta = " << myEta);
556  ATH_MSG_DEBUG("");
557  ATH_MSG_DEBUG(" ==>> Accepted the electron!");
558  ATH_MSG_DEBUG("");
559  }
560  else
561  {
562  accept = false;
563  ATH_MSG_DEBUG(" ==>> The electron has NOT passed the pT and eta cuts!");
564  ATH_MSG_DEBUG("");
565  }
566  }
567  }
568  if (m_cuts_f_mu_on)
569  {
570  if (std::abs(pID) == 13)
571  {
572  ATH_MSG_DEBUG(" ** ( pT , eta ) cuts applied on the muon --> ( " << m_cuts_f_mu_pT
573  << " , " << m_cuts_f_mu_eta << " )");
574  if (test_cuts(myPT, m_cuts_f_mu_pT, myEta, m_cuts_f_mu_eta))
575  {
576  ATH_MSG_DEBUG(" ==>> Found a muon which passed the pT and eta cuts!");
577  ATH_MSG_DEBUG(" - Muon: pT = " << myPT << " MeV");
578  ATH_MSG_DEBUG(" - Muon: eta = " << myEta);
579  ATH_MSG_DEBUG("");
580  ATH_MSG_DEBUG(" ==>> Accepted the muon!");
581  ATH_MSG_DEBUG("");
582  }
583  else
584  {
585  accept = false;
586  ATH_MSG_DEBUG(" ==>> The muon has NOT passed the pT and eta cuts!");
587  ATH_MSG_DEBUG("");
588  }
589  }
590  }
591  if (m_cuts_f_had_on)
592  {
593  if (MC::isHadron(pID) && MC::isCharged(pID))
594  {
595  ATH_MSG_DEBUG(" ** ( pT , eta ) cuts applied on the charged hadron --> ( " << m_cuts_f_had_pT
596  << " , " << m_cuts_f_had_eta << " )");
597  if (test_cuts(myPT, m_cuts_f_had_pT, myEta, m_cuts_f_had_eta))
598  {
599  ATH_MSG_DEBUG(" ==>> Found a charged hadron which passed the pT and eta cuts!");
600  ATH_MSG_DEBUG(" - Charged hadron: pT = " << myPT << " MeV");
601  ATH_MSG_DEBUG(" - Charged hadron: eta = " << myEta);
602  ATH_MSG_DEBUG("");
603  ATH_MSG_DEBUG(" ==>> Accepted the charged hadron!");
604  ATH_MSG_DEBUG("");
605  }
606  else
607  {
608  accept = false;
609  ATH_MSG_DEBUG(" ==>> The charged hadron has NOT passed the pT and eta cuts!");
610  ATH_MSG_DEBUG("");
611  }
612  }
613  }
614  if (m_cuts_f_gam_on)
615  {
616  if (std::abs(pID) == 22)
617  {
618  ATH_MSG_DEBUG(" ** ( pT , eta ) cuts applied on the gamma --> ( " << m_cuts_f_gam_pT
619  << " , " << m_cuts_f_gam_eta << " )");
620  if (test_cuts(myPT, m_cuts_f_gam_pT, myEta, m_cuts_f_gam_eta))
621  {
622  ATH_MSG_DEBUG(" ==>> Found a gamma which passed the pT and eta cuts!");
623  ATH_MSG_DEBUG(" - Gamma: pT = " << myPT << " MeV");
624  ATH_MSG_DEBUG(" - Gamma: eta = " << myEta);
625  ATH_MSG_DEBUG("");
626  ATH_MSG_DEBUG(" ==>> Accepted the gamma!");
627  ATH_MSG_DEBUG("");
628  }
629  else
630  {
631  accept = false;
632  ATH_MSG_DEBUG(" ==>> The gamma has NOT passed the pT and eta cuts!");
633  ATH_MSG_DEBUG("");
634  }
635  }
636  }
637  if (m_cuts_f_K0_on)
638  {
639  if (std::abs(pID) == 311)
640  {
641  ATH_MSG_DEBUG(" ** ( pT , eta ) cuts applied on the K0 --> ( " << m_cuts_f_K0_pT
642  << " , " << m_cuts_f_K0_eta << " )");
643  if (test_cuts(myPT, m_cuts_f_K0_pT, myEta, m_cuts_f_K0_eta))
644  {
645  ATH_MSG_DEBUG(" ==>> Found a K0 which passed the pT and eta cuts!");
646  ATH_MSG_DEBUG(" - K0: pT = " << myPT << " MeV");
647  ATH_MSG_DEBUG(" - K0: eta = " << myEta);
648  ATH_MSG_DEBUG("");
649  ATH_MSG_DEBUG(" ==>> Accepted the K0!");
650  ATH_MSG_DEBUG("");
651  }
652  else
653  {
654  accept = false;
655  ATH_MSG_DEBUG(" ==>> The K0 has NOT passed the pT and eta cuts!");
656  ATH_MSG_DEBUG("");
657  }
658  }
659  }
660 
661  return accept;
662 }
663 
665  const std::string &treeIDStr, const bool fromFinalB) const
666 {
667  int pID = child->pdgId();
668  // ** Find name **
669  const HepPDT::ParticleData *pData = particleData(std::abs(pID));
670  std::string pName = "unknown particle";
671  if (pData)
672  {
673  pName = pData->name();
674  if (pID < 0)
675  pName = "anti - " + pName;
676  }
677  ATH_MSG_DEBUG(" " << treeIDStr << " "
678  << "Child (" << pName
679  << ") " << child << " , from final B = " << fromFinalB);
680 
681  return;
682 }
683 
685 {
686  double total = m_EventCnt;
687  ATH_MSG_ALWAYS(" I===============================================================================================");
688  ATH_MSG_ALWAYS(" I xAODBSignalFilter Summary Report ");
689  ATH_MSG_ALWAYS(" I===============================================================================================");
691  {
692  ATH_MSG_ALWAYS(" I LVL1 muon trigger report:");
693  ATH_MSG_ALWAYS(" I Muon pT cut " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
694  << m_localLVL1MuonCutPT << " MeV ");
695  ATH_MSG_ALWAYS(" I Muon pseudo-rapidity cut" << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
697  ATH_MSG_ALWAYS(" I No of events containing at least " << '\t' << '\t' << '\t' << '\t' << '\t' << "I");
698  ATH_MSG_ALWAYS(" I one particle satisfying these cuts " << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
699  << m_LVL1Counter);
701  {
702  ATH_MSG_ALWAYS(" I LVL2 muon trigger report:");
703  ATH_MSG_ALWAYS(" I Muon pT cut " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
704  << m_localLVL2MuonCutPT << " MeV ");
705  ATH_MSG_ALWAYS(" I Muon pseudo-rapidity cut " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
707  }
709  {
710  ATH_MSG_ALWAYS(" I LVL2 electron trigger report:");
711  ATH_MSG_ALWAYS(" I Electron pT cut " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << " I" << '\t' << m_localLVL2ElectronCutPT << " MeV ");
712  ATH_MSG_ALWAYS(" I Electron pseudo-rapidity cut " << '\t' << '\t' << '\t' << '\t' << '\t' << "I"
713  << '\t' << m_localLVL2ElectronCutEta);
714  }
716  {
717  ATH_MSG_ALWAYS(" I No of events containing at least one muon satisfying LVL1 cut" << '\t' << "I");
718  ATH_MSG_ALWAYS(" I and at least one separate particle passing these LVL2 cuts " << '\t' << '\t' << "I" << '\t'
719  << m_LVL2Counter);
720  }
721  }
722  ATH_MSG_ALWAYS(" I Total no of input events " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
723  << total);
724  ATH_MSG_ALWAYS(" I No of events rejected by trigger " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
725  << m_rejectedTrigger);
726  ATH_MSG_ALWAYS(" I No of events rejected in total " << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << '\t' << "I" << '\t'
727  << m_rejectedAll);
729  ATH_MSG_ALWAYS(" I To obtain correct cross section, multiply BX in PythiaB report by " << '\t' << '\t' << "I" << '\t'
730  << m_LVL1Counter / total);
732  ATH_MSG_ALWAYS(" I To obtain correct cross section, multiply BX in PythiaB report by " << '\t' << '\t' << "I" << '\t'
733  << m_LVL2Counter / total);
735  ATH_MSG_ALWAYS(" I No trigger requests made");
736  //
737  ATH_MSG_ALWAYS(" I=========================================== End of report =====================================");
738 
739  return StatusCode::SUCCESS;
740 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAODBSignalFilter::test_cuts
bool test_cuts(const double myPT, const double testPT, const double myEta, const double testEta) const
Definition: xAODBSignalFilter.cxx:401
xAODBSignalFilter::m_localLVL2MuonCutPT
double m_localLVL2MuonCutPT
Definition: xAODBSignalFilter.h:56
isBottomMeson
bool isBottomMeson(const T &p)
Definition: AtlasPID.h:473
xAODBSignalFilter::m_InvMass_PartFakeMass1
double m_InvMass_PartFakeMass1
Definition: xAODBSignalFilter.h:65
P4Helpers::invMass
double invMass(const I4Momentum &pA, const I4Momentum &pB)
invariant mass from two I4momentum references
Definition: P4Helpers.h:239
isBottomBaryon
bool isBottomBaryon(const T &p)
Definition: AtlasPID.h:489
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAODBSignalFilter::m_cuts_f_had_on
bool m_cuts_f_had_on
Definition: xAODBSignalFilter.h:47
xAOD::TruthParticle_v1::pz
float pz() const
The z component of the particle's momentum.
xAODBSignalFilter::m_cuts_f_gam_on
bool m_cuts_f_gam_on
Definition: xAODBSignalFilter.h:48
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
xAODBSignalFilter::m_TotalInvMassMax
double m_TotalInvMassMax
Definition: xAODBSignalFilter.h:67
CutsMETMaker::accept
StatusCode accept(const xAOD::Muon *mu)
Definition: CutsMETMaker.cxx:18
xAODBSignalFilter::filterFinalize
virtual StatusCode filterFinalize()
Definition: xAODBSignalFilter.cxx:684
xAOD::TruthParticle_v1::px
float px() const
The x component of the particle's momentum.
xAODBSignalFilter::LVL1_Mu_Trigger
bool LVL1_Mu_Trigger(const xAOD::TruthParticle *child) const
Definition: xAODBSignalFilter.cxx:406
xAODBSignalFilter::m_cuts_f_mu_eta
double m_cuts_f_mu_eta
Definition: xAODBSignalFilter.h:54
xAOD::TruthParticle_v1::py
float py() const
The y component of the particle's momentum.
xAODBSignalFilter::m_localLVL1MuonCutOn
bool m_localLVL1MuonCutOn
Definition: xAODBSignalFilter.h:49
xAODBSignalFilter::m_cuts_f_e_pT
double m_cuts_f_e_pT
Definition: xAODBSignalFilter.h:52
xAODBSignalFilter::m_localLVL1MuonCutPT
double m_localLVL1MuonCutPT
Definition: xAODBSignalFilter.h:56
xAODBSignalFilter::m_rejectedAll
double m_rejectedAll
Definition: xAODBSignalFilter.h:62
xAODBSignalFilter::m_TotalInvMass_switch
bool m_TotalInvMass_switch
Definition: xAODBSignalFilter.h:51
xAODBSignalFilter::m_LVL1Counter
double m_LVL1Counter
Definition: xAODBSignalFilter.h:59
xAODBSignalFilter::m_InvMassMin
double m_InvMassMin
Definition: xAODBSignalFilter.h:66
xAODBSignalFilter::FindAllChildren
void FindAllChildren(const xAOD::TruthParticle *mother, std::string treeIDStr, bool fromFinalB, bool &foundSignal, bool &passedAllCuts, TLorentzVector &p1, TLorentzVector &p2, bool fromSelectedB, TLorentzVector &total_4mom) const
Definition: xAODBSignalFilter.cxx:434
MC::isPhysical
bool isPhysical(const T &p)
Definition: HepMCHelpers.h:32
xAODBSignalFilter::m_cuts_f_e_eta
double m_cuts_f_e_eta
Definition: xAODBSignalFilter.h:54
AthCommonDataStore< AthCommonMsg< Algorithm > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
xAODBSignalFilter::m_cuts_f_gam_pT
double m_cuts_f_gam_pT
Definition: xAODBSignalFilter.h:53
xAODBSignalFilter::m_cuts_f_e_on
bool m_cuts_f_e_on
Definition: xAODBSignalFilter.h:47
xAODBSignalFilter::m_InvMass_switch
bool m_InvMass_switch
Definition: xAODBSignalFilter.h:51
GenFilter
Base class for event generator filtering modules.
Definition: GenFilter.h:30
xAODBSignalFilter::FinalStatePassedCuts
bool FinalStatePassedCuts(const xAOD::TruthParticle *child) const
Definition: xAODBSignalFilter.cxx:528
HepMC::EVTGENUNDECAYEDSTATUS
constexpr int EVTGENUNDECAYEDSTATUS
Definition: MagicNumbers.h:42
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::TruthParticle_v1::e
virtual double e() const override final
The total energy of the particle.
xAODBSignalFilter.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:41
xAODBSignalFilter::m_cuts_f_had_eta
double m_cuts_f_had_eta
Definition: xAODBSignalFilter.h:54
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_MSG_ALWAYS
#define ATH_MSG_ALWAYS(x)
Definition: AthMsgStreamMacros.h:35
xAODBSignalFilter::m_cuts_f_mu_pT
double m_cuts_f_mu_pT
Definition: xAODBSignalFilter.h:52
xAODBSignalFilter::m_cuts_f_K0_eta
double m_cuts_f_K0_eta
Definition: xAODBSignalFilter.h:55
xAODBSignalFilter::m_localLVL1MuonCutEta
double m_localLVL1MuonCutEta
Definition: xAODBSignalFilter.h:56
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
xAODBSignalFilter::m_EventCnt
int m_EventCnt
Definition: xAODBSignalFilter.h:69
xAODBSignalFilter::m_InvMassMax
double m_InvMassMax
Definition: xAODBSignalFilter.h:66
xAODBSignalFilter::m_InvMass_PartId1
int m_InvMass_PartId1
Definition: xAODBSignalFilter.h:64
xAODBSignalFilter::m_localLVL2MuonCutEta
double m_localLVL2MuonCutEta
Definition: xAODBSignalFilter.h:57
xAOD::TruthParticle_v1::decayVtx
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
xAODBSignalFilter::m_TotalInvMassMin
double m_TotalInvMassMin
Definition: xAODBSignalFilter.h:67
xAODBSignalFilter::m_InvMass_PartFakeMass2
double m_InvMass_PartFakeMass2
Definition: xAODBSignalFilter.h:65
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MagicNumbers.h
isHadron
bool isHadron(const T &p)
Definition: AtlasPID.h:207
xAODBSignalFilter::m_localLVL2ElectronCutPT
double m_localLVL2ElectronCutPT
Definition: xAODBSignalFilter.h:57
xAODBSignalFilter::m_localLVL2MuonCutOn
bool m_localLVL2MuonCutOn
Definition: xAODBSignalFilter.h:49
xAODBSignalFilter::filterEvent
virtual StatusCode filterEvent()
Definition: xAODBSignalFilter.cxx:83
xAOD::TruthParticle_v1::eta
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
Definition: TruthParticle_v1.cxx:174
xAODBSignalFilter::m_localLVL2ElectronCutEta
double m_localLVL2ElectronCutEta
Definition: xAODBSignalFilter.h:58
xAODBSignalFilter::xAODBSignalFilter
xAODBSignalFilter(const std::string &name, ISvcLocator *pSvcLocator)
Definition: xAODBSignalFilter.cxx:32
xAODBSignalFilter::PrintChild
void PrintChild(const xAOD::TruthParticle *child, const std::string &treeIDStr, const bool fromFinalB) const
Definition: xAODBSignalFilter.cxx:664
xAODBSignalFilter::m_B_pdgid
int m_B_pdgid
Definition: xAODBSignalFilter.h:63
xAODBSignalFilter::m_cuts_f_mu_on
bool m_cuts_f_mu_on
Definition: xAODBSignalFilter.h:47
MC::isStable
bool isStable(const T &p)
Definition: HepMCHelpers.h:30
xAODBSignalFilter::LVL2_eMu_Trigger
bool LVL2_eMu_Trigger(const xAOD::TruthParticle *child) const
Definition: xAODBSignalFilter.cxx:419
isCharged
bool isCharged(const T &p)
Definition: AtlasPID.h:496
xAODBSignalFilter::m_cuts_f_had_pT
double m_cuts_f_had_pT
Definition: xAODBSignalFilter.h:52
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MC::isDecayed
bool isDecayed(const T &p)
Definition: HepMCHelpers.h:29
xAOD::TruthParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TruthParticle_v1.cxx:166
xAODBSignalFilter::m_cuts_f_K0_on
bool m_cuts_f_K0_on
Definition: xAODBSignalFilter.h:48
xAODBSignalFilter::m_localLVL2ElectronCutOn
bool m_localLVL2ElectronCutOn
Definition: xAODBSignalFilter.h:50
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
GenBase::particleData
const HepPDT::ParticleData * particleData(int pid) const
Access an element in the particle data table.
Definition: GenBase.h:126
xAODBSignalFilter::m_InvMass_PartId2
int m_InvMass_PartId2
Definition: xAODBSignalFilter.h:64
xAODBSignalFilter::m_cuts_f_K0_pT
double m_cuts_f_K0_pT
Definition: xAODBSignalFilter.h:53
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
xAOD::TruthVertex_v1::outgoingParticle
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
Definition: TruthVertex_v1.cxx:121
xAODBSignalFilter::m_cuts_f_gam_eta
double m_cuts_f_gam_eta
Definition: xAODBSignalFilter.h:55
HepMCHelpers.h
xAODBSignalFilter::m_rejectedTrigger
double m_rejectedTrigger
Definition: xAODBSignalFilter.h:61
xAODBSignalFilter::m_LVL2Counter
double m_LVL2Counter
Definition: xAODBSignalFilter.h:60