ATLAS Offline Software
ParticleJetLabelCommon.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
8 
9 // private internal functions
10 namespace {
11  // this returns a charm child if it exists, otherwise returns the
12  // particle itself. If the truth record contains broken links return
13  // a nullptr.
14  const xAOD::TruthParticle* getCharmChild(const xAOD::TruthParticle* p) {
15  for (unsigned int n = 0; n < p->nChildren(); n++) {
16  const xAOD::TruthParticle* child = p->child(n);
17  // nullptr would indicate a broken truth record, but the rest of
18  // the code lets this pass silently so we'll do the same here.
19  if (!child) return nullptr;
20  if (MC::hasCharm(child->pdgId())) {
21  return getCharmChild(child);
22  }
23  }
24  return p;
25  }
26 }
27 
28 namespace ParticleJetTools {
29 
30  // the code below is taken from ParticleJetDeltaRLabelTool with
31  // minimal modification
32  // --------------------------------------------------------------
33 
34  inline bool isChild( const xAOD::TruthParticle* p, const xAOD::TruthParticle* c) {
35 
36  if ( HepMC::is_same_particle(p,c) ) { return false; }
37 
38  for (size_t iC = 0; iC < p->nChildren(); iC++) {
39  const xAOD::TruthParticle* cc = p->child(iC);
40  if (!cc) { continue; }
41 
42  if ( HepMC::is_same_particle(cc,c) ) { return true; }
43 
44  if (isChild(cc, c)) { return true; }
45  }
46 
47  return false;
48  }
49 
51  if (!p) return {NAN, NAN, NAN};
52  return {p->x(), p->y(), p->z()};
53  }
55  return {j.px(), j.py(), j.pz()};
56  }
58  if (events.empty()) return {NAN, NAN, NAN};
59  return p3(events.at(0)->signalProcessVertex());
60  }
61 
62 
64  ( const std::vector<const xAOD::TruthParticle*>& parents
65  , std::vector<const xAOD::TruthParticle*>& children
66  ) {
67 
68  if ( &parents == &children ) {
69  // Same vector provided for both inputs. Extra care needed in
70  // this case...
71  const std::vector<const xAOD::TruthParticle*> copyParents = parents;
72  childrenRemoved(copyParents, children);
73  return;
74  }
75  // We can now safely assume that parents will not be modified
76  // during this loop.
77  for ( const xAOD::TruthParticle* p : parents ) {
78  if (!p) continue;
79  children.erase(std::remove_if(children.begin(),
80  children.end(),
81  [p](const xAOD::TruthParticle* c) { return (c && isChild(p, c)); }),
82  children.end());
83  // auto erased = std::erase_if(children, [p](const xAOD::TruthParticle* c) { return (c && isChild(p, c)); }); // C++20
84  }
85  return;
86  }
87 
88 
89  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
90  // End of code copied from ParticleJetDeltaRLabelTool
91 
93  auto chk = [](const std::string& s, const std::string& varname) {
94  if (s.empty()) throw std::runtime_error(
95  "name for '" + varname + "' is not specified in particle jet tools"
96  " configuration");
97  };
98 #define CHECK(var) chk(var, #var)
100  CHECK(doubleint);
101  CHECK(pt);
102  CHECK(Lxy);
103  CHECK(dr);
104  CHECK(pdgId);
107  CHECK(barcode); // FIXME barcode-based
108  CHECK(childLxy);
109  CHECK(childPt);
110  CHECK(childPdgId);
113 #undef CHECK
114  }
115 
117  singleint(n.singleint),
118  doubleint(n.doubleint),
119  pt(n.pt),
120  Lxy(n.Lxy),
121  dr(n.dr),
122  pdgId(n.pdgId),
125  barcode(n.barcode), // FIXME barcode-based
126  childLxy(n.childLxy),
127  childPt(n.childPt),
128  childPdgId(n.childPdgId),
129  childPositionDPhi(n.childPositionDPhi),
130  childPositionDEta(n.childPositionDEta)
131  {
132  }
133 
134 
135  // key might be added back if we figure out how to get the store
136  // gate key from a read handle in analysis base
139  const std::string& linkname):
140  m_dec(linkname)
141  {
142  }
144  const xAOD::Jet& jet,
145  const std::vector<const xAOD::TruthParticle*>& ipv) const
146  {
147  IPLV links;
148  for (const xAOD::TruthParticle* ip: ipv) {
149  // I copied this whole song and dance from setAssociatedObjects
150  // in the jet edm. It would be much easier if we could store the
151  // container hash in this object and use ElementLink(sgkey,
152  // index) but that seems to break in AnalysisBase
153  IPLV::value_type link;
154  const auto* ipc = dynamic_cast<const xAOD::IParticleContainer*>(
155  ip->container());
156  link.toIndexedElement(*ipc, ip->index());
157  links.push_back(link);
158  }
159  m_dec(jet) = links;
160  }
161 
163  const Particles& particles,
164  const LabelDecorators& decs) {
165 
166  // we also want to save information about the maximum pt particle of the labeling partons
167  auto getMaxPtPart = [](const auto& container) -> const xAOD::TruthParticle* {
168  if (container.size() == 0) return nullptr;
169  auto itr = std::max_element(container.begin(), container.end(),
170  [](auto* p1, auto* p2) {
171  return p1->pt() < p2->pt();
172  });
173  return *itr;
174  };
175 
176  // set truth label for jets above pt threshold
177  // hierarchy: b > c > tau > light
178  int label = 0; // default: light
179  const xAOD::TruthParticle* labelling_particle = nullptr;
180  const xAOD::TruthParticle* child_particle = nullptr;
181  if (particles.b.size()) {
182  label = 5;
183  labelling_particle = getMaxPtPart(particles.b);
184  child_particle = getCharmChild(labelling_particle);
185  } else if (particles.c.size()) {
186  label = 4;
187  labelling_particle = getMaxPtPart(particles.c);
188  } else if (particles.tau.size()) {
189  label = 15;
190  labelling_particle = getMaxPtPart(particles.tau);
191  }
192 
193  const Amg::Vector3D& origin = particles.origin;
194 
195  // decorate info about the labelling particle
196  decs.singleint(jet) = label;
197  if (label == 0) {
198  decs.pt(jet) = NAN;
199  decs.Lxy(jet) = NAN;
200  decs.dr(jet) = NAN;
201  decs.pdgId(jet) = 0;
202  decs.positionDPhi(jet) = NAN;
203  decs.positionDEta(jet) = NAN;
204  decs.barcode(jet) = HepMC::INVALID_PARTICLE_BARCODE; // FIXME barcode-based
205  decs.childLxy(jet) = NAN;
206  decs.childPt(jet) = NAN;
207  decs.childPdgId(jet) = 0;
208  decs.childPositionDPhi(jet) = NAN;
209  decs.childPositionDEta(jet) = NAN;
210  } else {
211  decs.pt(jet) = partPt(labelling_particle);
212  decs.Lxy(jet) = partLxy(labelling_particle, origin);
213  decs.dr(jet) = partDR(labelling_particle, jet);
214  decs.pdgId(jet) = partPdgId(labelling_particle);
215  decs.positionDPhi(jet) = positionDPhi(labelling_particle, jet, origin);
216  decs.positionDEta(jet) = positionDEta(labelling_particle, jet, origin);
217  decs.barcode(jet) = labelling_particle ?
218  HepMC::barcode(labelling_particle) : HepMC::INVALID_PARTICLE_BARCODE; // FIXME barcode-based
219  decs.childLxy(jet) = partLxy(child_particle, origin);
220  decs.childPt(jet) = partPt(child_particle);
221  decs.childPdgId(jet) = partPdgId(child_particle);
222  decs.childPositionDPhi(jet) = positionDPhi(child_particle, jet, origin);
223  decs.childPositionDEta(jet) = positionDEta(child_particle, jet, origin);
224  }
225 
226  // extended flavour label
227  int double_label = 0;
228  if (particles.b.size()) {
229  if (particles.b.size() >= 2)
230  double_label = 55;
231 
232  else if (particles.c.size())
233  double_label = 54;
234 
235  else
236  double_label = 5;
237 
238  } else if (particles.c.size()) {
239  if (particles.c.size() >= 2)
240  double_label = 44;
241 
242  else
243  double_label = 4;
244 
245  } else if (particles.tau.size()){
246 
247  bool hasElectrondecay = false;
248  bool hasMuondecay = false;
249  bool hasHadronicdecay = false;
250  for (auto itau: particles.tau){
251  for (size_t i = 0; i< itau->nChildren(); i++){ // tau children loop
252  if (itau->child(i)->absPdgId() == 12 || itau->child(i)->absPdgId() == 14 || itau->child(i)->absPdgId() == 16) continue;
253  if (MC::isMuon(itau->child(i))) hasMuondecay = true;
254  else if (MC::isElectron(itau->child(i))) hasElectrondecay = true;
255  else hasHadronicdecay = true;
256  }
257  }
258 
259  if (particles.tau.size() >= 2){
260  // check if we have at least one hadronic tau
261  if (hasHadronicdecay){
262  // check if we have also tau->mu decay
263  if (hasMuondecay) double_label = 151513;
264  // check if we have also tau->el decay
265  else if (hasElectrondecay) double_label = 151511;
266  // otherwise fully hadronic di-tau decay
267  else double_label = 1515;
268  }
269  } else {
270  // only consider hadronic tau decay
271  if (hasHadronicdecay) double_label = 15;
272  }
273 
274  }
275 
276  decs.doubleint(jet) = double_label;
277 
278  }
279 
281  const Particles& particles,
282  const LabelNames& names) {
284  }
285 
287  if (!part) return NAN;
288  return part->pt();
289  }
290  float partLxy(const xAOD::TruthParticle* part, const Amg::Vector3D& origin) {
291  if (!part) return NAN;
292  if (const auto* vx = part->decayVtx() ) return (p3(vx) - origin).perp();
293  return INFINITY;
294  }
295  float partDR(const xAOD::TruthParticle* part, const xAOD::Jet& jet) {
296  if (!part) return NAN;
297  return part->p4().DeltaR(jet.p4());
298  }
300  if (!part) return 0;
301  return part->pdgId();
302  }
304  const xAOD::Jet& jet,
305  const Amg::Vector3D& origin) {
306  if (!part) return NAN;
307  if (const auto* vx = part->decayVtx() ) {
308  Amg::Vector3D displacement = p3(vx) - origin;
309  return p3(jet).deltaPhi(displacement);
310  }
311  return INFINITY;
312  }
314  const xAOD::Jet& jet,
315  const Amg::Vector3D& origin) {
316  if (!part) return NAN;
317  if (const auto* vx = part->decayVtx() ) {
318  Amg::Vector3D displacement = p3(vx) - origin;
319  return displacement.eta() - jet.eta();
320  }
321  return INFINITY;
322  }
323 
324 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
ParticleJetTools::LabelNames::dr
std::string dr
Definition: ParticleJetLabelCommon.h:27
ParticleJetTools::LabelNames::Lxy
std::string Lxy
Definition: ParticleJetLabelCommon.h:26
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
ParticleJetTools::isChild
bool isChild(const xAOD::TruthParticle *p, const xAOD::TruthParticle *c)
Definition: ParticleJetLabelCommon.cxx:34
ParticleJetTools::LabelDecorators::childLxy
SG::AuxElement::Decorator< float > childLxy
Definition: ParticleJetLabelCommon.h:51
ParticleJetTools::LabelNames::pdgId
std::string pdgId
Definition: ParticleJetLabelCommon.h:28
hasCharm
bool hasCharm(const T &p)
Definition: AtlasPID.h:501
ParticleJetTools::LabelDecorators::LabelDecorators
LabelDecorators(const LabelNames &)
Definition: ParticleJetLabelCommon.cxx:116
python.DecayParser.parents
parents
print ("==> buf:",buf)
Definition: DecayParser.py:31
PlotCalibFromCool.label
label
Definition: PlotCalibFromCool.py:78
CHECK
#define CHECK(var)
ParticleJetTools::LabelNames::childPositionDEta
std::string childPositionDEta
Definition: ParticleJetLabelCommon.h:36
TRTCalib_cfilter.p1
p1
Definition: TRTCalib_cfilter.py:130
test_pyathena.pt
pt
Definition: test_pyathena.py:11
ParticleJetTools::partDR
float partDR(const xAOD::TruthParticle *part, const xAOD::Jet &jet)
Definition: ParticleJetLabelCommon.cxx:295
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:112
ParticleJetTools::LabelNames::childLxy
std::string childLxy
Definition: ParticleJetLabelCommon.h:32
ParticleJetTools::LabelDecorators::barcode
SG::AuxElement::Decorator< int > barcode
Definition: ParticleJetLabelCommon.h:50
ParticleJetTools::LabelNames::check
void check()
Definition: ParticleJetLabelCommon.cxx:92
SG::ReadHandleKey< xAOD::TruthParticleContainer >
HepMC::INVALID_PARTICLE_BARCODE
constexpr int INVALID_PARTICLE_BARCODE
Definition: MagicNumbers.h:53
ParticleJetTools::LabelNames::childPt
std::string childPt
Definition: ParticleJetLabelCommon.h:33
HepMC::is_same_particle
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
Definition: MagicNumbers.h:354
python.DataFormatRates.events
events
Definition: DataFormatRates.py:105
ParticleJetTools::positionDEta
float positionDEta(const xAOD::TruthParticle *part, const xAOD::Jet &jet, const Amg::Vector3D &origin)
Definition: ParticleJetLabelCommon.cxx:313
ParticleJetTools::LabelDecorators::Lxy
SG::AuxElement::Decorator< float > Lxy
Definition: ParticleJetLabelCommon.h:45
ParticleJetLabelCommon.h
ParticleJetTools::p3
Amg::Vector3D p3(const xAOD::TruthVertex *p)
Definition: ParticleJetLabelCommon.cxx:50
ParticleJetTools::LabelDecorators::doubleint
SG::AuxElement::Decorator< int > doubleint
Definition: ParticleJetLabelCommon.h:43
ParticleJetTools::IParticleLinker::m_dec
SG::AuxElement::Decorator< IPLV > m_dec
Definition: ParticleJetLabelCommon.h:66
TRTCalib_cfilter.p2
p2
Definition: TRTCalib_cfilter.py:131
xAOD::Jet_v1::pz
float pz() const
The z-component of the jet's momentum.
Definition: Jet_v1.cxx:99
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:731
DMTest::links
links
Definition: CLinks_v1.cxx:22
python.subdetectors.mmg.names
names
Definition: mmg.py:8
xAOD::EgammaHelpers::isElectron
bool isElectron(const xAOD::Egamma *eg)
is the object an electron (not Fwd)
Definition: EgammaxAODHelpers.cxx:12
HepMC::barcode
int barcode(const T *p)
Definition: Barcode.h:16
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
ParticleJetTools::LabelNames::doubleint
std::string doubleint
Definition: ParticleJetLabelCommon.h:24
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
ParticleJetTools::Particles
Definition: ParticleJetLabelCommon.h:69
xAOD::Jet_v1::py
float py() const
The y-component of the jet's momentum.
Definition: Jet_v1.cxx:94
ParticleJetTools::childrenRemoved
void childrenRemoved(const std::vector< const xAOD::TruthParticle * > &parents, std::vector< const xAOD::TruthParticle * > &children)
Definition: ParticleJetLabelCommon.cxx:64
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
ParticleJetTools::LabelDecorators::pt
SG::AuxElement::Decorator< float > pt
Definition: ParticleJetLabelCommon.h:44
ParticleJetTools::LabelNames::singleint
std::string singleint
Definition: ParticleJetLabelCommon.h:23
ParticleJetTools::partPt
float partPt(const xAOD::TruthParticle *part)
Definition: ParticleJetLabelCommon.cxx:286
xAOD::TruthVertex_v1
Class describing a truth vertex in the MC record.
Definition: TruthVertex_v1.h:37
ParticleJetTools::LabelDecorators::pdgId
SG::AuxElement::Decorator< int > pdgId
Definition: ParticleJetLabelCommon.h:47
ParticleJetTools::LabelDecorators::childPdgId
SG::AuxElement::Decorator< int > childPdgId
Definition: ParticleJetLabelCommon.h:53
ParticleJetTools::LabelNames::childPositionDPhi
std::string childPositionDPhi
Definition: ParticleJetLabelCommon.h:35
ParticleJetTools::IParticleLinker::IParticleLinker
IParticleLinker(const SG::ReadHandleKey< xAOD::TruthParticleContainer > &, const std::string &linkName)
Definition: ParticleJetLabelCommon.cxx:137
ParticleJetTools
Definition: ParticleJetLabelCommon.h:20
xAOD::Jet_v1::px
float px() const
The x-component of the jet's momentum.
Definition: Jet_v1.cxx:90
ParticleJetTools::LabelNames::childPdgId
std::string childPdgId
Definition: ParticleJetLabelCommon.h:34
ParticleJetTools::LabelDecorators::childPt
SG::AuxElement::Decorator< float > childPt
Definition: ParticleJetLabelCommon.h:52
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
ParticleJetTools::LabelDecorators::positionDEta
SG::AuxElement::Decorator< float > positionDEta
Definition: ParticleJetLabelCommon.h:49
ParticleJetTools::signalProcessP3
Amg::Vector3D signalProcessP3(const xAOD::TruthEventContainer &)
Definition: ParticleJetLabelCommon.cxx:57
ParticleJetTools::positionDPhi
float positionDPhi(const xAOD::TruthParticle *part, const xAOD::Jet &jet, const Amg::Vector3D &origin)
Definition: ParticleJetLabelCommon.cxx:303
ParticleJetTools::setJetLabels
void setJetLabels(const xAOD::Jet &jet, const Particles &particles, const LabelNames &names)
Definition: ParticleJetLabelCommon.cxx:280
ParticleJetTools::LabelNames::positionDEta
std::string positionDEta
Definition: ParticleJetLabelCommon.h:30
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
LArG4AODNtuplePlotter.varname
def varname(hname)
Definition: LArG4AODNtuplePlotter.py:37
ParticleJetTools::LabelNames::pt
std::string pt
Definition: ParticleJetLabelCommon.h:25
ParticleJetTools::partLxy
float partLxy(const xAOD::TruthParticle *part, const Amg::Vector3D &origin)
Definition: ParticleJetLabelCommon.cxx:290
ParticleJetTools::partPdgId
int partPdgId(const xAOD::TruthParticle *part)
Definition: ParticleJetLabelCommon.cxx:299
ParticleJetTools::LabelDecorators::childPositionDEta
SG::AuxElement::Decorator< float > childPositionDEta
Definition: ParticleJetLabelCommon.h:55
ParticleJetTools::LabelNames::barcode
std::string barcode
Definition: ParticleJetLabelCommon.h:31
LArG4FSStartPointFilter.particles
list particles
Definition: LArG4FSStartPointFilter.py:84
ParticleJetTools::LabelDecorators::positionDPhi
SG::AuxElement::Decorator< float > positionDPhi
Definition: ParticleJetLabelCommon.h:48
python.DecayParser.children
children
Definition: DecayParser.py:32
ParticleJetTools::LabelDecorators
Definition: ParticleJetLabelCommon.h:40
ParticleJetTools::IParticleLinker::decorate
void decorate(const xAOD::Jet &, const std::vector< const xAOD::TruthParticle * > &) const
Definition: ParticleJetLabelCommon.cxx:143
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
ParticleJetTools::LabelDecorators::childPositionDPhi
SG::AuxElement::Decorator< float > childPositionDPhi
Definition: ParticleJetLabelCommon.h:54
ParticleJetTools::LabelDecorators::singleint
SG::AuxElement::Decorator< int > singleint
Definition: ParticleJetLabelCommon.h:42
python.compressB64.c
def c
Definition: compressB64.py:93
ParticleJetTools::LabelDecorators::dr
SG::AuxElement::Decorator< float > dr
Definition: ParticleJetLabelCommon.h:46
ParticleJetTools::LabelNames::positionDPhi
std::string positionDPhi
Definition: ParticleJetLabelCommon.h:29
HepMCHelpers.h
ParticleJetTools::IParticleLinker::IPLV
std::vector< ElementLink< xAOD::IParticleContainer > > IPLV
Definition: ParticleJetLabelCommon.h:65
python.handimod.cc
int cc
Definition: handimod.py:523
rerun_display.chk
chk
Definition: rerun_display.py:69
isMuon
bool isMuon(const T &p)
Definition: AtlasPID.h:154
ParticleJetTools::LabelNames
Definition: ParticleJetLabelCommon.h:22