ATLAS Offline Software
Truth3CollectionMaker.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 // Author: James Catmore (James.Catmore@cern.ch) with modifications by Benjamin Nachman (bnachman@cern.ch)
6 // Removes all truth particles/vertices which do not pass a user-defined cut
7 
12 //#include "xAODTruth/TruthVertexContainer.h"
13 
15 
16 #include <vector>
17 #include <string>
18 
19 // Constructor
21  const std::string& n,
22  const IInterface* p ) :
24 //m_ntotvtx(0),
25 m_ntotpart(0),
26 //m_npassvtx(0),
27 m_npasspart(0),
28 m_particlesKey("TruthParticles"),
29 //m_verticesKey("TruthVertices"),
30 m_collectionName(""),
31 m_partString(""),
32 m_classifier("MCTruthClassifier/MCTruthClassifier"),
33 m_runClassifier(true)
34 {
35  declareInterface<DerivationFramework::IAugmentationTool>(this);
36  declareProperty("ParticlesKey", m_particlesKey);
37  //declareProperty("VerticesKey", m_verticesKey);
38  declareProperty("NewCollectionName", m_collectionName);
39  declareProperty("ParticleSelectionString", m_partString);
40  declareProperty("MCTruthClassifier", m_classifier);
41  declareProperty("RunClassifier", m_runClassifier);
42 }
43 
44 // Destructor
46 }
47 
48 // Athena initialize and finalize
50 {
51  ATH_MSG_VERBOSE("initialize() ...");
52  if (m_runClassifier) ATH_CHECK(m_classifier.retrieve());
53 
54  if (m_particlesKey=="" /*|| m_verticesKey==""*/) {
55  ATH_MSG_FATAL("No truth particle collection provided to use as a basis for new collections");
56  return StatusCode::FAILURE;
57  } else {ATH_MSG_INFO("Using " << m_particlesKey << " as the source collections for new truth collections");}
58 
59  if (m_collectionName=="") {
60  ATH_MSG_FATAL("No key provided for the new truth particle collection");
61  return StatusCode::FAILURE;
62  } else {ATH_MSG_INFO("New truth particle collection key: " << m_collectionName );}
63 
64  if (m_partString=="") {
65  ATH_MSG_FATAL("No selection string provided");
66  return StatusCode::FAILURE;
67  } else {ATH_MSG_INFO("Truth particle selection string: " << m_partString );}
68 
69  // Set up the text-parsing machinery for thinning the truth directly according to user cuts
70  if ( !m_partString.empty() ) {
71  ATH_CHECK( initializeParser(m_partString) );
72  }
73  return StatusCode::SUCCESS;
74 }
75 
77 {
78  ATH_MSG_VERBOSE("finalize() ...");
79  //ATH_MSG_INFO("Processed "<< m_ntotvtx <<" truth vertices, "<< m_npassvtx << " were retained ");
80  ATH_MSG_INFO("Processed "<< m_ntotpart <<" truth particles, "<< m_npasspart << " were retained ");
81  ATH_CHECK( finalizeParser() );
82  return StatusCode::SUCCESS;
83 }
84 
85 // Selection and collection creation
87 {
88 
89  // Retrieve truth collections
90  const xAOD::TruthParticleContainer* importedTruthParticles;
91  if (evtStore()->retrieve(importedTruthParticles,m_particlesKey).isFailure()) {
92  ATH_MSG_ERROR("No TruthParticle collection with name " << m_particlesKey << " found in StoreGate!");
93  return StatusCode::FAILURE;
94  }
95 
96  // Create the new containers
97  xAOD::TruthParticleContainer* newParticleCollection = new xAOD::TruthParticleContainer();
98  CHECK( evtStore()->record( newParticleCollection, m_collectionName ) );
99  xAOD::TruthParticleAuxContainer* newParticleAuxCollection = new xAOD::TruthParticleAuxContainer();
100  CHECK( evtStore()->record( newParticleAuxCollection, m_collectionName + "Aux." ) );
101  newParticleCollection->setStore( newParticleAuxCollection );
102  ATH_MSG_DEBUG( "Recorded new TruthParticleContainer with key: " << m_collectionName);
103 
104  // Set up a mask with the same entries as the full collections
105  unsigned int nParticles = importedTruthParticles->size();
106  m_ntotpart += nParticles;
107 
108  // Set up decorators
109  static const SG::AuxElement::Decorator< ElementLink<xAOD::TruthParticleContainer> > linkDecorator("originalTruthParticle");
110  static const SG::AuxElement::Decorator< int > originDecorator("particleMotherPdgId");
111  static const SG::AuxElement::Decorator< int > typeDecorator("particleOriginBarcode"); // FIXME barcode-based
112  static const SG::AuxElement::Decorator< float > typeDecoratorMass("particleOriginMass");
113  static const SG::AuxElement::Decorator< int > tauprongDecorator("nprong");
114  static const SG::AuxElement::Decorator< int > tautypeDecorator("islep");
115 
116  std::vector<int> entries;
117 
118  // Execute the text parsers and update the mask
119  if (!m_partString.empty()) {
120  entries = m_parser->evaluateAsVector();
121  // check the sizes are compatible
122  if (nParticles != entries.size() ) {
123  ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used TruthParticles?");
124  return StatusCode::FAILURE;
125  } else {
126  // add relevant particles to new collection
127  for (unsigned int i=0; i<nParticles; ++i) {
128  ElementLink<xAOD::TruthParticleContainer> eltp(*importedTruthParticles,i);
129  if (entries[i]==1) {
130 
131  const xAOD::TruthParticle* theParticle = (*importedTruthParticles)[i];
132 
133  //SUSYTRUTH definitions are based on Appendix A in http://arxiv.org/pdf/1403.4853v1.pdf.
134 
135  //SUSYTRUTH Leptons
136  if (theParticle->isLepton()){
137  bool drop = false;
138  if (!theParticle->hasProdVtx()) drop = true;
139  else{
140  const int parentPDGID = abs(theParticle->prodVtx()->incomingParticle(0)->pdgId());
141  const double parentMass = theParticle->prodVtx()->incomingParticle(0)->p4().M()/1000.;
142  if (parentPDGID==24 && parentMass < 20){ //semi-leptonic b-decays in Herwig++ where the off-shell W is saved
143  drop = true;
144  }
145  else if (parentPDGID!=24 && parentPDGID!=15){ //what about W decays in Sherpa?
146  drop = true;
147  }
148  else if (parentPDGID==15){//check to make sure the tau came from a W
149  if (theParticle->prodVtx()->incomingParticle(0)->hasProdVtx()){
150  const xAOD::TruthParticle * mother_hold = theParticle->prodVtx()->incomingParticle(0)->prodVtx()->incomingParticle(0);
151  int mcount = 0;
152  while (mother_hold->hasProdVtx() && abs(mother_hold->pdgId())==15){
153  mcount++;
154  if (mcount > 10){ //should not ever come in here, but just in case there is a closed loop somewhere.
155  break;
156  }
157  mother_hold = mother_hold->prodVtx()->incomingParticle(0);
158  }
159  if (mcount > 10 || abs(mother_hold->pdgId())!=24){
160  drop = true;
161  }
162  else{
163  //keep
164  }
165  }
166  else{
167  drop = true;
168  }
169  }
170  }
171  if (drop){
172  entries[i]=0;
173  continue;
174  }
175  }
176 
177  xAOD::TruthParticle* xTruthParticle = new xAOD::TruthParticle();
178  newParticleCollection->push_back( xTruthParticle );
179 
180  int motherBarcode = HepMC::INVALID_PARTICLE_ID;
181  int motherPDGid = 0;
182  float mothermass = 0.;
183  if (theParticle->hasProdVtx()){
184  const xAOD::TruthParticle * mother_hold = theParticle->prodVtx()->incomingParticle(0);
185  motherBarcode = HepMC::barcode(mother_hold);
186  motherPDGid = mother_hold->pdgId();
187  mothermass = mother_hold->p4().M()/1000.;
188  xTruthParticle->setBarcode(motherBarcode); // FIXME barcode-based
189  int mcount = 0;
190  //Let's find the first mother of mothers that has a different PDGid
191  while (mother_hold->hasProdVtx() && mother_hold->pdgId()==theParticle->pdgId()){
192  mcount++;
193  if (mcount > 10){
194  break; //should not come in here, but just in case we have a closed loop from a bug
195  }
196  mother_hold = mother_hold->prodVtx()->incomingParticle(0);
197  motherBarcode = HepMC::barcode(mother_hold); // FIXME barcode-based
198  motherPDGid = mother_hold->pdgId();
199  mothermass = mother_hold->p4().M()/1000.;
200  }
201  }
202 
203  *xTruthParticle=*theParticle;
204  xTruthParticle->setBarcode(motherBarcode); // FIXME barcode-based
205  originDecorator(*xTruthParticle) = motherPDGid;
206  typeDecorator(*xTruthParticle) = motherBarcode; // FIXME barcode-based
207  typeDecoratorMass(*xTruthParticle) = mothermass;
208 
209  //Check for tau decays
210  if (abs(theParticle->pdgId()) == 15 && theParticle->hasDecayVtx()){
211  int nprong = 0;
212  int islep = 0;
213 
214  //Algorithm:
215  //Make a vector of all children of the tau. While one of the children has a child:
216  //Go down one level and store all of the children of the children. If no children have a child, stop.
217 
218  /*
219  std::vector< std::vector<const xAOD::TruthParticle *> > tau_family;
220  bool has_a_child = 0;
221  std::vector<const xAOD::TruthParticle *> tau_daughts_first;
222  for (unsigned int j=0; j<theParticle->nChildren(); j++){
223  const xAOD::TruthParticle * daught_hold = theParticle->decayVtx()->outgoingParticle(j);
224  tau_daughts_first.push_back(daught_hold);
225  if (daught_hold->hasDecayVtx()){
226  has_a_child = 1;
227  }
228  }
229  tau_family.push_back(tau_daughts_first);
230  int level = -1;
231  while (has_a_child){
232  level++;
233  has_a_child = 0;
234  std::vector<const xAOD::TruthParticle *> tau_daughts;
235  for (unsigned int j=0; j<tau_family[level].size(); j++){
236  for (unsigned int k=0; k<tau_family[level][j]->nChildren(); k++){
237  const xAOD::TruthParticle * daught_hold = tau_family[level][j]->decayVtx()->outgoingParticle(k);
238  tau_daughts.push_back(daught_hold);
239  if (daught_hold->hasDecayVtx()){
240  has_a_child = 1;
241  }
242  }
243  }
244  tau_family.push_back(tau_daughts);
245  }
246 
247  for (unsigned int i=0; i<tau_family.size(); i++){
248  for (unsigned int j=0; j<tau_family[i].size(); j++){
249  if (tau_family[i][j]->isChLepton()){
250  islep=1;
251  }
252  if (tau_family[i][j]->hasDecayVtx()){
253  continue;
254  }
255  if (tau_family[i][j]->isCharged()){
256  nprong++;
257  }
258  }
259  }
260  */
261 
262  //std::cout << "nprong " << nprong << " " << islep << std::endl;
263  tauprongDecorator(*xTruthParticle) = nprong;
264  tautypeDecorator(*xTruthParticle) = islep;
265  }
266  }
267  }
268  }
269  }
270  // Count the mask
271  for (unsigned int i=0; i<nParticles; ++i){
272  if (entries[i]) ++m_npasspart;
273  }
274 
275  return StatusCode::SUCCESS;
276 }
277 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
DerivationFramework::Truth3CollectionMaker::m_collectionName
std::string m_collectionName
Definition: Truth3CollectionMaker.h:35
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
DerivationFramework::Truth3CollectionMaker::m_partString
std::string m_partString
Definition: Truth3CollectionMaker.h:36
DerivationFramework::Truth3CollectionMaker::m_particlesKey
std::string m_particlesKey
Definition: Truth3CollectionMaker.h:33
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
xAOD::TruthParticle_v1::setBarcode
void setBarcode(int value)
Set barcode.
TruthParticleContainer.h
Truth3CollectionMaker.h
HepMC::INVALID_PARTICLE_ID
constexpr int INVALID_PARTICLE_ID
Definition: MagicNumbers.h:56
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
TruthParticleAuxContainer.h
xAOD::TruthParticle_v1::isLepton
bool isLepton() const
Whether the particle is a lepton.
xAOD::TruthParticleAuxContainer_v1
Auxiliary store for the truth vertices.
Definition: TruthParticleAuxContainer_v1.h:27
xAOD::TruthParticle_v1::hasDecayVtx
bool hasDecayVtx() const
Check for a decay vertex on this particle.
xAOD::TruthParticleAuxContainer
TruthParticleAuxContainer_v1 TruthParticleAuxContainer
Declare the latest version of the truth particle auxiliary container.
Definition: TruthParticleAuxContainer.h:16
IMCTruthClassifier.h
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:58
lumiFormat.i
int i
Definition: lumiFormat.py:92
beamspotman.n
n
Definition: beamspotman.py:731
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
DerivationFramework::Truth3CollectionMaker::Truth3CollectionMaker
Truth3CollectionMaker(const std::string &t, const std::string &n, const IInterface *p)
Definition: Truth3CollectionMaker.cxx:20
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
DerivationFramework::Truth3CollectionMaker::addBranches
virtual StatusCode addBranches() const override
Pass the thinning service
Definition: Truth3CollectionMaker.cxx:86
xAOD::TruthParticle
TruthParticle_v1 TruthParticle
Typedef to implementation.
Definition: Event/xAOD/xAODTruth/xAODTruth/TruthParticle.h:15
xAOD::TruthParticle_v1::hasProdVtx
bool hasProdVtx() const
Check for a production vertex on this particle.
Definition: TruthParticle_v1.cxx:74
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
xAOD::TruthVertex_v1::incomingParticle
const TruthParticle_v1 * incomingParticle(size_t index) const
Get one of the incoming particles.
Definition: TruthVertex_v1.cxx:71
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
xAOD::TruthParticle_v1::prodVtx
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
Definition: TruthParticle_v1.cxx:80
ExpressionParserUser
Definition: ExpressionParserUser.h:107
DerivationFramework::Truth3CollectionMaker::initialize
virtual StatusCode initialize() override
Definition: Truth3CollectionMaker.cxx:49
MagicNumbers.h
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
xAOD::TruthParticleContainer
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
Definition: Event/xAOD/xAODTruth/xAODTruth/TruthParticleContainer.h:17
DerivationFramework::Truth3CollectionMaker::finalize
virtual StatusCode finalize() override
Definition: Truth3CollectionMaker.cxx:76
DerivationFramework::Truth3CollectionMaker::m_runClassifier
bool m_runClassifier
Definition: Truth3CollectionMaker.h:38
entries
double entries
Definition: listroot.cxx:49
xAOD::TruthParticle_v1::p4
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
Definition: TruthParticle_v1.cxx:196
AthAlgTool
Definition: AthAlgTool.h:26
DerivationFramework::Truth3CollectionMaker::~Truth3CollectionMaker
~Truth3CollectionMaker()
Definition: Truth3CollectionMaker.cxx:45
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
DerivationFramework::Truth3CollectionMaker::m_classifier
ToolHandle< IMCTruthClassifier > m_classifier
Definition: Truth3CollectionMaker.h:37