ATLAS Offline Software
Loading...
Searching...
No Matches
TruthSvc.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// class header
6#include "TruthSvc.h"
7// other ISF_HepMC includes
8// ISF includes
10// Framework
11#include "GaudiKernel/ISvcLocator.h"
13#include "GaudiKernel/SystemOfUnits.h"
14// HepMC includes
17#include "AtlasHepMC/GenEvent.h"
22
23// CLHEP includes
24#include "CLHEP/Geometry/Point3D.h"
25
26// DetectorDescription
28
29#include <sstream>
30
31
32std::vector<HepMC::GenParticlePtr> findChildren(const HepMC::GenParticlePtr& p) {
33 if (!p) return std::vector<HepMC::GenParticlePtr>();
34 const auto& v = p->end_vertex();
35 if (!v) return std::vector<HepMC::GenParticlePtr>();
36 std::vector<HepMC::GenParticlePtr> ret = v->particles_out();
37 if (ret.size()==1) if (ret.at(0)->pdg_id()==p->pdg_id()) ret = findChildren(ret.at(0));
38 return ret;
39}
40
41#undef DEBUG_TRUTHSVC
42
44ISF::TruthSvc::TruthSvc(const std::string& name,ISvcLocator* svc) :
45 base_class(name,svc),
48{
49}
50
53{
54 ATH_MSG_VERBOSE( "initialize()" );
55
56 // Screen output
57 ATH_MSG_DEBUG("--------------------------------------------------------");
58
59 // retrieve BarcodeSvc
60 if ( m_barcodeSvc.retrieve().isFailure() ) {
61 ATH_MSG_FATAL("Could not retrieve BarcodeService. Abort.");
62 return StatusCode::FAILURE;
63 }
64
65 // copy a pointer to the strategy instance to the local
66 // array of pointers (for faster access)
67 ATH_CHECK(m_truthStrategies.retrieve());
68 // Would be nicer to make m_geoStrategies a vector of vectors
69 for ( unsigned short geoID=AtlasDetDescr::fFirstAtlasRegion; geoID<AtlasDetDescr::fNumAtlasRegions; ++geoID) {
70 m_numStrategies[geoID] = 0;
71 for ( const auto &truthStrategy : m_truthStrategies) {
72 if(truthStrategy->appliesToRegion(geoID)) {
73 ++m_numStrategies[geoID];
74 }
75 }
76 }
77 for ( unsigned short geoID=AtlasDetDescr::fFirstAtlasRegion; geoID<AtlasDetDescr::fNumAtlasRegions; ++geoID) {
79 unsigned short curNumStrategies = m_truthStrategies.size();
80 unsigned short nStrat(0);
81 for ( unsigned short i = 0; i < curNumStrategies; ++i) {
82 if(m_truthStrategies[i]->appliesToRegion(geoID)) {
83 m_geoStrategies[geoID][nStrat++] = &(*m_truthStrategies[i]);
84 }
85 }
86
87 // setup whether we want to write end-vertices in this region whenever a truth particle dies
88 // create an end-vertex for all truth particles ending in the current AtlasRegion?
89 bool forceEndVtx = std::find( m_forceEndVtxRegionsVec.begin(),
91 geoID ) != m_forceEndVtxRegionsVec.end();
92 m_forceEndVtx[geoID] = forceEndVtx;
93 }
94 ATH_MSG_VERBOSE("initialize() successful");
95 return StatusCode::SUCCESS;
96}
97
98
101{
102 ATH_MSG_VERBOSE("Finalizing ...");
103 return StatusCode::SUCCESS;
104}
105
106
108StatusCode ISF::TruthSvc::initializeTruthCollection(int largestGeneratedParticleBC, int largestGeneratedVertexBC)
109{
110 ATH_CHECK( m_barcodeSvc->initializeBarcodes(largestGeneratedParticleBC, largestGeneratedVertexBC) );
111 return StatusCode::SUCCESS;
112}
113
115 return StatusCode::SUCCESS;
116}
117
118
120void ISF::TruthSvc::registerTruthIncident( ISF::ITruthIncident& ti, bool saveAllChildren) const {
121
122 const bool passWholeVertex = m_passWholeVertex || saveAllChildren;
123 // pass whole vertex or individual child particles
124 ti.setPassWholeVertices(passWholeVertex);
125
126 // the GeoID
128
129 // check geoID assigned to the TruthIncident
130 if ( !validAtlasRegion(geoID) ) {
131 const auto& position = ti.position();
132 ATH_MSG_ERROR("Unable to register truth incident with unknown SimGeoID="<< geoID
133 << " at position z=" << position.z() << " r=" << position.perp());
134 return;
135 }
136
137 ATH_MSG_VERBOSE( "Registering TruthIncident for SimGeoID="
139
140 // number of child particles
141 const unsigned short numSec = ti.numberOfChildren();
142 if ( m_skipIfNoChildren && (numSec==0) ) {
143 ATH_MSG_VERBOSE( "No child particles present in the TruthIncident,"
144 << " will not record this TruthIncident.");
145 return;
146 }
147
148 // the parent particle -> get its id
149 const int parentID = ti.parentUniqueID();
150 if ( m_skipIfNoParentId && (parentID == HepMC::UNDEFINED_ID) ) {
151 ATH_MSG_VERBOSE( "Parent particle in TruthIncident does not have an id,"
152 << " will not record this TruthIncident.");
153 return;
154 }
155
156 // loop over registered truth strategies for given geoID
157 bool pass = false;
158 for ( unsigned short stratID=0; (!pass) && (stratID<m_numStrategies[geoID]); stratID++) {
159 // (*) test if given TruthIncident passes current strategy
160 pass = m_geoStrategies[geoID][stratID]->pass(ti);
161 }
162
163 if (pass) {
164 ATH_MSG_VERBOSE("At least one TruthStrategy passed.");
165 // at least one truth strategy returned true
166 // -> record incident
167 recordIncidentToMCTruth(ti, passWholeVertex);
168
169 } else {
170 // none of the truth strategies returned true
171 // -> child particles will NOT be added to the TruthEvent collection
172 // attach parent particle end vertex if it gets killed by this interaction
173 if ( m_forceEndVtx[geoID] && !ti.parentSurvivesIncident() ) {
174 ATH_MSG_VERBOSE("No TruthStrategies passed and parent destroyed - create end vertex.");
176
177#ifdef DEBUG_TRUTHSVC
178 const std::string survival = (ti.parentSurvivesIncident()) ? "parent survives" : "parent destroyed";
179 const std::string vtxType = (ti.interactionClassification()==ISF::STD_VTX) ? "Normal" : "Quasi-stable";
180 ATH_MSG_INFO("TruthSvc: " << vtxType << " vertex + " << survival
181 << ", TI Class: " << ti.interactionClassification()
182 << ", ProcessType: " << ti.physicsProcessCategory()
183 << ", ProcessSubType: " << ti.physicsProcessCode());
184#endif
185
186 }
187
188 }
189
190 return;
191}
192
194void ISF::TruthSvc::recordIncidentToMCTruth( ISF::ITruthIncident& ti, bool passWholeVertex) const {
195#ifdef DEBUG_TRUTHSVC
196 ATH_MSG_INFO("Starting recordIncidentToMCTruth(...)");
197#endif
198 int parentBC = ti.parentBarcode();
199
200 if (ti.parentParticle()->end_vertex()) {
201 ATH_MSG_WARNING ("Attempting to record a TruthIncident for a particle which has already decayed!");
202 ATH_MSG_WARNING ("No action will be taken - please fix client code.");
203 return;
204 }
205
206 // record the GenVertex
208 const ISF::InteractionClass_t classification = ti.interactionClassification();
209#ifdef DEBUG_TRUTHSVC
210 const std::string survival = (ti.parentSurvivesIncident()) ? "parent survives" : "parent destroyed";
211 const std::string vtxType = (ti.interactionClassification()==ISF::STD_VTX) ? "Normal" : "Quasi-stable";
212 ATH_MSG_INFO("TruthSvc: " << vtxType << " vertex + " << survival
213 << ", TI Class: " << ti.interactionClassification()
214 << ", ProcessType: " << ti.physicsProcessCategory()
215 << ", ProcessSubType: " << ti.physicsProcessCode());
216#endif
217
218 ATH_MSG_VERBOSE ( "Outgoing particles:" );
219 // update parent barcode and add it to the vertex as outgoing particle
220 int newPrimaryBC = HepMC::UNDEFINED_ID;
221 if (classification == ISF::QS_SURV_VTX) {
222 // Special case when a particle with a pre-defined decay interacts
223 // and survives.
224 // Set the barcode to the next available value below the simulation
225 // barcode offset.
226 newPrimaryBC = m_barcodeSvc->newGeneratedParticle(parentBC);
227 }
228 else {
229 newPrimaryBC = parentBC + HepMC::SIM_REGENERATION_INCREMENT;
230 }
231
232 HepMC::GenParticlePtr parentAfterIncident = ti.parentParticleAfterIncident( newPrimaryBC ); // This call changes ti.parentParticle() output
233 if(parentAfterIncident) {
234 if (classification==ISF::QS_SURV_VTX) {
235 // Special case when a particle with a pre-defined decay
236 // interacts and survives.
237 // As the parentParticleAfterIncident has a pre-defined decay
238 // its status should end in 2, but we should flag that it has
239 // survived an interaction.
240 if (!MC::isDecayed(parentAfterIncident)) {
241 ATH_MSG_WARNING ( "recordIncidentToMCTruth - check parentAfterIncident: " << parentAfterIncident );
242 }
243 }
244 vtxFromTI->add_particle_out( parentAfterIncident );
245 HepMC::suggest_barcode( parentAfterIncident, newPrimaryBC ); // TODO check this works correctly
246 // NB For ISFTruthIncident the m_parent ISFParticle still needs
247 // its id and particleLink properties to be properly updated at
248 // this point.
249 ATH_MSG_VERBOSE ( "Parent After Incident: " << parentAfterIncident << ", barcode: " << HepMC::barcode(parentAfterIncident));
250 }
251
252 const bool isQuasiStableVertex = (classification == ISF::QS_PREDEF_VTX); // QS_DEST_VTX and QS_SURV_VTX should be treated as normal from now on.
253 // add child particles to the vertex
254 const unsigned short numSec = ti.numberOfChildren();
255 for ( unsigned short i=0; i<numSec; ++i) {
256 bool writeOutChild = isQuasiStableVertex || passWholeVertex || ti.childPassedFilters(i);
257 if (writeOutChild) {
258 HepMC::GenParticlePtr p = nullptr;
259 // generate a new barcode for the child particle
260 int secondaryParticleBC = (isQuasiStableVertex) ?
261 m_barcodeSvc->newGeneratedParticle(parentBC) : m_barcodeSvc->newSecondaryParticle(parentBC); // TODO replace m_barcodeSvc
262 if ( secondaryParticleBC == HepMC::UNDEFINED_ID) {
264 ATH_MSG_WARNING("Unable to generate new Secondary Particle Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
265 else {
266 ATH_MSG_ERROR("Unable to generate new Secondary Particle Barcode. Aborting");
267 abort();
268 }
269 }
270 p = ti.childParticle( i, secondaryParticleBC ); // potentially overrides secondaryParticleBC
271 if (p) {
272 // add particle to vertex
273 vtxFromTI->add_particle_out( p);
274 int secondaryParticleBCFromTI = ti.childBarcode(i);
275 HepMC::suggest_barcode( p, secondaryParticleBCFromTI ? secondaryParticleBCFromTI : secondaryParticleBC );
276 // NB For ISFTruthIncident the current child ISFParticle still needs
277 // its id and particleLink properties to be properly updated at
278 // this point.
279 }
280 ATH_MSG_VERBOSE ( "Writing out " << i << "th child particle: " << p << ", barcode: " << HepMC::barcode(p));
281 } // <-- if write out child particle
282 else {
283 ATH_MSG_VERBOSE ( "Not writing out " << i << "th child particle." );
284 }
285
286 } // <-- loop over all child particles
287 ATH_MSG_VERBOSE("--------------------------------------------------------");
288}
289
292
293 int processCode = ti.physicsProcessCode();
294 int parentBC = ti.parentBarcode();
295
296 std::vector<double> weights(1);
297 int primaryBC = parentBC % HepMC::SIM_REGENERATION_INCREMENT;
298 weights[0] = static_cast<double>( primaryBC ); // FIXME vertex weights should not be used to encode other info.
299
300 // Check for a previous end vertex on this particle. If one existed, then we should put down next to this
301 // a new copy of the particle. This is the agreed upon version of the quasi-stable particle truth, where
302 // the vertex at which we start Q-S simulation no longer conserves energy, but we keep both copies of the
303 // truth particles
305 if (!parent) {
306 ATH_MSG_ERROR("Unable to write particle interaction to MC truth due to missing parent HepMC::GenParticle instance");
307 abort();
308 }
309 HepMC::GenEvent *mcEvent = parent->parent_event();
310 if (!mcEvent) {
311 ATH_MSG_ERROR("Unable to write particle interaction to MC truth due to missing parent HepMC::GenEvent instance");
312 abort();
313 }
314
315 // generate vertex
316 int vtxbcode = m_barcodeSvc->newSimulationVertex(); // TODO replace barcodeSvc
317 if ( vtxbcode == HepMC::UNDEFINED_ID) {
319 ATH_MSG_WARNING("Unable to generate new Truth Vertex Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
320 } else {
321 ATH_MSG_ERROR("Unable to generate new Truth Vertex Barcode. Aborting");
322 abort();
323 }
324 }
325 const int vtxStatus = 1000 + static_cast<int>(processCode) + HepMC::SIM_STATUS_THRESHOLD;
326 auto newVtx = HepMC::newGenVertexPtr( ti.position(),vtxStatus);
327
328 if (parent->end_vertex()){
329 ATH_MSG_ERROR ("createGVfromTI: Parent particle found with an end vertex attached. This should not happen!");
330 ATH_MSG_ERROR ("createGVfromTI: Parent 1: " << parent << ", barcode: " << HepMC::barcode(parent));
331 ATH_MSG_ERROR ( "createGVfromTI: parent->end_vertex(): " << parent->end_vertex() << ", barcode: " << HepMC::barcode(parent->end_vertex()) );
332 abort();
333 } else { // Normal simulation
334#ifdef DEBUG_TRUTHSVC
335 ATH_MSG_VERBOSE ("createGVfromTI Parent 1: " << parent << ", barcode: " << HepMC::barcode(parent));
336#endif
337 // add parent particle to newVtx
338 newVtx->add_particle_in( parent );
339#ifdef DEBUG_TRUTHSVC
340 ATH_MSG_VERBOSE ( "createGVfromTI End Vertex representing process: " << processCode << ", for parent with barcode "<<parentBC<<". Creating." );
341 ATH_MSG_VERBOSE ( "createGVfromTI Parent 2: " << parent << ", barcode: " << HepMC::barcode(parent));
342#endif
343 mcEvent->add_vertex(newVtx);
344 HepMC::suggest_barcode( newVtx, vtxbcode );
345 newVtx->add_attribute(HepMCStr::weights,std::make_shared<HepMC3::VectorDoubleAttribute>(weights));
346 }
347
348 return parent->end_vertex();
349}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool validAtlasRegion(AtlasDetDescr::AtlasRegion region)
Check a given AtlasRegion for its validity.
Definition AtlasRegion.h:40
ATLAS-specific HepMC functions.
std::vector< HepMC::GenParticlePtr > findChildren(const HepMC::GenParticlePtr &p)
Definition TruthSvc.cxx:32
static const char * getName(int region)
ISF interface class for TruthIncidents.
virtual int physicsProcessCategory() const =0
Return category of the physics process represented by the truth incident (eg hadronic,...
virtual int physicsProcessCode() const =0
Return specific physics process code of the truth incident (eg ionisation, bremsstrahlung,...
virtual ISF::InteractionClass_t interactionClassification() const
The interaction classifications are described as follows: STD_VTX: interaction of a particle without ...
virtual int parentBarcode()=0
Return the barcode of the parent particle.
virtual HepMC::GenParticlePtr parentParticle()=0
Return the parent particle as a HepMC particle type (only called for particles that will enter the He...
bool childPassedFilters(unsigned short index) const
Should a particular child be written out to the GenEvent.
virtual HepMC::GenParticlePtr childParticle(unsigned short index, int bc=HepMC::UNDEFINED_ID)=0
Return the i-th child as a HepMC particle type and assign the given Barcode to the simulator particle...
unsigned short numberOfChildren() const
Return total number of child particles.
AtlasDetDescr::AtlasRegion geoID()
Return the SimGeoID corresponding to the vertex of the truth incident.
virtual int parentUniqueID()=0
Return the unique ID of the parent particle.
virtual HepMC::GenParticlePtr parentParticleAfterIncident(int newBC)=0
Return the parent particle after the TruthIncident vertex (and assign a new barcode to it).
void setPassWholeVertices(bool passWholeVertex)
Set whether this TruthIncident should pass the vertex as a whole or individual children.
virtual bool parentSurvivesIncident() const =0
Return a boolean whether or not the parent particle survives the incident.
virtual int childBarcode(unsigned short index) const =0
Return the barcode of the i-th child particle (if defined as part of the TruthIncident) otherwise ret...
virtual const HepMC::FourVector & position() const =0
Return HepMC position of the truth vertex.
StatusCode initializeTruthCollection(int largestGeneratedParticleBC=0, int largestGeneratedVertexBC=0) override
Initialize the Truth Svc at the beginning of each event.
Definition TruthSvc.cxx:108
Gaudi::Property< bool > m_passWholeVertex
Definition TruthSvc.h:96
ServiceHandle< Barcode::IBarcodeSvc > m_barcodeSvc
The Barcode service.
Definition TruthSvc.h:83
void registerTruthIncident(ITruthIncident &truthincident, bool saveAllChildren=false) const override
Register a truth incident.
Definition TruthSvc.cxx:120
unsigned short m_numStrategies[AtlasDetDescr::fNumAtlasRegions]
Definition TruthSvc.h:89
HepMC::GenVertexPtr createGenVertexFromTruthIncident(ITruthIncident &truthincident) const
Record and end vertex to the MC Truth for the parent particle.
Definition TruthSvc.cxx:291
Gaudi::Property< std::vector< unsigned int > > m_forceEndVtxRegionsVec
property containing AtlasRegions for which
Definition TruthSvc.h:98
StatusCode finalize() override
Athena algorithm's interface method finalize().
Definition TruthSvc.cxx:100
StatusCode releaseEvent() override
Finalize the Truth Svc at the end of each event.
Definition TruthSvc.cxx:114
TruthSvc(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition TruthSvc.cxx:44
void recordIncidentToMCTruth(ITruthIncident &truthincident, bool passWholeVertex) const
Record the given truth incident to the MC Truth.
Definition TruthSvc.cxx:194
Gaudi::Property< bool > m_skipIfNoChildren
MCTruth steering.
Definition TruthSvc.h:92
ITruthStrategy ** m_geoStrategies[AtlasDetDescr::fNumAtlasRegions]
for faster access: using an internal pointer to the actual ITruthStrategy instances
Definition TruthSvc.h:88
ToolHandleArray< ITruthStrategy > m_truthStrategies
the truth strategies applied (as AthenaToolHandle Array)
Definition TruthSvc.h:86
Gaudi::Property< bool > m_ignoreUndefinedBarcodes
do/don't abort if retrieve an undefined barcode
Definition TruthSvc.h:94
std::array< bool, AtlasDetDescr::fNumAtlasRegions > m_forceEndVtx
attach end vertex to
Definition TruthSvc.h:100
StatusCode initialize() override
Athena algorithm's interface method initialize().
Definition TruthSvc.cxx:52
Gaudi::Property< bool > m_skipIfNoParentId
do not record if parentId == HepMC::UNDEFINED_ID
Definition TruthSvc.h:93
AtlasRegion
A simple enum of ATLAS regions and sub-detectors.
Definition AtlasRegion.h:21
const std::string weights
int barcode(const T *p)
Definition Barcode.h:15
constexpr int UNDEFINED_ID
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
bool suggest_barcode(T &p, int i)
Definition GenEvent.h:607
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
Definition GenVertex.h:25
HepMC3::GenVertexPtr GenVertexPtr
Definition GenVertex.h:23
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
constexpr int SIM_REGENERATION_INCREMENT
Constant defining the barcode threshold for regenerated particles, i.e. particles surviving an intera...
InteractionClass_t
The interaction classifications are described as follows: STD_VTX: interaction of a particle without ...
@ QS_SURV_VTX
@ QS_PREDEF_VTX
bool isDecayed(const T &p)
Identify if the particle decayed.