ATLAS Offline Software
McVtxFilter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // McVtxFilter.cxx
7 // Implementation file for class McVtxFilter
8 // Author: S.Binet<binet@cern.ch>
10 
11 // Framework includes
13 #include "GaudiKernel/MsgStream.h"
14 #include "GaudiKernel/GaudiException.h"
15 
16 // HepMC includes
17 #include "AtlasHepMC/GenParticle.h"
18 #include "AtlasHepMC/GenVertex.h"
19 
20 // AnalysisUtils includes
22 
23 // McParticleUtils includes
25 
29 
33  IFilterCuts(),
34  AthMessaging ( "McVtxFilter" ),
35  m_matchSign( false ),
36  m_matchBranches( false ),
37  m_decayPattern( "" ),
38  m_parentList(),
39  m_childList()
40 {}
41 
42 McVtxFilter::McVtxFilter( const std::string& decayPattern,
43  const bool matchSign,
44  const bool matchBranches ) :
45  IFilterCuts(),
46  AthMessaging ( "McVtxFilter" ),
47  m_matchSign( matchSign ),
48  m_matchBranches( matchBranches ),
49  m_decayPattern( decayPattern ),
50  m_parentList(),
51  m_childList()
52 {
54 }
55 
56 McVtxFilter::McVtxFilter( const bool matchSign,
57  const bool matchBranches ) :
58  IFilterCuts(),
59  AthMessaging ( "McVtxFilter" ),
60  m_matchSign( matchSign ),
61  m_matchBranches( matchBranches ),
62  m_decayPattern( "" ),
63  m_parentList(),
64  m_childList()
65 {}
66 
68  IFilterCuts ( rhs ),
69  AthMessaging ( "McVtxFilter" ),
70  m_matchSign ( rhs.m_matchSign ),
71  m_matchBranches( rhs.m_matchBranches ),
72  m_decayPattern ( rhs.m_decayPattern ),
73  m_parentList(),
74  m_childList()
75 {
76  // deep copy of the parent branch
79  rhs.m_parentList.begin();
80  itr != rhs.m_parentList.end();
81  ++itr ) {
83  }
84 
85  // deep copy of the child branch
88  rhs.m_childList.begin();
89  itr != rhs.m_childList.end();
90  ++itr ) {
92  }
93 }
94 
96 {
97  if ( this != &rhs ) {
102 
103  // deep copy of the parent branch
106  rhs.m_parentList.begin();
107  itr != rhs.m_parentList.end();
108  ++itr ) {
110  }
111 
112  // deep copy of the child branch
115  rhs.m_childList.begin();
116  itr != rhs.m_childList.end();
117  ++itr ) {
119  }
120  }
121  return *this;
122 }
123 
124 
129 {
130  ATH_MSG_VERBOSE("In McVtxFilter::isAccepted(...)");
131 //AV TODO: add here a check to prevent null pointer dereference
132  unsigned int number_particles_out = vtx->particles_out_size();
133  unsigned int number_particles_in = vtx->particles_in_size();
138  if ( m_childList.size() == static_cast<unsigned int>( 1 ) &&
139  m_parentList.size() == static_cast<unsigned int>( 0 ) &&
140  number_particles_out == static_cast<unsigned int>( 1 ) ) {
141 #ifdef HEPMC3
142  const HepMC::ConstGenParticlePtr& part = vtx->particles_out().front();
143 #else
144  HepMC::ConstGenParticlePtr part = *(vtx->particles_out_const_begin());
145 #endif
146  const ParticleCandidateList * item = *( m_childList.begin() );
147  if ( item->hasInList( part->pdg_id(), m_matchSign ) ) {
148  return true;
149  } else {
150  return false;
151  }
152  }
153 
157  if ( !m_matchBranches ) {
158 
159  //
160  // Test only if there is enough *output* branches to match for
161  //
162  if ( number_particles_in < m_parentList.size() ||
163  number_particles_out < m_childList.size() ) {
164  return false;
165  }
166 
167  } else {
168  //
169  // Strict match of output branches
170  //
171  if ( number_particles_in != m_parentList.size() ||
172  number_particles_out != m_childList.size() ) {
173  return false;
174  }
175  }
176 
180  if ( m_matchBranches &&
181  m_parentList.size() == static_cast<unsigned int>(1) &&
182  m_childList.size() == static_cast<unsigned int>(2) &&
183  number_particles_out >= 2 ) {
184  return checkTwoBodyDecay( vtx );
185  } //> two-body decay
186 
187 
191  ATH_MSG_VERBOSE("trying checkParentBranch(...)");
192  if ( checkParentBranch( vtx ) == false ) return false;
193 
194  ATH_MSG_VERBOSE("trying checkChildBranch(...)");
195  if ( checkChildBranch ( vtx ) == false ) return false;
196 
197  ATH_MSG_VERBOSE("McVtxFilter::isAccepted(...) => DONE");
198  return true;
199 }
200 
201 void McVtxFilter::dump( std::ostream& out ) const
202 {
203  out << ">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<" << std::endl;
204  out << ">>> Parents : " << std::endl;
206  itr != m_parentList.end();
207  ++itr ) {
208  out << "\nList for : " << *itr
209  << " (" << (*itr)->size() << ")" << std::endl;
210  (*itr)->dropList();
211  }
212 
213  out << ">>> Children : " << std::endl;
215  itr != m_childList.end();
216  ++itr ) {
217  out << "\nList for : " << *itr
218  << " (" << (*itr)->size() << ")" << std::endl;
219  (*itr)->dropList();
220  }
221  out << ">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<" << std::endl;
222 
223  return;
224 }
225 
226 
230 
233 {
234  if ( filter ) {
235  const McVtxFilter * vtxFilter =
236  dynamic_cast<const McVtxFilter*>(filter);
237 
238  if ( vtxFilter ) {
239  operator=(*vtxFilter);
240  } else {
241  ATH_MSG_ERROR("Can't dynamic_cast " << typeid(filter).name() << " to a McVtxFilter");
242  }
243  } //> filter is a valid pointer
244 }
245 
247 void McVtxFilter::setDecayPattern( const std::string& decayPattern )
248 {
249  // clear parent and child candidates
251  m_childList.clear();
252 
254 
256 
257  std::vector<std::vector<std::string> > parents = parser.getParents();
258  for(std::vector<std::vector<std::string> >::const_iterator itr = parents.begin();
259  itr != parents.end();
260  ++itr ) {
262  const std::vector<std::string>::const_iterator candEnd = itr->end();
263  for( std::vector<std::string>::const_iterator candidate = itr->begin();
264  candidate != candEnd;
265  ++candidate ) {
266  int pdgID = parser.pdgId( *candidate );
267  list->push_back( pdgID );
268  }
269  if ( ! list->empty() ) {
271  } else {
272  delete list;
273  }
274  }
275  std::vector<std::vector<std::string> > children = parser.getChildren();
276  for(std::vector<std::vector<std::string> >::const_iterator itr = children.begin();
277  itr != children.end();
278  ++itr ) {
280  const std::vector<std::string>::const_iterator candEnd = itr->end();
281  for( std::vector<std::string>::const_iterator candidate = itr->begin();
282  candidate != candEnd;
283  ++candidate ) {
284  int pdgID = parser.pdgId( *candidate );
285  list->push_back( pdgID );
286  }
287  if ( ! list->empty() ) {
289  } else {
290  delete list;
291  }
292  }
293 
294  return;
295 }
296 
297 
301 
303 {
304  ATH_MSG_VERBOSE("In checkParentBranch...");
305 
307  if ( m_parentList.empty() ) {
308  return true;
309  }
310 
311  if ( msgLvl(MSG::VERBOSE) ) {
312  HepMC::Print::line(std::cout,vtx);
313  }
314 
316  if ( static_cast<unsigned int>(vtx->particles_in_size()) < m_parentList.size() ){
317  return false;
318  }
319 
320  if ( msgLvl(MSG::VERBOSE) ) {
321  msg() << MSG::VERBOSE
322  << "Number of list of parents : "
323  << m_parentList.size()
324  << endmsg;
326  }
327 
328  std::vector<int> parentIds;
329 #ifdef HEPMC3
330  for ( const auto& Part: vtx->particles_in() ) {
331  parentIds.push_back( Part->pdg_id() );
332  }
333 #else
334  for ( HepMC::GenVertex::particles_in_const_iterator itrPart = vtx->particles_in_const_begin();
335  itrPart != vtx->particles_in_const_end();
336  ++itrPart ) {
337  parentIds.push_back( (*itrPart)->pdg_id() );
338  }
339 #endif
340 
342  std::vector<int> parents;
343 
344  bool accepted = false;
345  while ( permute.get(parents) && !accepted ) {
346  accepted = true;
347  const unsigned int iMax = std::min( m_parentList.size(), parentIds.size() );
348  for ( unsigned int i = 0; i != iMax; ++i ) {
349  const bool hasInList = m_parentList[i]->hasInList( parents[i],m_matchSign );
350  if ( !hasInList ) {
351  // this permutation is not suiting, going to the next one (if any)
352  accepted = false;
353  break;
354  }
355  }
356 
357  // everything went fine for this permutation !
358  if ( accepted ) {
359  break;
360  }
361  }
362 
363  ATH_MSG_VERBOSE(">>> CheckParentBranch is DONE : "
364  << ( accepted ? "accept" : "reject" )
365  << " vtx= " << vtx);
366  return accepted;
367 }
368 
370 {
371  ATH_MSG_VERBOSE("In checkChildBranch...");
372 
373  if ( msgLvl(MSG::VERBOSE) ) {
374  HepMC::Print::line(std::cout,vtx);
375  }
376 
378  if ( m_childList.empty() ) {
379  return true;
380  }
381 
383  if ( static_cast<unsigned int>(vtx->particles_out_size()) < m_childList.size() ) return false;
384  ATH_MSG_VERBOSE("Number of list of children : " << m_childList.size());
385 
386  std::vector<int> childIds;
387  for ( auto Part: *vtx) {
388  childIds.push_back( Part->pdg_id() );
389  }
390 
392  std::vector<int> children;
393 
394  bool accepted = false;
395  while ( permute.get(children) && !accepted ) {
396  accepted = true;
397  const unsigned int iMax = std::min( m_childList.size(), childIds.size() );
398  for ( unsigned int i = 0; i != iMax; ++i ) {
399  const bool hasInList = m_childList[i]->hasInList( children[i], m_matchSign );
400  if ( !hasInList ) {
401  // this permutation is not suiting, going to the next one (if any)
402  accepted = false;
403  break;
404  }
405  }
406  }
407 
408  ATH_MSG_VERBOSE(">>> CheckChildBranch is DONE : "
409  << ( accepted ? "accept" : "reject" )
410  << " vtx= " << vtx);
411  return accepted;
412 }
413 
415 {
416  ATH_MSG_VERBOSE("In checkTwoBodyDecay...");
417 
421  const bool parentTree = checkParentBranch( vtx );
422  if ( parentTree == false ) {
423  return false;
424  }
425 
427  ATH_MSG_VERBOSE(">>> Check child branch");
428 
430  const ParticleCandidateList * children1 = m_childList[0];
431  const ParticleCandidateList * children2 = m_childList[1];
432 
434 //AV It would be a very good idea to have a chack of the number of output particles here.
435 #ifdef HEPMC3
436  const int pdgId1= vtx->particles_out().at(0)->pdg_id();
437  const int pdgId2= vtx->particles_out().at(1)->pdg_id();
438 #else
439  HepMC::GenVertex::particles_out_const_iterator itrPart = vtx->particles_out_const_begin();
440  const int pdgId1 = (*itrPart)->pdg_id();
441  ++itrPart;
442  const int pdgId2 = (*itrPart)->pdg_id();
443 #endif
444 
446  for( ParticleCandidateList::const_iterator itr1 = children1->begin();
447  itr1 != children1->end();
448  ++itr1 ) {
450  for( ParticleCandidateList::const_iterator itr2 = children2->begin();
451  itr2 != children2->end();
452  ++itr2 ) {
453  ATH_MSG_VERBOSE("Checking the pair : " << (*itr1) << "/" << (*itr2));
454 
457  if ( m_matchSign &&
458  ( ( (*itr1) == pdgId1 && (*itr2) == pdgId2 ) ||
459  ( (*itr1) == pdgId2 && (*itr2) == pdgId1 ) ) ) {
460  ATH_MSG_VERBOSE("Strict sign matching found !");
461  return true;
464  } else if ( ( std::abs(*itr1) == std::abs(pdgId1) &&
465  std::abs(*itr2) == std::abs(pdgId2) ) ||
466  ( std::abs(*itr1) == std::abs(pdgId2) &&
467  std::abs(*itr2) == std::abs(pdgId1) ) ) {
468  ATH_MSG_VERBOSE("Loose sign matching found !");
469  return true;
470  }
471  ATH_MSG_VERBOSE("Checking next pair");
472  }//> loop over 2nd child's candidates
473  }//> loop over 1st child's candidates
474 
477  ATH_MSG_VERBOSE(">>> CheckTwoBodyDecay is DONE.");
478  return false;
479 }
480 
482 // Operators
484 
485 MsgStream& operator<<( MsgStream & msg, const McVtxFilter &obj )
486 {
487  std::stringstream out;
488  obj.dump( out );
489  msg << out.str() << endmsg;
490  return msg;
491 }
492 
493 std::ostream& operator<<( std::ostream& out, const McVtxFilter &obj )
494 {
495  obj.dump( out );
496  return out;
497 }
DataVector::reserve
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
ParticleCandidateList::begin
const_iterator begin() const
Definition: ParticleCandidateList.h:145
python.CaloScaleNoiseConfig.parser
parser
Definition: CaloScaleNoiseConfig.py:75
McVtxFilter::dump
void dump(std::ostream &out=std::cout) const
Dump to std::ostream (default = std::cout) the decay pattern the filter one is looking for.
Definition: McVtxFilter.cxx:201
McVtxFilter::m_matchBranches
bool m_matchBranches
Tell if one wants a strict vertex branches matching.
Definition: McVtxFilter.h:174
AnalysisPermutation.h
McVtxFilter::m_parentList
DataVector< const ParticleCandidateList > m_parentList
The list of the matching particles Ids : each item in DataVector stands for an entering branch to the...
Definition: McVtxFilter.h:182
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
python.DecayParser.parents
parents
print ("==> buf:",buf)
Definition: DecayParser.py:31
GenVertex.h
ParticleCandidateList::dropList
void dropList() const
Definition: ParticleCandidateList.cxx:59
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
operator<<
MsgStream & operator<<(MsgStream &msg, const McVtxFilter &obj)
I/O operators.
Definition: McVtxFilter.cxx:485
McVtxFilter::checkParentBranch
bool checkParentBranch(HepMC::ConstGenVertexPtr vtx) const
Check if the parent branch fulfills the requirements.
Definition: McVtxFilter.cxx:302
McVtxFilter::setFilter
virtual void setFilter(const IFilterCuts *filter)
Set filter cut options.
Definition: McVtxFilter.cxx:232
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
HepMC::Print::line
void line(std::ostream &os, const GenEvent &e)
Definition: GenEvent.h:554
McVtxFilter::McVtxFilter
McVtxFilter()
Default constructor:
Definition: McVtxFilter.cxx:32
GenParticle.h
McVtxFilter::checkTwoBodyDecay
bool checkTwoBodyDecay(HepMC::ConstGenVertexPtr vtx) const
Check the branches for the special case of a 1->2 body decay (there is some room for optimisation in ...
Definition: McVtxFilter.cxx:414
covarianceTool.filter
filter
Definition: covarianceTool.py:514
McVtxFilter
McVtxFilter allows to select HepMC::GenParticle based on the decay pattern.
Definition: McVtxFilter.h:45
McVtxFilter::isAccepted
virtual bool isAccepted(HepMC::ConstGenVertexPtr vtx) const
Main filter method.
Definition: McVtxFilter.cxx:128
McVtxFilter::decayPattern
const std::string & decayPattern() const
return the decay pattern used by this filter
Definition: McVtxFilter.h:224
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
AthMessaging::msgLvl
bool msgLvl(const MSG::Level lvl) const
Test the output level.
Definition: AthMessaging.h:151
McVtxFilter::m_decayPattern
std::string m_decayPattern
The decay pattern one looks for.
Definition: McVtxFilter.h:178
AnalysisUtils::Permutation
permutation
Definition: AnalysisPermutation.h:24
lumiFormat.i
int i
Definition: lumiFormat.py:92
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
McVtxFilter::setDecayPattern
void setDecayPattern(const std::string &decayPattern)
Set the decay pattern to look for : it correctly setups the parent and children according to the LaTe...
Definition: McVtxFilter.cxx:247
DataVector::front
const T * front() const
Access the first element in the collection as an rvalue.
AnalysisUtils::Permutation::get
bool get(OUT &perm)
get a permutation.
Definition: AnalysisPermutation.h:59
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
McVtxFilter::checkChildBranch
bool checkChildBranch(HepMC::ConstGenVertexPtr vtx) const
Check if the child branch fulfills the requirements.
Definition: McVtxFilter.cxx:369
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
DataVector::clear
void clear()
Erase all the elements in the collection.
min
#define min(a, b)
Definition: cfImp.cxx:40
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
McVtxFilter.h
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.
item
Definition: ItemListSvc.h:43
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
ParticleCandidateList::end
const_iterator end() const
Definition: ParticleCandidateList.h:150
DetType::Part
Part
Definition: DetType.h:14
IFilterCuts::operator=
IFilterCuts & operator=(const IFilterCuts &rhs)
Assignment operator:
Definition: IFilterCuts.h:78
python.DecayParser.children
children
Definition: DecayParser.py:32
ParticleCandidateList::const_iterator
std::list< int >::const_iterator const_iterator
Definition: ParticleCandidateList.h:41
IFilterCuts
IFilterCuts is a class which is used internally by the filters to copy their cut properties one to ...
Definition: IFilterCuts.h:21
HepMC::ConstGenVertexPtr
const HepMC::GenVertex * ConstGenVertexPtr
Definition: GenVertex.h:60
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
ParticleCandidateList
A simple wrapper for std::list<int> to model a list of particle identity candidates.
Definition: ParticleCandidateList.h:31
McVtxFilter::m_matchSign
bool m_matchSign
Discrimination between particles and conjugates.
Definition: McVtxFilter.h:167
python.PyAthena.obj
obj
Definition: PyAthena.py:135
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
McVtxFilter::m_childList
DataVector< const ParticleCandidateList > m_childList
The list of the matching particles Ids : each item in DataVector stands for an out-going branch to th...
Definition: McVtxFilter.h:186
McVtxFilter::operator=
McVtxFilter & operator=(const McVtxFilter &rhs)
Assignment operator:
Definition: McVtxFilter.cxx:95
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
DecayParser
Definition: DecayParser.h:34