ATLAS Offline Software
CalcTTZPartonHistory.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
3  */
4 
8 
9 namespace top {
10 
12 
14  xAOD::PartonHistory* ttbarPartonHistory) {
15  ttbarPartonHistory->IniVarZ();
16 
17  TLorentzVector Z;
18  TLorentzVector ZDecay1;
19  TLorentzVector ZDecay2;
20  int ZDecay1_pdgId{};
21  int ZDecay2_pdgId{};
22  bool is_on_shell{};
23  bool event_has_Z = CalcTTZPartonHistory::getZ(truthParticles,
24  &Z,
25  &ZDecay1,
26  &ZDecay1_pdgId,
27  &ZDecay2,
28  &ZDecay2_pdgId,
29  &is_on_shell);
30 
31  if (event_has_Z && !m_ancestry_corrupted) {
32 
33  ttbarPartonHistory->auxdecor< float >("MC_Z_m") = Z.M();
34  ttbarPartonHistory->auxdecor< float >("MC_Z_pt") = Z.Pt();
35  ttbarPartonHistory->auxdecor< float >("MC_Z_eta") = Z.Eta();
36  ttbarPartonHistory->auxdecor< float >("MC_Z_phi") = Z.Phi();
37 
38  ttbarPartonHistory->auxdecor< float >("MC_Zdecay1_m") = ZDecay1.M();
39  ttbarPartonHistory->auxdecor< float >("MC_Zdecay1_pt") = ZDecay1.Pt();
40  ttbarPartonHistory->auxdecor< float >("MC_Zdecay1_eta") = ZDecay1.Eta();
41  ttbarPartonHistory->auxdecor< float >("MC_Zdecay1_phi") = ZDecay1.Phi();
42  ttbarPartonHistory->auxdecor< int >("MC_Zdecay1_pdgId") = ZDecay1_pdgId;
43 
44  ttbarPartonHistory->auxdecor< float >("MC_Zdecay2_m") = ZDecay2.M();
45  ttbarPartonHistory->auxdecor< float >("MC_Zdecay2_pt") = ZDecay2.Pt();
46  ttbarPartonHistory->auxdecor< float >("MC_Zdecay2_eta") = ZDecay2.Eta();
47  ttbarPartonHistory->auxdecor< float >("MC_Zdecay2_phi") = ZDecay2.Phi();
48  ttbarPartonHistory->auxdecor< int >("MC_Zdecay2_pdgId") = ZDecay2_pdgId;
49 
50  ttbarPartonHistory->auxdecor< int >("MC_Z_IsOnShell") = static_cast<int>(is_on_shell);
51  } // if
52 
53  ttbarPartonHistory->auxdecor< int >("MC_Z_AncestryCorrupted") = static_cast<int>(m_ancestry_corrupted);
54  }
55 
57  TLorentzVector* Z_p4,
58  TLorentzVector* ZDecay1,
59  int* ZDecay1_pdgId,
60  TLorentzVector* ZDecay2,
61  int* ZDecay2_pdgId,
62  bool* is_on_shell) {
63  bool hasZ {
64  false
65  };
66  bool hasZDecay1 {
67  false
68  };
69  bool hasZDecay2 {
70  false
71  };
72 
73  *is_on_shell = false;
74  m_ancestry_corrupted = false;
75 
76  // First check for real (on-shell) Z bosons in the truth record
77  // (PDG ID 23). Only consider Z bosons at the end of the chain
78  // of radiative corrections (i.e. a Z boson decaying into
79  // something else than a Z).
80  for (const auto *p : *truthParticles) {
81  if (!p->isZ()) continue;
83 
84  const auto& z = PartonHistoryUtils::findAfterFSR(p);
85  *is_on_shell = true;
86  if (z->nChildren() != 2) continue;
87 
88  *Z_p4 = z->p4();
89  hasZ = true;
90 
91  for (size_t i = 0; i < z->nChildren(); ++i) {
92  const auto& child = z->child(i);
93  if (!child) continue;
94  if (child->pdgId() > 0) {
95  *ZDecay1 = child->p4();
96  *ZDecay1_pdgId = child->pdgId();
97  hasZDecay1 = true;
98  } else {
99  *ZDecay2 = child->p4();
100  *ZDecay2_pdgId = child->pdgId();
101  hasZDecay2 = true;
102  }
103  } // for
104  } // for
105 
106  // Our job is done if the event has a real Z boson.
107  if (hasZ && (!hasZDecay1 || !hasZDecay2)) m_ancestry_corrupted = true;
108  if (hasZ) return hasZ && hasZDecay1 && hasZDecay2;
109 
110  // For off-shell Z bosons it's a bit more tricky. We now look
111  // for two same-flavour particles that are attached to the
112  // ttbar vertex.
113  for (const auto *p : *truthParticles) {
114  if (abs(p->pdgId()) > 19) continue; // Only elementary fermions
115  if (p->pdgId() < 0) continue; // No anti-particles (to avoid
116  // double-counting)
117  const auto& sibling = getFlavourSibling(p);
118  if (!sibling) continue;
119 
120  // Check whether the particle is attached to the ttbar vertex.
121  bool has_top_sibling {
122  false
123  };
124  bool has_antitop_sibling {
125  false
126  };
127  const auto& parent = p->parent(0);
128  if (!parent) continue;
129  for (size_t i = 0; i < parent->nChildren(); ++i) {
130  const auto* child = parent->child(i);
131  if (!child) continue;
132  if (child == p) continue; // Make sure we don't look at our candidate.
133  if (child->pdgId() == 6) has_top_sibling = true;
134  if (child->pdgId() == -6) has_antitop_sibling = true;
135  if (has_top_sibling && has_antitop_sibling) break;
136  }
137  if (!(has_top_sibling && has_antitop_sibling)) continue;
138 
139  *ZDecay1 = p->p4();
140  *ZDecay1_pdgId = p->pdgId();
141  hasZDecay1 = true;
142  *ZDecay2 = sibling->p4();
143  *ZDecay2_pdgId = sibling->pdgId();
144  hasZDecay2 = true;
145 
146  *Z_p4 = *ZDecay1 + *ZDecay2;
147  hasZ = true;
148  } // for
149 
150  if (hasZ && (!hasZDecay1 || !hasZDecay2)) m_ancestry_corrupted = true;
151  return hasZ && hasZDecay1 && hasZDecay2;
152  }
153 
155  const auto& parent = particle->parent(0);
156 
157  if (!parent) return nullptr;
158 
159  for (size_t i = 0; i < parent->nChildren(); ++i) {
160  const auto& sibling_candidate = parent->child(i);
161  if (!sibling_candidate) continue;
162  if (sibling_candidate->pdgId() == -particle->pdgId()) {
163  return sibling_candidate;
164  }
165  }
166  return nullptr;
167  }
168 
170  // Get the Truth Particles
171  const xAOD::TruthParticleContainer* truthParticles(nullptr);
172 
173  if(m_config->getDerivationStream() == "PHYS") //in DAOD_PHYS we don't have the truth particles container
174  {
175  // To obtain both tops and the Z boson, we need the collections for both
176  std::vector<std::string> collections = {"TruthTop", "TruthBosonsWithDecayParticles", "HardScatterParticles"};
177  ATH_CHECK(buildContainerFromMultipleCollections(collections,"AT_TTZPartonHistory_TruthParticles"));
178  ATH_CHECK(evtStore()->retrieve(truthParticles, "AT_TTZPartonHistory_TruthParticles"));
179 
180  //we need to be able to navigate from the Ws to their decayProducts, see CalcTopPartonHistory.h for details
182  }
183  else //otherwise we retrieve the container as usual
184  {
185  ATH_CHECK(evtStore()->retrieve(truthParticles, m_config->sgKeyMCParticle()));
186  }
187 
188  // Create the partonHistory xAOD object
189  //cppcheck-suppress uninitvar
191  //cppcheck-suppress uninitvar
193  partonCont->setStore(partonAuxCont);
194  //cppcheck-suppress uninitvar
195  xAOD::PartonHistory* ttbarPartonHistory = new xAOD::PartonHistory {};
196  partonCont->push_back(ttbarPartonHistory);
197 
198  // Recover the parton history for ttbar events
199  ttbarHistorySaver(truthParticles, ttbarPartonHistory);
200  zHistorySaver(truthParticles, ttbarPartonHistory);
201 
202  // Save to StoreGate / TStore
203  std::string outputSGKey = m_config->sgKeyTopPartonHistory();
204  std::string outputSGKeyAux = outputSGKey + "Aux.";
205 
206  StatusCode save = evtStore()->tds()->record(partonCont, outputSGKey);
207  StatusCode saveAux = evtStore()->tds()->record(partonAuxCont, outputSGKeyAux);
208  if (!save || !saveAux) {
209  return StatusCode::FAILURE;
210  }
211 
212  return StatusCode::SUCCESS;
213  }
214 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::PartonHistory
Interface class.
Definition: PartonHistory.h:48
top::CalcTopPartonHistory::buildContainerFromMultipleCollections
StatusCode buildContainerFromMultipleCollections(const std::vector< std::string > &collections, const std::string &out_contName)
used to build container from multiple collections in DAOD_PHYS we don't have the TruthParticles colle...
Definition: CalcTopPartonHistory.cxx:21
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
top
TopConfig A simple configuration that is NOT a singleton.
Definition: AnalysisTrackingHelper.cxx:58
top::CalcTopPartonHistory::linkBosonCollections
StatusCode linkBosonCollections()
currently in DAOD_PHYS TruthTop have links to Ws from the TruthBoson collection, which have no link t...
Definition: CalcTopPartonHistory.cxx:39
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
top::CalcTTZPartonHistory::getFlavourSibling
const xAOD::TruthParticle * getFlavourSibling(const xAOD::TruthParticle *particle)
Definition: CalcTTZPartonHistory.cxx:154
CalcTTZPartonHistory.h
SG::AuxElement::auxdecor
Decorator< T, ALLOC >::reference_type auxdecor(const std::string &name) const
Fetch an aux decoration, as a non-const reference.
top::CalcTopPartonHistory::m_config
std::shared_ptr< top::TopConfig > m_config
Definition: CalcTopPartonHistory.h:87
xAOD::PartonHistory::IniVarZ
void IniVarZ()
Definition: PartonHistory.cxx:351
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
checkTP.save
def save(self, fileName="./columbo.out")
Definition: checkTP.py:178
top::PartonHistoryUtils::findAfterFSR
const xAOD::TruthParticle * findAfterFSR(const xAOD::TruthParticle *particle)
Return particle after FSR (before the decay vertex)
Definition: PartonHistoryUtils.cxx:8
lumiFormat.i
int i
Definition: lumiFormat.py:92
z
#define z
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:41
PartonHistoryUtils.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
top::CalcTtbarPartonHistory
Definition: CalcTtbarPartonHistory.h:33
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
top::CalcTTZPartonHistory::m_ancestry_corrupted
bool m_ancestry_corrupted
Definition: CalcTTZPartonHistory.h:50
top::CalcTTZPartonHistory::execute
virtual StatusCode execute()
Definition: CalcTTZPartonHistory.cxx:169
top::CalcTTZPartonHistory::CalcTTZPartonHistory
CalcTTZPartonHistory(const std::string &name)
Definition: CalcTTZPartonHistory.cxx:11
top::CalcTTZPartonHistory::zHistorySaver
void zHistorySaver(const xAOD::TruthParticleContainer *truthParticles, xAOD::PartonHistory *ttbarPartonHistory)
Definition: CalcTTZPartonHistory.cxx:13
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
TopConfig.h
xAOD::PartonHistoryAuxContainer
Aux Container.
Definition: PartonHistory.h:41
top::CalcTtbarPartonHistory::ttbarHistorySaver
void ttbarHistorySaver(const xAOD::TruthParticleContainer *truthParticles, xAOD::PartonHistory *ttbarPartonHistory)
Definition: CalcTtbarPartonHistory.cxx:13
top::CalcTTZPartonHistory::getZ
bool getZ(const xAOD::TruthParticleContainer *truthParticles, TLorentzVector *Z, TLorentzVector *ZDecay1, int *ZDecay1_pdgId, TLorentzVector *ZDecay2, int *ZDecay2_pdgId, bool *is_on_shell)
Definition: CalcTTZPartonHistory.cxx:56
top::PartonHistoryUtils::hasParticleIdenticalParent
bool hasParticleIdenticalParent(const xAOD::TruthParticle *particle)
Return true when particle is a top before FSR.
Definition: PartonHistoryUtils.cxx:28