ATLAS Offline Software
ClassifyAndCalculateHFTool.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 // //
7 // ClassifyAndCalculateHFTool.cxx //
8 // Implementation file for class ClassifyAndCalculateHFTool //
9 // Author: Adrian Berrocal Guardia <adrian.berrocal.guardia@cern.ch> //
10 // //
12 
16 
17 namespace DerivationFramework {
18 
19  /*
20  ---------------------------------------------------------------------------------------------------------------------------------------
21  ------------------------------------------------------- Constructor/Destructor --------------------------------------------------------
22  ---------------------------------------------------------------------------------------------------------------------------------------
23  */
24 
25  ClassifyAndCalculateHFTool::ClassifyAndCalculateHFTool(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t,n,p){
26  declareInterface<DerivationFramework::ClassifyAndCalculateHFTool>(this);
27  }
28 
30  }
31 
32  /*
33  ---------------------------------------------------------------------------------------------------------------------------------------
34  --------------------------------------------------------- Initialize/Finalize ---------------------------------------------------------
35  ---------------------------------------------------------------------------------------------------------------------------------------
36  */
37 
39 
40  ATH_MSG_INFO("Initialize");
41 
42  // Print the string variables.
43 
44  ATH_MSG_INFO("Cut on the pt of the jets: " << m_jetPtCut);
45  ATH_MSG_INFO("Cut on the eta of the jets: " << m_jetEtaCut);
46  ATH_MSG_INFO("Cut on the pt of the leading hadron: " << m_leadingHadronPtCut);
47  ATH_MSG_INFO("Cut on the ratio between the pt of the leading hadron and the pt of its associated jet: " << m_leadingHadronPtRatioCut);
48 
49  return StatusCode::SUCCESS;
50  }
51 
53  return StatusCode::SUCCESS;
54  }
55 
56  /*
57  ---------------------------------------------------------------------------------------------------------------------------------------
58  -------------------------------------------------------------- Flag Jets --------------------------------------------------------------
59  ---------------------------------------------------------------------------------------------------------------------------------------
60  */
61 
63  const std::map<const xAOD::Jet*, std::vector<xAOD::TruthParticleContainer::const_iterator>>& particleMatch,
64  const std::map<const xAOD::TruthParticle*, DerivationFramework::HadronOriginClassifier::HF_id>& hadronMap,
65  const std::string& hfDecorationName) const{
66 
67  SG::Decorator< int > decorator_flav(hfDecorationName + "_flav");
68  SG::Decorator< int > decorator_id(hfDecorationName + "_id");
69  SG::Decorator< int > decorator_count(hfDecorationName + "_count");
70 
71  for(const xAOD::Jet* jet : *jets){
72 
73  // Check if the jet passes the cuts and if it does not, then skip it.
74 
75  if(jet->p4().Pt() < m_jetPtCut || std::abs(jet->p4().Eta()) > m_jetEtaCut) {
76  decorator_flav(*jet) = -999;
77  decorator_id(*jet) = -999;
78  decorator_count(*jet) = -999;
79  continue;
80  }
81 
82  // Create a set of integer variables to save the necessary variables for the HF classifier:
83  // -flav: Flavour of the jet.
84  // -id: Origin of the most initial hadron of the jet.
85  // -count: Number of associated hadrons of the jet that have the same flavour as the jet.
86 
87  int flav=0;
88  int id=0;
89  int count=0;
90 
91  // Create a set of integer variables to save information that is required to compute the necessary variables for the HF classifier.:
92  // -bcount: It contains the number of B-hadrons.
93  // -ccount: It contains the number of C-hadrons.
94  // -bcountcut: It contains the number of B-hadron that pass the cuts.
95  // -ccountcut: It contains the number of C-hadron that pass the cuts.
96  // -bid: The greatest value of the variable "TopHadronOriginFlag" for B-hadrons (most initial B-hadron).
97  // -cid: The greatest value of the variable "TopHadronOriginFlag" for C-hadrons (most initial B-hadron).
98 
99  int bcount=0;
100  int ccount=0;
101  int bcountcut=0;
102  int ccountcut=0;
103 
104  int bid=0;
105  int cid=0;
106 
107  // Get the hadrons associated with the jet that is being considered.
108 
109  auto it = particleMatch.find (jet);
110  if (it != particleMatch.end()) {
111 
113 
114  // Create two integer variables:
115  // -hforigin: It will contain the origin of the hadron if it is a HF hadron. Otherwise, it will be 6.
116  // -pdgId: It will contain the value of the variable "pdgId" of the hadron.
117 
118  int hforigin = 6;
119  int pdgId = (*hf)->pdgId();
120 
121  // Extract the origin of the hadron.
122 
123  auto h_it = hadronMap.find(*hf);
124  if(h_it!=hadronMap.end()){
125  hforigin= static_cast<int>(h_it->second);
126  }
127 
128  // Check if hforigin is 6 and if it is the case, then hadron is not HF and it is skipped.
129 
130  if(6==hforigin) continue;
131 
132  // Compute the ratio between the pt of the hadron and the pt of its associated jet.
133 
134  float ptratio = (*hf)->p4().Pt()/jet->p4().Pt();
135 
136  // Determine if the hadron is a B-hadron or a C-hadron.
137 
138  int hftype = 0;
139 
140  if(MC::isCharmHadron(pdgId)) hftype=4; // B-hadron
141  if(MC::isBottomHadron(pdgId)) hftype=5; // C-hadron.
142 
143  // Check if hftype is 4 or 5.
144 
145  if(5==hftype){
146 
147  // In this case, hftype is 5 so the hadron is a B-hadron.
148  // Save hforigin in bid if it is greater than the current bid.
149 
150  if(bid<hforigin)bid=hforigin;
151 
152  // Add one to bcount and to bcountcut if hadron passes the cuts.
153 
154  ++bcount;
155 
156  if((*hf)->p4().Pt()>m_leadingHadronPtCut && ptratio>m_leadingHadronPtRatioCut){
157  ++bcountcut;
158  }
159  }
160  else if(4==hftype){
161 
162  // In this case, hftype is 4 so the hadron is a C-hadron.
163  // Save hforigin in cid if it is greater than the current cid.
164 
165  if(cid>hforigin)cid=hforigin;
166 
167  // Add one to ccount and to ccountcut if hadron passes the cuts.
168 
169  ++ccount;
170 
171  if((*hf)->p4().Pt()>m_leadingHadronPtCut && ptratio>m_leadingHadronPtRatioCut){
172  ++ccountcut;
173  }
174 
175  }
176  else{
177 
178  // In this case, hftype is not 4 neither 5 so print an error.
179 
180  ATH_MSG_WARNING("Hadron type '" << hftype << "' is not 4 or 5");
181 
182  }
183 
184  }
185  }
186 
187  // Check if there is at least one B-hadron or a C-hadron that passes the cuts.
188 
189  if(bcountcut){
190 
191  // In this case, at least one B-hadron passes the cuts.
192  // The "flavour" of the jet (flav) is set to 5.
193  // As a id of the jet, the greatest value of the variable "TopHadronOriginFlag" for B-hadrons is used (origin of the most initial hadron).
194  // The number of B-hadrons is saved in count.
195 
196  flav=5;
197  id=bid;
198  count=bcount;
199  }
200  else if(ccountcut){
201 
202  // In this case, no B-hadron passes the cuts, but at least one C-hadron does.
203  // The "flavour" of the jet (flav) is set to 4.
204  // As a id of the jet, the greatest value of the variable "TopHadronOriginFlag" for C-hadrons is used (origin of the most initial hadron).
205  // The number of C-hadrons is saved in count.
206 
207  flav=4;
208  id=cid;
209  count=ccount;
210  }
211 
212  // Dectorate the jet with the flav, id and count.
213  decorator_flav(*jet) = flav;
214  decorator_id(*jet) = id;
215  decorator_count(*jet) = count;
216  }
217 
218  }
219 
220  /*
221  ---------------------------------------------------------------------------------------------------------------------------------------
222  ---------------------------------------------------------- HF Classification ----------------------------------------------------------
223  ---------------------------------------------------------------------------------------------------------------------------------------
224  */
225 
226  int ClassifyAndCalculateHFTool::computeHFClassification(const xAOD::JetContainer* jets, const std::string& hfDecorationName) const{
227 
228  // Create a set of integer variables to save information that is required to compute the HF classifier.:
229  // -b: Number of jets that has just one B-hadron that passes the cuts.
230  // -B: Number of jets that has more than one B-hadron and at least one of them passes the cuts.
231  // -c: Number of jets that has just one C-hadron that passes the cuts (and no B-hadron)
232  // -C: Number of jets that has more than one C-hadron and at least one of them passes the cuts (and no B-hadron).
233  // -b_prompt: Number of jets that has just one prompt B-hadron that passes the cuts.
234  // -B_prompt: Number of jets that has more than one prompt B-hadron and at least one of them passes the cuts.
235  // -c_prompt: Number of jets that has just one prompt C-hadron that passes the cuts (and no B-hadron).
236  // -C_prompt: Number of jets that has more than one prompt C-hadron and at least one of them passes the cuts (and no B-hadron).
237  // -mpifsr_code: HF classifier for events with no prompt additional hadrons, just Multi-Parton Interaction (MPI) and/or Final State Radiation (FSR) hadrons.
238  // Note: prompt hadrons in this context are hadrons that do not come from the direct decay of top, W or Higgs but they are not from MPI or FSR.
239 
240  int b=0, B=0, c=0, C=0;
241  int b_prompt=0, B_prompt=0, c_prompt=0, C_prompt=0;
242 
243  int mpifsr_code=0;
244 
245  for(const xAOD::Jet* jet : *jets){
246 
247  // Check if the jet passes the cuts and if it does not, then skip it.
248 
249  if(jet->p4().Pt() < m_jetPtCut) continue;
250  if(std::abs(jet->p4().Eta()) > m_jetEtaCut) continue;
251 
252  // Get the flavour, the id and the number of hadrons of the considered jet.
253 
254  int flav = 0;
255  int id = 0;
256  int count = 0;
257 
258  SG::ConstAccessor<int> hfflavAcc(hfDecorationName + "_flav");
259  if(hfflavAcc.isAvailable(*jet)){
260  flav=hfflavAcc(*jet);
261  }else{
262  ATH_MSG_WARNING("variable '" + hfDecorationName + "_flav' not found.");
263  continue;
264  }
265 
266  SG::ConstAccessor<int> hfidAcc(hfDecorationName + "_id");
267  if(hfidAcc.isAvailable(*jet)){
268  id=hfidAcc(*jet);
269  }else{
270  ATH_MSG_WARNING("variable '" + hfDecorationName + "_id' not found.");
271  continue;
272  }
273 
274  SG::ConstAccessor<int> hfcountAcc(hfDecorationName + "_count");
275  if(hfcountAcc.isAvailable(*jet)){
276  count=hfcountAcc(*jet);
277  }else{
278  ATH_MSG_WARNING("variable '" + hfDecorationName + "_count' not found.");
279  continue;
280  }
281 
282  // Check the flavour and the id of the jet.
283 
284  if(flav==5 && id < 3){
285 
286  // In this case, the flavour is 5 and id is less than 3.
287  // This means that the jet has at least one B-hadron that is not from direct decay of top, W or Higgs.
288  // Hence, the jet is an additional one.
289 
290  // Check the number of B-hadrons.
291 
292  if(count > 1){
293 
294  // In this case, there is more than one B-hadron, so add 1 to B.
295 
296  B++;
297 
298  }
299  else{
300 
301  // In this case, there is just one B-hadron, so add 1 to b.
302 
303  b++;
304 
305  }
306  }
307  if(flav==4 && (id==0 || id==-1 || id==-2)){
308 
309  // In this case, the flavour is 4 and id is 0, -1 or -2.
310  // This means that the jet has no B-hadron and at least one C-hadron that is not from direct decay of top, W or Higgs.
311  // Hence, the jet is an additional one.
312 
313  // Check the number of C-hadrons.
314 
315  if(count > 1){
316 
317  // In this case, there is more than one C-hadron, so add 1 to C.
318 
319  C++;
320  }
321  else{
322 
323  // In this case, there is just one C-hadron, so add 1 to c.
324 
325  c++;
326  }
327  }
328 
329  // Check the flavour and the id of the jet but considering only prompt particles (id=0).
330 
331  if(flav==5 && id==0){
332 
333  // In this case, the flavour is 5 and id is 0.
334  // This means that the jet has at least one B-hadron that is not from direct decay of top, W or Higgs neither from MPI or FSR.
335 
336  // Check the number of B-hadrons.
337 
338  if(count > 1){
339 
340  // In this case, there is more than one B-hadron, so add 1 to B_prompt.
341 
342  B_prompt++;
343 
344  }
345  else{
346 
347  // In this case, there is jut one B-hadron, so add 1 to b_prompt.
348 
349  b_prompt++;
350 
351  }
352  }
353  if(flav==4 && id==0){
354 
355  // In this case, the flavour is 4 and id is 0.
356  // This means that the jet has no B-hadron and at least one C-hadron that is not from direct decay of top, W or Higgs neither from MPI or FSR.
357 
358  // Check the number of C-hadrons.
359 
360  if(count > 1){
361 
362  // In this case, there is more than one C-hadron, so add 1 to C_prompt.
363 
364  C_prompt++;
365  }
366  else{
367 
368  // In this case, there is just one C-hadron, so add 1 to C_prompt.
369 
370  c_prompt++;
371 
372  }
373  }
374 
375  // In the case when there is no prompt hadrons, then the HF classifier is computed with non-promt hadrons.
376  // This hadrons come from Multi-Parton Interactions (MPI) and the Final State Radiation (FSR).
377  // Compute mpifsr_code which will contain the HF classifier when there is no prompt hadrons.
378  // Each jet adds a different quantity to mpifsr_code depending on its flavour and its id.
379 
380  if(id==1 && flav==5){ // b MPI
381  mpifsr_code -= 1000;
382  }
383  else if(id==2 && flav==5){ // b FSR
384  mpifsr_code -= 100;
385  }
386  else if(id==-1 && flav==4){ // c MPI
387  mpifsr_code -= 10;
388  }
389  else if(id==-2 && flav==4) { // c FSR
390  mpifsr_code -= 1;
391  }
392  }
393 
394  // Compute the ext_code using the number of additional jets with HF hadrons.
395  // Compute the prompt_code using the number of additional jets with propmt HF hadrons.
396 
397  int ext_code = 1000*b+100*B+10*c+1*C;
398  int prompt_code = 1000*b_prompt+100*B_prompt+10*c_prompt+1*C_prompt;
399 
400  // Check if there are prompt hadrons and non-prompt hadrons using ext_code and prompt_code.
401 
402  if(prompt_code==0 && ext_code!=0){
403 
404  // In this case, there is no prompt hadrons but there are MPI and FSR hadrons.
405  // Hence, return mpifsr_code as a HF classifier, which is equal to ext_code but in negative sign.
406 
407  return mpifsr_code;
408 
409  }
410 
411  // In this case, there are prompt hadrons, so return ext_code as HF classifier.
412 
413  return ext_code;
414 
415  }
416 
418 
419  // Check the value of the HF classifier (hfclassif) which is computed with the function computeHFClassification.
420 
421  if(std::abs(hfclassif)>=100){
422 
423  // If the absolute value of hfclassif is greater than 100, then there is at least one jet with a B-hadron.
424  // In this case, return 1.
425 
426  return 1;
427 
428 
429  }
430  else if(hfclassif==0){
431 
432  // If hfclassif is 0, then there is no jet with a B-hadron or a C-hadron.
433  // In this case, return 0.
434 
435  return 0;
436  }
437 
438  // If the absolute value of hfclassif is lower than 100 and non-zero, then there is no jet with a B-hadron but at least one with a C-hadron.
439  // In this case, return -1.
440 
441  return -1;
442  }
443 }
DerivationFramework::ClassifyAndCalculateHFTool::flagJets
void flagJets(const xAOD::JetContainer *jets, const std::map< const xAOD::Jet *, std::vector< xAOD::TruthParticleContainer::const_iterator >> &particleMatch, const std::map< const xAOD::TruthParticle *, DerivationFramework::HadronOriginClassifier::HF_id > &hadronMap, const std::string &hfDecorationName) const
Definition: ClassifyAndCalculateHFTool.cxx:62
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
skel.it
it
Definition: skel.GENtoEVGEN.py:396
DerivationFramework::ClassifyAndCalculateHFTool::m_leadingHadronPtCut
Gaudi::Property< float > m_leadingHadronPtCut
Definition: ClassifyAndCalculateHFTool.h:102
SG::ConstAccessor< int >
DerivationFramework::ClassifyAndCalculateHFTool::~ClassifyAndCalculateHFTool
virtual ~ClassifyAndCalculateHFTool()
Definition: ClassifyAndCalculateHFTool.cxx:29
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
DerivationFramework::ClassifyAndCalculateHFTool::initialize
virtual StatusCode initialize() override
Definition: ClassifyAndCalculateHFTool.cxx:38
isBottomHadron
bool isBottomHadron(const T &p)
Definition: AtlasPID.h:680
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
DerivationFramework::ClassifyAndCalculateHFTool::computeHFClassification
int computeHFClassification(const xAOD::JetContainer *jets, const std::string &hfDecorationName) const
Definition: ClassifyAndCalculateHFTool.cxx:226
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
DerivationFramework::ClassifyAndCalculateHFTool::m_jetPtCut
Gaudi::Property< float > m_jetPtCut
Definition: ClassifyAndCalculateHFTool.h:100
DerivationFramework::ClassifyAndCalculateHFTool::finalize
virtual StatusCode finalize() override
Definition: ClassifyAndCalculateHFTool.cxx:52
SG::Decorator< int >
DerivationFramework::ClassifyAndCalculateHFTool::m_leadingHadronPtRatioCut
Gaudi::Property< float > m_leadingHadronPtRatioCut
Definition: ClassifyAndCalculateHFTool.h:103
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
DerivationFramework
THE reconstruction tool.
Definition: ParticleSortingAlg.h:24
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:227
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
DerivationFramework::ClassifyAndCalculateHFTool::m_jetEtaCut
Gaudi::Property< float > m_jetEtaCut
Definition: ClassifyAndCalculateHFTool.h:101
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::ClassifyAndCalculateHFTool::getSimpleClassification
int getSimpleClassification(int hfclassif) const
Definition: ClassifyAndCalculateHFTool.cxx:417
isCharmHadron
bool isCharmHadron(const T &p)
Definition: AtlasPID.h:679
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
defineDB.jets
list jets
Definition: JetTagCalibration/share/defineDB.py:24
DerivationFramework::ClassifyAndCalculateHFTool::ClassifyAndCalculateHFTool
ClassifyAndCalculateHFTool(const std::string &t, const std::string &n, const IInterface *p)
Definition: ClassifyAndCalculateHFTool.cxx:25
ClassifyAndCalculateHFTool.h
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
AthAlgTool
Definition: AthAlgTool.h:26
python.compressB64.c
def c
Definition: compressB64.py:93
HepMCHelpers.h