ATLAS Offline Software
TruthResetAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "TruthResetAlg.h"
6 //
7 #include "AtlasHepMC/GenEvent.h"
8 #include "AtlasHepMC/GenVertex.h"
12 
13 #include "StoreGate/ReadHandle.h"
14 #include "StoreGate/WriteHandle.h"
15 
16 #include "CLHEP/Vector/LorentzVector.h"
17 #include "CLHEP/Units/SystemOfUnits.h"
18 //
19 #include "CLHEP/Geometry/Point3D.h"
21 #include <climits>
22 
23 TruthResetAlg::TruthResetAlg(const std::string& name, ISvcLocator* pSvcLocator):
24  AthAlgorithm(name, pSvcLocator)
25 {
26  declareProperty("InputMcEventCollection" , m_inputMcEventCollection = "TruthEvent");
27  declareProperty("OutputMcEventCollection" , m_outputMcEventCollection = "NewTruthEvent");
28 }
29 
30 
31 //----------------------------------------------------
33 //----------------------------------------------------
34 
37  return StatusCode::SUCCESS;
38 
39 }
40 
41 //-------------------------------------------------
43 //-------------------------------------------------
44 
45  ATH_MSG_DEBUG( " execute..... " );
47  if (!inputMcEventCollection.isValid()) {
48  ATH_MSG_ERROR("Could not find input McEventCollection called " << inputMcEventCollection.name() << " in store " << inputMcEventCollection.store() << ".");
49  return StatusCode::FAILURE;
50  }
51  const HepMC::GenEvent& inputEvent(**(inputMcEventCollection->begin()));
52 
53  //Sanity check
54  bool inputProblem(false);
55  for (const auto& particle: inputEvent) {
56  if (MC::isStable(particle)) {
57  if (!particle->production_vertex()) {
58  ATH_MSG_ERROR("Stable particle without a production vertex!! " << particle);
59  inputProblem = true;
60  }
61  }
62  else if (MC::isDecayed(particle)) {
63  if (!particle->production_vertex()) {
64  ATH_MSG_ERROR("Decyed particle without a production vertex!! " << particle);
65  inputProblem = true;
66  }
67  if (!particle->end_vertex()) {
68  ATH_MSG_ERROR("Decyed particle without an end vertex!! " << particle);
69  inputProblem = true;
70  }
71  }
72  }
73  if (inputProblem) {
74  ATH_MSG_FATAL("Problems in input GenEvent - bailing out.");
75  return StatusCode::FAILURE;
76  }
77 #ifdef HEPMC3
78  std::unique_ptr<HepMC::GenEvent> outputEvent = std::make_unique<HepMC::GenEvent>(inputEvent);
81  if (inputEvent.run_info()) outputEvent->set_run_info(std::make_shared<HepMC3::GenRunInfo>(*(inputEvent.run_info().get())));
82  for (;;) {
83  std::vector<HepMC::GenParticlePtr> p_to_remove;
84  std::vector<HepMC::GenVertexPtr> v_to_remove;
85  for (auto& particle: outputEvent->particles()) {
87  p_to_remove.push_back(particle);
88  }
89  }
90  for (auto& particle: p_to_remove) outputEvent->remove_particle(particle);
91  for (auto& vertex: outputEvent->vertices()) {
92  if (HepMC::is_simulation_vertex(vertex) || vertex->particles_out().empty() ) {
93  v_to_remove.push_back(vertex);
94  }
95  }
96  for (auto& vertex: v_to_remove) outputEvent->remove_vertex(vertex);
97  if (p_to_remove.empty() && v_to_remove.empty()) break;
98  }
99 #else
100 
101  std::unique_ptr<HepMC::GenEvent> outputEvent = std::make_unique<HepMC::GenEvent>(inputEvent.signal_process_id(),
102  inputEvent.event_number());
103 
104  outputEvent->set_mpi ( inputEvent.mpi() );
105  outputEvent->set_event_scale ( inputEvent.event_scale() );
106  outputEvent->set_alphaQCD ( inputEvent.alphaQCD() );
107  outputEvent->set_alphaQED ( inputEvent.alphaQED() );
108  if ( inputEvent.cross_section() ) {
109  outputEvent->set_cross_section ( *inputEvent.cross_section());
110  }
111  if (inputEvent.heavy_ion()) {
112  outputEvent->set_heavy_ion(*(inputEvent.heavy_ion()));
113  }
114  if (inputEvent.pdf_info()) {
115  outputEvent->set_pdf_info(*(inputEvent.pdf_info()));
116  }
117  outputEvent->define_units( inputEvent.momentum_unit(), inputEvent.length_unit() );
118 
119  // 1. create a NEW copy of all vertices from inputEvent
120  // taking care to map new vertices onto the vertices being copied
121  // and add these new vertices to this event.
122  // We do not use GenVertex::operator= because that would copy
123  // the attached particles as well.
124  std::map<const HepMC::GenVertex*,HepMC::GenVertex*> inputEvtVtxToOutputEvtVtx;
125  HepMC::GenEvent::vertex_const_iterator currentVertexIter(inputEvent.vertices_begin());
126  const HepMC::GenEvent::vertex_const_iterator endOfCurrentListOfVertices(inputEvent.vertices_end());
127  ATH_MSG_VERBOSE( "Starting a vertex loop ... " );
128  for (; currentVertexIter != endOfCurrentListOfVertices; ++currentVertexIter) {
129  const HepMC::GenVertex *pCurrentVertex(*currentVertexIter);
130  if (HepMC::is_simulation_vertex(pCurrentVertex)) {
131  continue; // skip vertices created by the simulation
132  }
133  std::unique_ptr<HepMC::GenVertex> copyOfGenVertex =std::make_unique<HepMC::GenVertex>(pCurrentVertex->position(), pCurrentVertex->id(), pCurrentVertex->weights() );
134  copyOfGenVertex->suggest_barcode( HepMC::barcode(pCurrentVertex) );
135  inputEvtVtxToOutputEvtVtx[pCurrentVertex] = copyOfGenVertex.get();
136  outputEvent->add_vertex( copyOfGenVertex.release() );
137  } //vertex loop
138 
139  // 2. copy the signal process vertex info.
140  if ( inputEvent.signal_process_vertex() ) {
141  outputEvent->set_signal_process_vertex( inputEvtVtxToOutputEvtVtx[inputEvent.signal_process_vertex()] );
142  }
143  else {
144  outputEvent->set_signal_process_vertex( nullptr );
145  }
146  //
147  // 3. create a NEW copy of all particles from inputEvent
148  // taking care to attach them to the appropriate vertex
151  for ( HepMC::GenEvent::particle_const_iterator particleIter = inputEvent.particles_begin();
152  particleIter != inputEvent.particles_end(); ++particleIter ) {
153  const HepMC::GenParticle* currentParticle = *particleIter;
154  if (HepMC::is_simulation_particle(currentParticle)) {
155  continue; // skip particles created by simulation
156  }
157  std::unique_ptr<HepMC::GenParticle> copyOfGenParticle = std::make_unique<HepMC::GenParticle>(*currentParticle);
158  const bool isBeamParticle1(currentParticle == inputEvent.beam_particles().first);
159  const bool isBeamParticle2(currentParticle == inputEvent.beam_particles().second);
160  // There may (will) be particles which had end vertices added by
161  // the simulation (inputEvent). Those vertices will not be copied
162  // to the outputEvent, so we should not try to use them here.
163  const bool shouldAddProdVertex(currentParticle->production_vertex() && inputEvtVtxToOutputEvtVtx[ currentParticle->production_vertex() ]);
164  const bool shouldAddEndVertex(currentParticle->end_vertex() && inputEvtVtxToOutputEvtVtx[ currentParticle->end_vertex() ]);
165  if ( isBeamParticle1 || isBeamParticle2 || shouldAddProdVertex || shouldAddEndVertex ) {
166  HepMC::GenParticle* particleCopy = copyOfGenParticle.release();
167  if ( isBeamParticle1 ) {
168  beam1 = particleCopy;
169  }
170  if ( isBeamParticle2 ) {
171  beam2 = particleCopy;
172  }
173  if ( shouldAddProdVertex || shouldAddEndVertex ) {
174  if ( shouldAddEndVertex ) {
175  inputEvtVtxToOutputEvtVtx[ currentParticle->end_vertex() ]->
176  add_particle_in(particleCopy);
177  }
178  if ( shouldAddProdVertex ) {
179  inputEvtVtxToOutputEvtVtx[ currentParticle->production_vertex() ]->
180  add_particle_out(particleCopy);
181  }
182  }
183  else {
184  ATH_MSG_WARNING ( "Found GenParticle with no production or end vertex! \n" << *currentParticle);
185  }
186  }
187  }
188  outputEvent->set_beam_particles( beam1, beam2 );
189  //
190  // 4. now that vtx/particles are copied, copy weights and random states
191  outputEvent->set_random_states( inputEvent.random_states() );
192  outputEvent->weights() = inputEvent.weights();
193 #endif
194 
195  //Sanity check
196  bool outputProblem(false);
197  for (const auto& particle: *(outputEvent.get())) {
198  if (MC::isStable(particle)) {
199  if (!particle->production_vertex()) {
200  ATH_MSG_ERROR("Stable particle without a production vertex!! " << particle);
201  outputProblem = true;
202  }
203  if (particle->end_vertex()) {
204  ATH_MSG_ERROR("Stable particle with an end vertex!! " << particle);
205  outputProblem = true;
206  }
207  }
208  else if (MC::isDecayed(particle)) {
209  if (!particle->production_vertex()) {
210  ATH_MSG_ERROR("Decayed particle without a production vertex!! " << particle);
211  outputProblem = true;
212  }
213  if (!particle->end_vertex()) {
214  ATH_MSG_ERROR("Decayed particle without an end vertex!! " << particle);
215  outputProblem = true;
216  }
217  }
218  }
219  if (outputProblem) {
220  ATH_MSG_FATAL("Problems in output GenEvent - bailing out.");
221  return StatusCode::FAILURE;
222  }
223 
225  ATH_CHECK(outputMcEventCollection.record(std::make_unique<McEventCollection>()));
226  outputMcEventCollection->push_back(outputEvent.release());
227  if (!outputMcEventCollection.isValid()) {
228  ATH_MSG_ERROR("Could not record output McEventCollection called " << outputMcEventCollection.name() << " in store " << outputMcEventCollection.store() << ".");
229  return StatusCode::FAILURE;
230  }
231 
232  ATH_MSG_DEBUG( "succeded TruthResetAlg ..... " );
233 
234  return StatusCode::SUCCESS;
235 
236 }
TruthResetAlg.h
TruthResetAlg::m_inputMcEventCollection
SG::ReadHandleKey< McEventCollection > m_inputMcEventCollection
Definition: TruthResetAlg.h:26
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
ForwardTracker::beam1
@ beam1
Definition: ForwardTrackerConstants.h:13
GenEvent.h
ForwardTracker::beam2
@ beam2
Definition: ForwardTrackerConstants.h:13
SG::ReadHandle< McEventCollection >
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
SG::VarHandleBase::name
const std::string & name() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:75
GenVertex.h
TruthResetAlg::TruthResetAlg
TruthResetAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TruthResetAlg.cxx:23
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
TruthResetAlg::execute
virtual StatusCode execute() override final
Definition: TruthResetAlg.cxx:42
GeoPrimitives.h
WriteHandle.h
Handle class for recording to StoreGate.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
HepMC::is_simulation_particle
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
Definition: MagicNumbers.h:299
McEventCollection.h
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
HepMC::barcode
int barcode(const T *p)
Definition: Barcode.h:16
SG::VarHandleBase::store
std::string store() const
Return the name of the store holding the object we are proxying.
Definition: StoreGate/src/VarHandleBase.cxx:379
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
HepMC::is_simulation_vertex
bool is_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation (TODO migrate to be based on status).
Definition: MagicNumbers.h:305
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
AthAlgorithm
Definition: AthAlgorithm.h:47
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
SG::WriteHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MagicNumbers.h
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::WriteHandle< McEventCollection >
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
MC::isStable
bool isStable(const T &p)
Definition: HepMCHelpers.h:30
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MC::isDecayed
bool isDecayed(const T &p)
Definition: HepMCHelpers.h:29
ReadHandle.h
Handle class for reading from StoreGate.
HepMCHelpers.h
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
GenParticle
@ GenParticle
Definition: TruthClasses.h:30
TruthResetAlg::initialize
virtual StatusCode initialize() override final
Definition: TruthResetAlg.cxx:32
TruthResetAlg::m_outputMcEventCollection
SG::WriteHandleKey< McEventCollection > m_outputMcEventCollection
Definition: TruthResetAlg.h:27