ATLAS Offline Software
HFOR_Truth.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 #include <cmath>
6 #include <iostream>
7 #include <map>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "boost/property_tree/info_parser.hpp"
13 #include "boost/property_tree/xml_parser.hpp"
14 
15 // Framework include(s):
16 
17 #include "xAODBase/IParticle.h"
18 
21 
24 
27 
29 
30 #include <HFORTools/HFOR_Truth.h>
31 
32 using namespace std;
33 //==============================================================================
34 //HFOR_Truth Instantiation
35 //There is no default strategy, it's mandatory to chose either angularBased or
36 //jetBased overlap removal.
37 //Several bookkeeper maps are provided to track the action of the tool
38 //==============================================================================
40  m_debug = false;
41  //You will need to configure the tool to the HFOR strategy you want
42  m_angularBased_HFOR = false;
43  m_jetBased_HFOR = false;
44 
45  m_matchCone = 0.4 ;
46  m_jetBasedHFOR_pT_min = 5000.; //5 GeV is the lower limit of AntiKt4Jets reclustering
47  m_jetBasedHFOR_eta_max = 4.5;
48  m_sampleType = HFORType::noType;
49 
50  //Helper to understand what each number means
51  m_sampleNameMap[HFORType::isBB] = "bb";
52  m_sampleNameMap[HFORType::isCC] = "cc" ;
53  m_sampleNameMap[HFORType::isC] = "c" ;
54  m_sampleNameMap[HFORType::isLight] = "light" ;
55  m_sampleNameMap[HFORType::noType] = "unknown" ;
56 
57  m_sampleName = m_sampleNameMap[m_sampleType] ;
58 
59  m_runConfigMap[HFORType::isLight].clear() ;
60  m_runConfigMap[HFORType::isBB].clear() ;
61  m_runConfigMap[HFORType::isCC].clear() ;
62  m_runConfigMap[HFORType::isC].clear() ;
63 
64  m_runConfigFile = "" ;
65 
66  //Initialize the maps book-keepping information
67 
68  //Number of quarks identifyed/found
69  m_Nquarks["FS"][4] = 0 ;
70  m_Nquarks["FS"][5] = 0 ;
71 
72  m_Nquarks["ME"][4] = 0 ;
73  m_Nquarks["ME"][5] = 0 ;
74 
75  m_Nquarks["GS"][4] = 0 ;
76  m_Nquarks["GS"][5] = 0 ;
77 
78  m_Nquarks["MPI"][4] = 0 ;
79  m_Nquarks["MPI"][5] = 0 ;
80 
81  //Number of classifications
82  m_Nclass[HFORType::isBB] = 0 ;
83  m_Nclass[HFORType::isCC] = 0 ;
84  m_Nclass[HFORType::isC] = 0 ;
85  m_Nclass[HFORType::isLight] = 0 ;
86  m_Nclass[HFORType::noType] = 0 ;
87 
88  //Vector of deltaR for each type
89 
90  m_dR["ME"][4].clear() ;
91  m_dR["ME"][5].clear() ;
92 
93  m_dR["GS"][4].clear() ;
94  m_dR["GS"][5].clear() ;
95 
96 }
97 //==============================================================================
98 
99 //==============================================================================
100 //HFOR_Truth Instantiation
101 //This method will navigate through the MC container, finds final state quarks
102 //and finds if overlaps are present. It will then call the configured strategy
103 //(jet or angular based removal) and return an "action" (keep the event which
104 //is now classified accordingly to HFORType or kill it)
105 //==============================================================================
107  const xAOD::JetContainer* jets) {
108 
109  unsigned int nPart = 0 ;
110 
111  //unsigned int quarks_4 = 0 ;
112  //unsigned int quarks_5 = 0 ;
113 
115 
116  //If this sample is not Alpgen+Pythia, do nothing
117  if ( m_sampleType == HFORType::noType ) {
118  //This message should be debug ...
119  //Warning(__PRETTY_FUNCTION__, "This is not a valid AlpgenPythia sample, do nothing") ;
120  return action ;
121  }
122 
123  //Navigates through the MC truth container and try to find if overlaps are present
124 
125  std::map <int, std::vector<const xAOD::TruthParticle* > > fsQuarksMap ;
126 
127  //Scan the container and find the final state quarks
128  for (const auto *truth : truthEvent ) {
129  //std::cout << "---> " << truth->crossSection() << " " << truth->crossSectionError() << std::endl ;
130  if (truth != nullptr) {
131  //nVert = truth->nTruthVertices();
132  nPart = truth->nTruthParticles();
133  for (unsigned int i = 0; i < nPart; i++) {
134  const xAOD::TruthParticle* truthParticle = truth->truthParticle(i);
135  if (truthParticle != nullptr) {
136  if (MC::isCharm(truthParticle)) {
137  //quarks_4 ++ ;
138  if (is_FinalState(truthParticle) ) {
139  fsQuarksMap[4].push_back(truthParticle) ;
140  }
141  }
142  if (MC::isBottom(truthParticle)) {
143  //quarks_5 ++ ;
144  if ( is_FinalState(truthParticle) ) {
145  fsQuarksMap[5].push_back(truthParticle) ;
146  }
147  }
148  }
149  }
150  }
151  }
152 
153  //Book keeping
154  m_Nquarks["FS"][4] += fsQuarksMap[4].size() ;
155  m_Nquarks["FS"][5] += fsQuarksMap[5].size() ;
156 
157  //std::cout << "==============> " << quarks_4 << quarks_5 << std::endl ;
158  //Now scan the final state particle container to identify the type of action to take
159  //It return an string that could decorate the original container for further processing
160 
161  findHFQuarks(fsQuarksMap) ;
162 
163  if(m_angularBased_HFOR){ //Perform an angular based removal action
164  action = angularBasedRemoval() ;
165  } else if (m_jetBased_HFOR) {
166 
167  if(jets) action = jetBasedRemoval(jets);
168  else Warning("HFOR_Truth::findOverlap()","No JetContainer passed to jet-based HFOR!");
169 
170  } else{
171  Error("HFOR_Truth::findOverlap()","No HFOR type has been specified!");
172  }
173 
174  if(m_debug) {
175  for (auto& cc: m_qq ) {
176  std::string cc_name = cc.first ;
177  for (auto& qmap: cc.second) {
178  int id = qmap.first ;
179  std::cout << " ***** ----> " << cc_name << " " << id << " " << qmap.second.size() << std::endl ;
180  }
181  }
182  }
183 
184  //std::cout << "!!!!! " << fsQuarksMap[4].size() << " " << fsQuarksMap[5].size() << std::endl ;
185  return (action) ;
186 }
187 //==============================================================================
188 
189 //==============================================================================
190 // This method will determine the type of action (keep or kill the event) using
191 // b and c truth jets.
192 //==============================================================================
194 
195  //If this sample is not Alpgen+Pythia, do nothing
196  if ( m_sampleType == HFORType::noType ) { //This message should be debug ...
197  Warning(__PRETTY_FUNCTION__, "This is not a valid AlpgenPythia sample, do nothing") ;
198  return (HFORType::noType) ;
199  }
200 
201  if(m_debug) std::cout<<std::endl<<"jetBased HFOR"<<std::endl;
202  bool killEvent = false;
203  if(!jets) Error("HFOR_Truth::jetBasedRemoval()","Couldn't jet container! It is needed for JetBased HFOR!");
204 
205  //Load the quark vectors (these are always the same in the event)
206  std::vector <const xAOD::TruthParticle*> B_ME_v = m_qq["ME"][5];
207  std::vector <const xAOD::TruthParticle*> C_ME_v = m_qq["ME"][4];
208  std::vector <const xAOD::TruthParticle*> B_GS_v = m_qq["GS"][5];
209  std::vector <const xAOD::TruthParticle*> C_GS_v = m_qq["GS"][4];
210 
211  for (const xAOD::Jet * jet : *jets) {
212  const std::string labelGhostB = "GhostBQuarksFinal", labelGhostC = "GhostCQuarksFinal";
213  std::vector<const xAOD::TruthParticle *> ghostB, ghostC;
214  if( !jet->getAssociatedObjects<xAOD::TruthParticle>( labelGhostB, ghostB ) ||
215  !jet->getAssociatedObjects<xAOD::TruthParticle>( labelGhostC, ghostC ) ){
216  Error("HFOR_Truth::jetBasedRemoval()","Couldn't access truth particleas associated to HF quarks!");
217  return HFORType::noType;
218  }
219 
220  size_t nGhostMatchedBQuarks = ghostB.size();
221  size_t nGhostMatchedCQuarks = ghostC.size();
222  size_t nB_ME = 0, nC_ME = 0, nB_GS = 0, nC_GS = 0;
223 
224  if(nGhostMatchedCQuarks == 0 && nGhostMatchedBQuarks == 0) continue;//do nothing for jets without HF hadrons!
225  if( jet->pt() < m_jetBasedHFOR_pT_min || std::fabs(jet->eta()) > m_jetBasedHFOR_eta_max ) continue;
226 
227  //Look only in region where to use only GS only for 2 quarks in 1 jet and ME for 2 quarks in 2 jets
228 
229  for (const xAOD::TruthParticle * part : ghostB ) {
230  if(!part) Error("HFOR_Truth::jetBasedRemoval()","No BQuark particles but ghost-matching exists!! It should not happen!");
231  for (const xAOD::TruthParticle * part_B_ME : B_ME_v )
232  if( HepMC::uniqueID(part) == HepMC::uniqueID(part_B_ME)) nB_ME++;
233  for (const xAOD::TruthParticle * part_B_GS : B_GS_v )
234  if( HepMC::uniqueID(part) == HepMC::uniqueID(part_B_GS)) nB_GS++;
235  }
236 
237  for (const xAOD::TruthParticle * part : ghostC ) {
238  if(!part) Error("HFOR_Truth::jetBasedRemoval()","No CQuark particles but ghost-matching exists!! It should not happen!");
239  for (const xAOD::TruthParticle * part_C_ME : C_ME_v )
240  if( HepMC::uniqueID(part) == HepMC::uniqueID(part_C_ME)) nC_ME++;
241  for (const xAOD::TruthParticle * part_C_GS : C_GS_v )
242  if( HepMC::uniqueID(part) == HepMC::uniqueID(part_C_GS)) nC_GS++;
243  }
244 
245  //Decide if you want to keep or not the event on the basis of this jet
246 
247  if(m_sampleType == HFORType::isLight){
248  if( nB_GS == 1 || nC_GS == 1) killEvent |= true;
249  else killEvent |= false;
250  }
251 
252  if(m_sampleType == HFORType::isBB ){
253  if( nB_ME == 2 ) killEvent |= true;
254  else killEvent |= false;
255  }
256 
257  if(m_sampleType == HFORType::isC || m_sampleType == HFORType::isCC){
258  if( nC_ME == 2 ) killEvent |= true;
259  else killEvent |= false;
260  }
261 
262  if(m_debug) {//All debug informaiton I may need...
263  std::cout<<"Looking j: pt= "<<jet->pt()/1000.<<" eta= "<<jet->eta()<<" phi= "<<jet->phi()
264  <<" FinalCount B "<<jet->auxdata<int>("GhostBQuarksFinalCount")
265  <<" FinalCount C "<<jet->auxdata<int>("GhostCQuarksFinalCount")<<std::endl;
266 
267  std::cout<<"nB_ME = "<<nB_ME<<" nC_ME = "<<nC_ME<<" nB_GS = "<<nB_GS<<" nC_GS = "<<nC_GS<<std::endl;
268  for (const xAOD::TruthParticle * part : ghostB ) {
269  std::cout<<"ghost b: "<<part<<" Vtx: "<<part->prodVtx()<<" n parent: "<<part->nParents()<<" n children: "<<part->nChildren()<<std::endl;
270  if(part->nParents())
271  std::cout<<" mother: "<<part->parent()<<" mother mothers: "<<part->parent()->nParents()<<std::endl;
272  }
273 
274  for (const xAOD::TruthParticle * part : ghostC ) {
275  if(part){
276  std::cout<<"ghost c: "<<part<<" n parent: "<<part->nParents()<<" n children: "<<part->nChildren()<<std::endl;
277  if(part->nParents()) std::cout<<"mother: "<<part->parent()<<" Vtx: "<<part->prodVtx()<<" mother mothers: "<<part->parent()->nParents()<<std::endl;
278  } else {
279  std::cout<<"WARNING: MISSING LINK!!!"<<std::endl;
280  }
281  }
282  }
283  }
284  if(m_debug) std::cout<<"KILL event? "<<killEvent<<std::endl;
285  if(killEvent) return HFORType::kill ;
286 
287  return (HFORType::noType) ;
288 }
289 //==============================================================================
290 
291 //==============================================================================
292 // Here we take all b and c quarks in the MC event tree and find if it is a
293 // final state quark
294 //==============================================================================
295 bool HFOR_Truth::is_FinalState(const xAOD::TruthParticle* bcQuark) const {
296  //This checks if the quark passed is final state or not
297  //TODO: check that this particle is really a b/c quark, check that it is not null
298 
299  const xAOD::TruthParticle * father = nullptr ;
300  const xAOD::TruthParticle * son = nullptr ;
301 
302  unsigned int nChildren = bcQuark->nChildren() ;
303  unsigned int nParents = bcQuark->nParents() ;
304 
305  bool isFromHadron = false ;
306  bool iscFromb = false ;
307  //+++++++++NB: THIS CHECK ALSO REMOVES B/C ORIGINATING FROM THE INIT. STATE PROTONS
308  // (MAYBE MPI PARTICLES) IS THIS FINE? I THINK IT WORKS BECAUSE THEY SHOULD NOT BE HFOR-ED
309  // BUT I AM NOT SURE....
310  for (unsigned int i=0; i<nParents; i++) {
311  father = bcQuark->parent(i) ;
312  if(m_debug) std::cout << " Father PDGID " << father->pdgId() << " (quark is " << bcQuark->pdgId() << ")" << std::endl ;
313  isFromHadron = (isFromHadron | father->isHadron() ) ;
314  if ( MC::isCharm(bcQuark) ) {
315  iscFromb = (iscFromb | MC::isBottom(father) ) ;
316  }
317  }
318  if (isFromHadron || iscFromb) {
319  return (false) ;
320  }
321 
322  for (unsigned int i=0; i<nChildren; i++) {
323  son = bcQuark->child(i) ;
324  if (son != nullptr) {
325  if ( MC::isCharm(son) || MC::isBottom(son) ) {
326  return (false) ;
327  }
328  } else {
329  return (false) ;
330  }
331  }
332 
333  return (true) ;
334 }
335 //==============================================================================
336 
337 //==============================================================================
338 // Here we will take the final state quarks found in this event and classify
339 // them as from Matrix Element, Gluon Spliting PDF or MPI. Containers are filled
340 // with quarks classified as ME or GS for further check on the fase space they
341 // occupy
342 //==============================================================================
343 bool HFOR_Truth::findHFQuarks(const std::map <int,
344  std::vector<const xAOD::TruthParticle* > >& fsQuarksMap) {
345 
346  //What I return is a map containing a map of vectors GS quarks and ME quarks
347  m_qq.clear() ; //VERY IMPORTANT
348 
349  int fsq_pdgId = -999 ;
350  int fsq_status = 0 ;
351 
352  int pdgId = 0 ;
353  int vtxBarcode = 0 ;
354  int level = 0 ;
355  int nid = 0 ;
356 
357  unsigned int nParents = 0 ;
358 
359  bool hasAncestor = false ;
360  bool hasProton = false ;
361 
362  bool isME = false ;
363 
364 
365  bool bc34 = false ;
366 
367 
368  std::vector <const xAOD::TruthParticle*> ME ;
369  std::vector <const xAOD::TruthParticle*> PDF ;
370 
371  std::map< int, std::vector <const xAOD::TruthParticle*> > xME ;
372  std::map< int, std::vector <const xAOD::TruthParticle*> > xPDF ;
373 
374  std::map< int, std::vector <const xAOD::TruthParticle*> > MPI ;
375  std::map< int, std::vector <const xAOD::TruthParticle*> > GS ;
376  std::map< int, std::vector <const xAOD::TruthParticle*> > ME_PDF ;
377  std::map< int, std::vector <const xAOD::TruthParticle*> > UFO ;
378 
379  const xAOD::TruthParticle* father = nullptr ;
380  //const xAOD::TruthParticle* son = nullptr ;
381  const xAOD::TruthParticle* ancestor = nullptr ;
382 
383  const xAOD::TruthVertex * prodVtx = nullptr;
384  const xAOD::TruthVertex * pvtx34 = nullptr;
385 
386  std::map<std::string, bool> tipo ;
387 
388 
389  // 1) Loop and find fs quarks with status 3
390 
391  for (const auto& fsQuarks: fsQuarksMap ) {
392  fsq_pdgId = fsQuarks.first ;
393  for (const auto& bcQuark: fsQuarks.second) {
394  fsq_status = bcQuark->status() ;
395  if (fsq_status == 3) {
396  if ( bcQuark->nChildren() == 0 ) {
397  //This is a Matrix Element quark
398  ME.push_back(bcQuark) ;
399 
400  for (unsigned int i=0; i<bcQuark->nParents(); i++) {
401  //If one of the parents has status = 3 and is the same flavor of the particle
402  //--> the PARENT will be a PDF parton
403  father = bcQuark->parent(i) ;
404  if ( (father->absPdgId() == fsq_pdgId) && (father->status() == 3) ) {
405  PDF.push_back(father) ;
406  }
407  }
408  }
409  else {
410  //This is a PDF Quark
411  PDF.push_back(bcQuark) ;
412  }
413  }
414  }
415  }
416 
417  // 2) Loop again and find fs quarks with status != 3
418 
419  for (const auto& fsQuarks: fsQuarksMap ) {
420  fsq_pdgId = fsQuarks.first ;
421  for (const auto& bcQuark: fsQuarks.second) {
422  fsq_status = bcQuark->status() ;
423  if (fsq_status != 3) {
424  //recursive search through ancestors, as xAOD cannot give a list of
425  //particle ancestors ...
426  level = 0 ;
427  ancestor = bcQuark ;
428 
429  hasAncestor = true ;
430  hasProton = false ;
431 
432  while (hasAncestor) {
433  // Check if the ancestor :
434  // 1) The ancestor is NOT SAME FLAVOR of bcQuark :
435  // - check if Ancestor is a proton
436  // - check if Ancestor is a top
437  // - check if Ancestor is a W
438  // - if bcQuark is c, check if Ancestor is a b or a b-Hadron -> STOP NAVIGATION
439  // - if bcQuark is b, check if Ancestor is a b-Hadron -> STOP NAVIGATION
440 
441  // 2) The ancestor IS SAME FLAVOR of bcQuark :
442  // - Do nothing, as this is from b/c or ME/PDF parent
443 
444  nParents = ancestor->nParents() ;
445  if ( nParents != 0 ) {
446  //FIXME: Should loop over all parents
447  ancestor = ancestor->parent(0) ;
448  level++ ;
449  }
450  else hasAncestor = false ;
451 
452  if (level != 0) {
453  tipo = checkAncestor(ancestor,bcQuark) ;
454  if ( tipo["orphan"] or tipo["cFromb"] or tipo["bFromb"] ) {
455  hasAncestor = false ;
456  }
457  else {
458  hasProton |= tipo["proton"] ;
459  }
460  }
461  }
462 
463  if ( (level == 1) & hasProton ) {
464  //This is a MPI
465  MPI[fsq_pdgId].push_back(bcQuark) ;
466  }
467  if ( (level == 2) & hasProton ) {
468  if ( (ME.size() + PDF.size()) == 0 ) {
469  //This comes from GS
470  GS[fsq_pdgId].push_back(bcQuark) ;
471  }
472  else {
473  //ME or PDF parton
474  ME_PDF[fsq_pdgId].push_back(bcQuark) ;
475 
476  //Check the production vertex
477  prodVtx = bcQuark->prodVtx() ;
478  pdgId = bcQuark->pdgId() ;
479  vtxBarcode = HepMC::barcode(prodVtx) ; // FIXME barcode-based
480  bc34 = ( (vtxBarcode == -3) | (vtxBarcode == -4) ) ; // FIXME barcode-based comparison against specific values
481  pvtx34 = prodVtx ;
482  if (! bc34) {
483  //Navigate the ancestor, stop if find a vtxBarcode == -3 or -4
484  hasAncestor = true ;
485  ancestor = bcQuark ;
486  while (hasAncestor) {
487  nParents = ancestor->nParents() ;
488  if (nParents != 0) {
489  for (unsigned int npp=0; npp<nParents; npp++) {
490  ancestor = ancestor->parent(npp) ;
491  prodVtx = ancestor->prodVtx() ;
492  vtxBarcode = HepMC::barcode(prodVtx) ; // FIXME barcode-based
493  bc34 = ( (vtxBarcode == -3) | (vtxBarcode == -4) ) & (ancestor->pdgId() == pdgId) ; // FIXME barcode-based comparison against specific values
494  if (bc34) pvtx34 = prodVtx ;
495  }
496  }
497  else hasAncestor = false ;
498  }
499  }
500  if (bc34) {
501  //Loop over the PDF partons container and see if from this vertex we get
502  //an oposite charge, same flavour quark
503  nid = 0 ;
504  for (auto& part: PDF) {
505  if ( ( part->prodVtx() == pvtx34 ) && (part->pdgId() == -pdgId) ) {
506  xPDF[fsq_pdgId].push_back(bcQuark) ;
507  nid++ ;
508  }
509  }
510 
511  //Check production vertex of parents, stop at the first
512  isME = false ;
513  for (auto& part: ME) {
514  if (!isME) {
515  nParents = part->nParents() ;
516  for (unsigned int i=0; i<nParents; i++) {
517  father = part->parent(i) ;
518  if ( ( father->prodVtx() == pvtx34 ) && (part->pdgId() == pdgId) ) {
519  xME[fsq_pdgId].push_back(bcQuark) ;
520  nid++ ;
521  isME = true ;
522  }
523  }
524  }
525  }
526  if (nid == 0) {
527  GS[fsq_pdgId].push_back(bcQuark) ;
528  }
529  }
530  else {
531  //Don't know what is this ...."
532  UFO[fsq_pdgId].push_back(bcQuark) ;
533  }
534  }
535  }
536  }
537  }
538  if (PDF.size() != xPDF[fsq_pdgId].size()) {
539  //Warning(__PRETTY_FUNCTION__, "Mismatch number of PDF identified partons of flavor %i", fsq_pdgId);
540  }
541  }
542 
543  //Store the quarks as classified in ME or GS
544  m_qq["ME"] = xME ;
545  m_qq["GS"] = GS ;
546 
547  //Book keeping
548  m_Nquarks["ME"][4] += xME[4].size() ;
549  m_Nquarks["ME"][5] += xME[5].size() ;
550 
551  m_Nquarks["GS"][4] += GS[4].size() ;
552  m_Nquarks["GS"][5] += GS[5].size() ;
553 
554  m_Nquarks["MPI"][4] += MPI[4].size() ;
555  m_Nquarks["MPI"][5] += MPI[5].size() ;
556 
557  if(m_debug){
558  std::cout<<"m_qq.size = "<<m_qq.size()<<endl;
559  std::cout<<"PDF n = "<<PDF.size()<<std::endl;
560  for(auto & i : PDF) std::cout<<i<<std::endl;
561  std::cout<<"ME n = "<<ME.size()<<std::endl;
562  for(auto & i : ME) std::cout<<i<<std::endl;
563  std::cout<<"GS n = "<<GS.size()<<std::endl;
564  for (const auto& gs_item : GS){
565  std::cout<<"GS item i = "<<gs_item.first<<std::endl;
566  for(const auto & i : gs_item.second) std::cout<<i<<std::endl;
567  }
568 
569  std::cout<<"xPDF n = "<<xPDF.size()<<std::endl;
570  for (const auto& xPDF_item : xPDF){
571  std::cout<<"xPDF item i = "<<xPDF_item.first<<std::endl;
572  for(const auto & i : xPDF_item.second) std::cout<<i<<std::endl;
573  }
574 
575  std::cout<<"xME n = "<<xME.size()<<std::endl;
576  for (const auto& xME_item : xME){
577  std::cout<<"xME item i = "<<xME_item.first<<std::endl;
578  for(const auto & i : xME_item.second) std::cout<<i<<std::endl;
579  }
580 
581  std::cout<<"MPI n = "<<MPI.size()<<std::endl;
582  for (const auto& mpi_item : MPI){
583  std::cout<<"MPI item i = "<<mpi_item.first<<std::endl;
584  for(const auto & i : mpi_item.second) std::cout<<i<<std::endl;
585  }
586  std::cout<<"ME_PDF n = "<<ME_PDF.size()<<std::endl;
587  for (const auto& ME_PDF_item : ME_PDF){
588  std::cout<<"ME_PDF item i = "<<ME_PDF_item.first<<std::endl;
589  for(const auto & i : ME_PDF_item.second) std::cout<<i<<std::endl;
590  }
591 
592  std::cout<<"UFO n = "<<UFO.size()<<std::endl;
593  for (const auto& UFO_item : UFO){
594  std::cout<<"UFO item i = "<<UFO_item.first<<std::endl;
595  for(const auto & i : UFO_item.second) std::cout<<i<<std::endl;
596  }
597  }
598 
599  return (true) ;
600 }
601 //==============================================================================
602 
603 //==============================================================================
604 // Helper to check the parent type of the b or c quark
605 //==============================================================================
606 std::map<std::string, bool> HFOR_Truth::checkAncestor(const xAOD::TruthParticle* ancestor,
607  const xAOD::TruthParticle* bcQuark) {
608 
609  std::map<std::string, bool> tipo ;
610 
611  tipo ["proton"] = false ;
612  tipo ["top"] = false ;
613  tipo ["W"] = false ;
614  tipo ["cFromb"] = false ;
615  tipo ["bFromb"] = false ;
616  tipo ["orphan"] = false ;
617  if (!is_sameFlavor(ancestor, bcQuark) ) {
618  tipo ["proton"] = is_proton(ancestor);
619  tipo ["top"] = ancestor->isTop() ;
620  tipo ["W"] = ancestor->isW() ;
621  tipo ["cFromb"] = (MC::isCharm(bcQuark) && (MC::isBottom(ancestor) || MC::isBottomHadron(ancestor))) ;
622  tipo ["bFromb"] = (MC::isBottom(bcQuark) && MC::isBottomHadron(ancestor)) ;
623  }
624  else {
625  tipo["orphan"] = true ;
626  }
627 
628  return (tipo) ;
629 
630 }
631 
632 //==============================================================================
633 
634 //==============================================================================
635 // Helper to check if particle is a proton
636 //==============================================================================
638  return (x->absPdgId() == 2212) ;
639 }
640 //==============================================================================
641 
642 //==============================================================================
643 
644 //==============================================================================
645 // Helper to check if 2 particles have the same flavor
646 //==============================================================================
648  const xAOD::TruthParticle* y) {
649  return ( x->absPdgId() == y->absPdgId() ) ;
650 }
651 //==============================================================================
652 
653 //==============================================================================
654 // Here we need to identify which flavor this MC sample is. We rely on a
655 // configuration file which relates the MC ChannelNumber (or run number) to
656 // his flavor.
657 //==============================================================================
658 int HFOR_Truth::readRunConfig(std::string runConfigFile) {
659 
660  m_runConfigFile = std::move(runConfigFile) ;
661 
662  boost::property_tree::ptree runConfig ;
663  boost::property_tree::read_info (m_runConfigFile, runConfig) ;
664 
665  for(boost::property_tree::ptree::value_type &v : runConfig.get_child("flavor.isLight")) {
666  m_runConfigMap[HFORType::isLight].push_back( atoi(v.first.data()) ) ;
667  }
668  for(boost::property_tree::ptree::value_type &v : runConfig.get_child("flavor.isBB")) {
669  m_runConfigMap[HFORType::isBB].push_back( atoi(v.first.data()) ) ;
670  }
671  for(boost::property_tree::ptree::value_type &v : runConfig.get_child("flavor.isCC")) {
672  m_runConfigMap[HFORType::isCC].push_back( atoi(v.first.data()) ) ;
673  }
674  for(boost::property_tree::ptree::value_type &v : runConfig.get_child("flavor.isC")) {
675  m_runConfigMap[HFORType::isC].push_back( atoi(v.first.data()) ) ;
676  }
677 
678  return 1;
679 }
680 
681 //==============================================================================
682 
683 //==============================================================================
684 // Here we keep the record of the MC sample type. The decision to keep or
685 // kill the event depends on this information
686 //==============================================================================
687 void HFOR_Truth::setSampleType(unsigned int sampleRunNumber) {
688 
690  HFORType key ;
691  bool found = false ;
692 
693  for (auto& kk: m_runConfigMap ) {
694  if (!found) {
695  key = kk.first ;
696  it = find (kk.second.begin(), kk.second.end(), sampleRunNumber);
697  if (it != m_runConfigMap[key].end() ) found = true ;
698  }
699  }
700 
701  if(!found) key = HFORType::noType ;
702 
703  m_sampleType = key ;
704  m_sampleName = m_sampleNameMap[m_sampleType] ;
705 
706 }
707 //==============================================================================
708 
709 //==============================================================================
710 // Getter to access the MC sample type
711 //==============================================================================
713  return m_sampleType ;
714 }
715 //==============================================================================
716 
717 //==============================================================================
718 // Getter for a human readable format of the MC sample
719 //==============================================================================
721  return m_sampleName ;
722 }
723 //==============================================================================
724 
725 //==============================================================================
726 // Setter for the size of the cone to be used in the overlap removal
727 //==============================================================================
729 
730  //Sanity check
731  if (deltaR > 0.0) {
732  m_matchCone = deltaR ;
733  }
734 }
735 //==============================================================================
736 
737 //==============================================================================
738 // Getter to access the value of cone size used in the overlap removal
739 //==============================================================================
741  return m_matchCone ;
742 }
743 //==============================================================================
744 
745 
746 //==============================================================================
747 //Here we will perform the angular based removal based on the sample type.
748 //Based on the angle between the 2 b or c quarks and it's classification as from
749 //ME or GS the event will be flagged to be killed (if it's a ME quark living
750 //in a GS phase space and vice-versa)
751 //==============================================================================
753 
754  HFORType tipo ;
755  std::string proc ;
756  int flavor ;
757 
758  std::map< std::string, std::map<int, int> > hasMatch ;
759  double dR = 0;
760 
761  for (auto& bcProcMap : m_qq ) {
762  proc = bcProcMap.first ;
763  for (auto& bcMap : bcProcMap.second) {
764  flavor = bcMap.first ;
765  hasMatch[proc][flavor] = 0 ;
766  m_dR[proc][flavor].clear() ;
767  if ( bcMap.second.size() > 1) {
768  //Combination of 2 different quarks
769  for (unsigned int i=0;i<bcMap.second.size();i++) {
770  for (unsigned int j=i+1;j<bcMap.second.size();j++) {
771  const xAOD::TruthParticle* x = bcMap.second[i] ;
772  const xAOD::TruthParticle* y = bcMap.second[j] ;
773  //Make sure they are opposite charge
774  //TODO: make sure they are from same vtx
775  if ( x->pdgId() == -y->pdgId() ) {
776 
777  dR = sqrt( pow(x->phi() - y->phi(),2) + pow(x->eta() - y->eta(),2) ) ;
778  m_dR[proc][flavor].push_back(dR) ;
779  if ( dR < m_matchCone ) {
780  hasMatch[proc][flavor]++ ;
781  if(m_debug) { // Same vertex ?
782  if (x->prodVtx() == y->prodVtx()) {
783  std::cout << "Match from same Vertex flavor->" << flavor << std::endl ;
784  }
785  else {
786  std::cout << "Match NOT from same Vertex flavor->" << flavor << std::endl ;
787  }
788  std::cout << "///////////////// " << proc << " " << flavor << " dr " << dR << std::endl ;
789  }
790  }
791  else {
792  if(m_debug) std::cout << "No Match (dr>0.4)" << std::endl ;
793  }
794  }
795  }
796  }
797  }
798  }
799  }
800 
801  tipo = m_sampleType ;
802  if(tipo == HFORType::noType ) return tipo;
803 
804  //light sample
805  if (m_sampleType == HFORType::isLight) {
806  //Remove ME b,c quarks
807  if ( (!m_qq["ME"][4].empty()) || (!m_qq["ME"][5].empty()) ) {
808  tipo = HFORType::kill ;
809  if(m_debug) std::cout << "Killed by ME size 4,5: " << m_qq["ME"][4].size() << " , " << m_qq["ME"][4].size() << std::endl ;
810  }
811  //Remove un-matched GS b,c quarks
812  else if (!m_qq["GS"][5].empty()) {
813  if (hasMatch["GS"][5] > 0) {
814  tipo = HFORType::isBB;
815  }
816  else {
817  tipo = HFORType::kill;
818  }
819 
820  }
821  else if (!m_qq["GS"][4].empty()) {
822  if (hasMatch["GS"][4] > 0) {
823  tipo = HFORType::isCC;
824  }
825  else {
826  tipo = HFORType::kill;
827  }
828  }
829  }
830 
831  //cc sample
832  if (m_sampleType == HFORType::isCC) {
833  //Remove matched ME c quarks
834  if ( hasMatch["ME"][4] > 0 ) {
835  tipo = HFORType::kill ;
836  }
837  else if (hasMatch["GS"][5] > 0) {
838  tipo = HFORType::isBB ;
839  }
840  else if (!m_qq["GS"][5].empty()) {
841  tipo = HFORType::kill ;
842  }
843  }
844 
845  //c sample
846  if (m_sampleType == HFORType::isC) {
847  //Remove
848  if ( hasMatch["GS"][5] > 0 ) {
849  tipo = HFORType::isBB ;
850  }
851  else if (!m_qq["GS"][5].empty() ) {
852  tipo = HFORType::kill ;
853  }
854  }
855 
856  //bb sample
857  if (m_sampleType == HFORType::isBB) {
858  //Remove matched ME b quarks
859  if (hasMatch["ME"][5] > 0 )
860  tipo = HFORType::kill ;
861  }
862 
863  m_Nclass[tipo] ++ ;
864  return tipo ;
865 }
866 //==============================================================================
867 
868 //==============================================================================
869 //Access the bookkeeper map
870 //==============================================================================
871 unsigned long int HFOR_Truth::getNquarks(const std::string& process, int flavor) {
872  //Access the number of quarks found in this sample according to the
873  //process and flavor
874  //TODO: check the keys ..
875  return m_Nquarks[process][flavor] ;
876 }
877 //==============================================================================
878 
879 //==============================================================================
880 //Access the number of decisions taken in this sample
881 //==============================================================================
882 unsigned long int HFOR_Truth::getNclass(HFORType htipo) {
883  //TODO check the keys
884  return m_Nclass[htipo] ;
885 }
886 //==============================================================================
887 
888 //=============================================================================
889 //Access a vector containing the deltaR of a given process and flavor
890 //BEFORE selection
891 //==============================================================================
892 std::map<std::string, std::map<int, std::vector<float> > > HFOR_Truth::getdR() {
893 
894  return m_dR ;
895 }
896 //==============================================================================
897 
898 
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::TruthParticle_v1::parent
const TruthParticle_v1 * parent(size_t i=0) const
Retrieve the i-th mother (TruthParticle) of this TruthParticle.
Definition: TruthParticle_v1.cxx:131
xAOD::TruthParticle_v1::absPdgId
int absPdgId() const
Absolute PDG ID code (often useful)
Powheg_tt_mtop_common.PDF
PDF
Definition: Powheg_tt_mtop_common.py:110
IParticle.h
HFOR_Truth.h
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
HFOR_Truth::getNquarks
unsigned long int getNquarks(const std::string &process, int flavor)
Definition: HFOR_Truth.cxx:871
HFOR_Truth::is_FinalState
bool is_FinalState(const xAOD::TruthParticle *bcQuark) const
Definition: HFOR_Truth.cxx:295
HFORType
HFORType
Definition: HFORTypes.h:9
TruthVertexContainer.h
TruthParticleContainer.h
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
HFORType::noType
@ noType
skel.it
it
Definition: skel.GENtoEVGEN.py:423
HFOR_Truth::setSampleType
void setSampleType(unsigned int runNumber)
Definition: HFOR_Truth.cxx:687
xAOD::TruthParticle_v1::isW
bool isW() const
Check if this particle is a W boson.
HFOR_Truth::is_sameFlavor
static bool is_sameFlavor(const xAOD::TruthParticle *x, const xAOD::TruthParticle *y)
Definition: HFOR_Truth.cxx:647
x
#define x
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
SUSY_SimplifiedModel_PostInclude.process
string process
Definition: SUSY_SimplifiedModel_PostInclude.py:42
PowhegPy8EG_H2a.pdgId
dictionary pdgId
Definition: PowhegPy8EG_H2a.py:128
HFOR_Truth::readRunConfig
int readRunConfig(std::string runConfigFile)
Definition: HFOR_Truth.cxx:658
isBottomHadron
bool isBottomHadron(const T &p)
Definition: AtlasPID.h:466
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
TruthParticleAuxContainer.h
python.changerun.kk
list kk
Definition: changerun.py:41
xAOD::TruthParticle_v1::nParents
size_t nParents() const
Number of parents of this particle.
Definition: TruthParticle_v1.cxx:122
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
HFOR_Truth::getSampleName
std::string getSampleName()
Definition: HFOR_Truth.cxx:720
HFOR_Truth::checkAncestor
static std::map< std::string, bool > checkAncestor(const xAOD::TruthParticle *ancestor, const xAOD::TruthParticle *bcQuark)
Definition: HFOR_Truth.cxx:606
isBottom
bool isBottom(const T &p)
Definition: AtlasPID.h:123
lumiFormat.i
int i
Definition: lumiFormat.py:92
HFOR_Truth::getdR
std::map< std::string, std::map< int, std::vector< float > > > getdR()
Definition: HFOR_Truth.cxx:892
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:41
HFORType::isBB
@ isBB
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:113
HFOR_Truth::findHFQuarks
bool findHFQuarks(const std::map< int, std::vector< const xAOD::TruthParticle * > > &fsQuarksMap)
Definition: HFOR_Truth.cxx:343
HFOR_Truth::getNclass
unsigned long int getNclass(HFORType)
Definition: HFOR_Truth.cxx:882
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
HFOR_Truth::setMatchConeSize
void setMatchConeSize(double deltaR)
Definition: HFOR_Truth.cxx:728
TruthVertexAuxContainer.h
xAOD::TruthParticle_v1::prodVtx
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
Definition: TruthParticle_v1.cxx:80
xAOD::TruthVertex_v1
Class describing a truth vertex in the MC record.
Definition: TruthVertex_v1.h:41
ptree
boost::property_tree::ptree ptree
Definition: JsonFileLoader.cxx:16
xAOD::TruthParticle_v1::nChildren
size_t nChildren() const
Number of children of this particle.
Definition: TruthParticle_v1.cxx:140
HFOR_Truth::getSampleType
HFORType getSampleType()
Definition: HFOR_Truth.cxx:712
mc.proc
proc
Definition: mc.PhPy8EG_A14NNPDF23_gg4l_example.py:22
HFORType::isC
@ isC
HFOR_Truth::angularBasedRemoval
HFORType angularBasedRemoval(void)
Definition: HFOR_Truth.cxx:752
python.PyAthena.v
v
Definition: PyAthena.py:157
HFOR_Truth::findOverlap
HFORType findOverlap(const xAOD::TruthEventContainer &truthEvent, const xAOD::JetContainer *jets=nullptr)
Definition: HFOR_Truth.cxx:106
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
xAOD::TruthVertex_v1::status
int status() const
New function Vertex status HepMC2 id == HepMC3 status, i.e.
Definition: TruthVertex_v1.h:59
HFORType::kill
@ kill
xAOD::TruthParticle_v1::status
int status() const
Status code.
y
#define y
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
python.CaloScaleNoiseConfig.action
action
Definition: CaloScaleNoiseConfig.py:77
HFOR_Truth::HFOR_Truth
HFOR_Truth()
Definition: HFOR_Truth.cxx:39
xAOD::TruthParticle_v1::child
const TruthParticle_v1 * child(size_t i=0) const
Retrieve the i-th mother (TruthParticle) of this TruthParticle.
Definition: TruthParticle_v1.cxx:149
TruthEventAuxContainer.h
HFOR_Truth::is_proton
static bool is_proton(const xAOD::TruthParticle *x)
Definition: HFOR_Truth.cxx:637
isCharm
bool isCharm(const T &p)
Definition: AtlasPID.h:120
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
defineDB.jets
list jets
Definition: JetTagCalibration/share/defineDB.py:24
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
TruthEventContainer.h
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
makeComparison.deltaR
float deltaR
Definition: makeComparison.py:36
HFOR_Truth::jetBasedRemoval
HFORType jetBasedRemoval(const xAOD::JetContainer *jets)
Definition: HFOR_Truth.cxx:193
HFOR_Truth::getMatchConeSize
double getMatchConeSize() const
Definition: HFOR_Truth.cxx:740
HFORType::isLight
@ isLight
HepMCHelpers.h
xAOD::TruthParticle_v1::isHadron
bool isHadron() const
Whether the particle is a hadron.
python.handimod.cc
int cc
Definition: handimod.py:523
xAOD::TruthParticle_v1::isTop
bool isTop() const
Check if this particle is a top quark.
HFORType::isCC
@ isCC
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37