ATLAS Offline Software
Loading...
Searching...
No Matches
TruthClosureCheck.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "TruthClosureCheck.h"
6//
11
12
14
15#include "CLHEP/Vector/LorentzVector.h"
16#include "CLHEP/Units/SystemOfUnits.h"
17//
18#include "CLHEP/Geometry/Point3D.h"
20#include <climits>
21
22//----------------------------------------------------
24 //----------------------------------------------------
25
28 return StatusCode::SUCCESS;
29
30}
31
32
33StatusCode TruthClosureCheck::sanityCheck(const HepMC::GenEvent& event) const {
34 //Sanity check
35 bool resetProblem(false);
36 for (const auto& particle: event) {
37 if (MC::isStable(particle)) {
38 if (!particle->production_vertex()) {
39 ATH_MSG_ERROR("Stable particle without a production vertex!! " << particle);
40 resetProblem = true;
41 }
42 if (!m_postSimulation && particle->end_vertex()) {
43 ATH_MSG_ERROR("Stable particle with an end vertex!! " << particle);
44 resetProblem = true;
45 }
46 }
47 else if (MC::isDecayed(particle)) {
48 if (!particle->production_vertex()) {
49 ATH_MSG_ERROR("Decayed particle without a production vertex!! " << particle);
50 resetProblem = true;
51 }
52 if (!particle->end_vertex()) {
53 ATH_MSG_ERROR("Decayed particle without an end vertex!! " << particle);
54 resetProblem = true;
55 }
56 }
57 }
58 if (resetProblem) {
59 return StatusCode::FAILURE;
60 }
61
62 return StatusCode::SUCCESS;
63}
64
66 const HepMC::ConstGenVertexPtr& resetVertex) const
67{
68 ATH_MSG_INFO("----------------------------------");
69 ATH_MSG_INFO("Original Vertex:");
70 ATH_MSG_INFO( origVertex );
71 ATH_MSG_INFO("Particles In:");
72 for (const auto& originalPartIn: origVertex->particles_in()) ATH_MSG_INFO( originalPartIn );
73 ATH_MSG_INFO("Particles Out:");
74 for (const auto& originalPartOut: origVertex->particles_out()) ATH_MSG_INFO( originalPartOut );
75 ATH_MSG_INFO("----------------------------------");
76 ATH_MSG_INFO("Reset Vertex:");
77 ATH_MSG_INFO( resetVertex );
78 ATH_MSG_INFO("Particles In:");
79 for (const auto& resetPartIn: resetVertex->particles_in()) ATH_MSG_INFO( resetPartIn );
80 ATH_MSG_INFO("Particles Out:");
81 for (const auto& resetPartOut: resetVertex->particles_out()) ATH_MSG_INFO( resetPartOut );
82 ATH_MSG_INFO("----------------------------------");
83 return;
84}
85
87 const HepMC::ConstGenVertexPtr& resetVertex) const
88{
89 if (!origVertex && !resetVertex) return StatusCode::SUCCESS;
90 if (!origVertex || !resetVertex) return StatusCode::FAILURE;
91 bool pass{true};
92
93 if (HepMC::barcode(origVertex) != HepMC::barcode(resetVertex)) { // FIXME barcode-based
94 ATH_MSG_ERROR ("vertex barcode differs! Original: "<<HepMC::barcode(origVertex)<<", Reset: "<<HepMC::barcode(resetVertex));
95 pass = false;
96 }
97 if (origVertex->position() != resetVertex->position()) {
98 const HepMC::FourVector& oP = origVertex->position();
99 const HepMC::FourVector& rP = resetVertex->position();
100 ATH_MSG_ERROR("vertex position differs! Original: ("<<oP.x()<<","<<oP.y()<<","<<oP.z()<<","<<oP.t()<<"), Reset: ("<<rP.x()<<","<<rP.y()<<","<<rP.z()<<","<<rP.t()<<")");
101 pass = false;
102 }
103 if (origVertex->particles_in().size() != resetVertex->particles_in().size() ) {
104 ATH_MSG_ERROR ("particles_in_size differs! Original: "<<origVertex->particles_in().size()<<", Reset: "<<resetVertex->particles_in().size());
105 pass = false;
106 }
107 if (origVertex->particles_out().size() != resetVertex->particles_out().size() ) {
108 ATH_MSG_ERROR ("particles_out_size differs! Original: "<<origVertex->particles_out().size()<<", Reset: "<<resetVertex->particles_out().size());
109 pass = false;
110 }
111 std::vector<HepMC::ConstGenParticlePtr> OriginalListOfParticlesIn = origVertex->particles_in();
112 std::vector<HepMC::ConstGenParticlePtr> ResetListOfParticlesIn = resetVertex->particles_in();
113 for ( std::vector<HepMC::ConstGenParticlePtr>::iterator originalPartInIter(OriginalListOfParticlesIn.begin()),resetPartInIter(ResetListOfParticlesIn.begin());
114 originalPartInIter != OriginalListOfParticlesIn.end() && resetPartInIter != ResetListOfParticlesIn.end();
115 ++originalPartInIter, ++resetPartInIter
116 ) {
117 if (compareGenParticle(*originalPartInIter,*resetPartInIter).isFailure()) {
118 ATH_MSG_ERROR ( "input particle properties differ!" );
119 pass &= false;
120 }
121 ATH_MSG_VERBOSE ( "particles match!" );
122 }
123
124
125 std::vector<HepMC::ConstGenParticlePtr> OriginalListOfParticlesOut = origVertex->particles_out();
126 std::vector<HepMC::ConstGenParticlePtr> ResetListOfParticlesOut = resetVertex->particles_out();
127 //AV: please remember that the best quantities to compare particles are physical quantities.
128 std::sort(OriginalListOfParticlesOut.begin(), OriginalListOfParticlesOut.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
129 std::sort(ResetListOfParticlesOut.begin(), ResetListOfParticlesOut.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
130
131 for ( std::vector<HepMC::ConstGenParticlePtr>::iterator originalPartOutIter(OriginalListOfParticlesOut.begin()), resetPartOutIter(ResetListOfParticlesOut.begin());
132 originalPartOutIter != OriginalListOfParticlesOut.end() && resetPartOutIter != ResetListOfParticlesOut.end();
133 ++originalPartOutIter, ++resetPartOutIter
134 ) {
135 if (compareGenParticle(*originalPartOutIter,*resetPartOutIter).isFailure()) {
136 ATH_MSG_ERROR ( "output particle properties differ!" );
137 pass &= false;
138 }
139 ATH_MSG_VERBOSE ( "particles match!" );
140 }
141 if(!pass) { return StatusCode::FAILURE; }
142 return StatusCode::SUCCESS;
143}
144
145
146
147
149 const HepMC::FourVector& resetMomenta) const
150{
151 bool pass{true};
152 if (m_compareMomenta) {
153 if (m_momentaLimit<std::abs(origMomenta.px()-resetMomenta.px())) {
154 pass &= false;
155 }
156 if (m_momentaLimit<std::abs(origMomenta.py()-resetMomenta.py())) {
157 pass &= false;
158 }
159 if (m_momentaLimit<std::abs(origMomenta.pz()-resetMomenta.pz())) {
160 pass &= false;
161 }
162 if (m_momentaLimit<std::abs(origMomenta.e()-resetMomenta.e())) {
163 pass &= false;
164 }
165 if(origMomenta != resetMomenta) {
166 ATH_MSG_ERROR ("Exact momenta agreement check failed.");
167 pass &= false;
168 }
169 }
170 if(!pass) { return StatusCode::FAILURE; }
171 return StatusCode::SUCCESS;
172}
173
175 const HepMC::ConstGenParticlePtr& resetParticle) const
176{
177 if (!origParticle && !resetParticle) return StatusCode::SUCCESS;
178 if (!origParticle || !resetParticle) return StatusCode::FAILURE;
179
180 bool pass{true};
181 if (HepMC::barcode(origParticle) != HepMC::barcode(resetParticle)) { // FIXME barcode-based
182 ATH_MSG_ERROR ("particle barcode differs! Original: "<<HepMC::barcode(origParticle)<<", Reset: "<<HepMC::barcode(resetParticle));
183 pass &= false;
184 }
185 if (origParticle->status() != resetParticle->status()) {
186 ATH_MSG_ERROR ("particle status differs! Original: "<<origParticle->status()<<", Reset: "<<resetParticle->status());
187 pass &= false;
188 }
189 if (origParticle->pdg_id() != resetParticle->pdg_id()) {
190 ATH_MSG_ERROR ("particle pdg_id differs! Original: "<<origParticle->pdg_id()<<", Reset: "<<resetParticle->pdg_id());
191 pass &= false;
192 }
193 if (compareMomenta(origParticle->momentum(), resetParticle->momentum()).isFailure()) {
194 const HepMC::FourVector& oM = origParticle->momentum();
195 const HepMC::FourVector& rM = resetParticle->momentum();
196 ATH_MSG_DEBUG("particle momentum differs! Original: ("<<oM.x()<<","<<oM.y()<<","<<oM.z()<<","<<oM.t()<<"), Reset: ("<<rM.x()<<","<<rM.y()<<","<<rM.z()<<","<<rM.t()<<")");
197 pass &= false;
198 }
199 if(!pass) { return StatusCode::FAILURE; }
200 return StatusCode::SUCCESS;
201}
202
203
204//-------------------------------------------------
205StatusCode TruthClosureCheck::execute(const EventContext& ctx) const {
206 //-------------------------------------------------
207
208 ATH_MSG_DEBUG( " execute..... " );
210 if (!originalMcEventCollection.isValid()) {
211 ATH_MSG_ERROR("Could not find original McEventCollection called " << originalMcEventCollection.name() << " in store " << originalMcEventCollection.store() << ".");
212 return StatusCode::FAILURE;
213 }
214 const HepMC::GenEvent& originalEvent(**(originalMcEventCollection->begin()));
215
216 if (sanityCheck(originalEvent).isFailure()) {
217 ATH_MSG_FATAL("Problems in original GenEvent - bailing out.");
218 return StatusCode::FAILURE;
219 }
220
222 if (!resetMcEventCollection.isValid()) {
223 ATH_MSG_ERROR("Could not find reset McEventCollection called " << resetMcEventCollection.name() << " in store " << resetMcEventCollection.store() << ".");
224 return StatusCode::FAILURE;
225 }
226 const HepMC::GenEvent& resetEvent(**(resetMcEventCollection->begin()));
227
228 if (sanityCheck(resetEvent).isFailure()) {
229 ATH_MSG_FATAL("Problems in reset GenEvent - bailing out.");
230 return StatusCode::FAILURE;
231 }
232
233 if (originalEvent.event_number() != resetEvent.event_number() ) {
234 ATH_MSG_ERROR ("event_number differs! Original: "<<originalEvent.event_number()<<", Reset: "<<resetEvent.event_number());
235 }
236
237 if (HepMC::signal_process_id(originalEvent) != HepMC::signal_process_id(resetEvent) ) {
238 ATH_MSG_ERROR ("signal_process_id differs! Original: "<<HepMC::signal_process_id(originalEvent)<<", Reset: "<<HepMC::signal_process_id(resetEvent));
239 }
241 std::vector<HepMC::ConstGenParticlePtr> OriginalBeams = originalEvent.beams();
242 std::vector<HepMC::ConstGenParticlePtr> ResetBeams = resetEvent.beams();
243
244 for ( std::vector<HepMC::ConstGenParticlePtr>::iterator originalBeamIter(OriginalBeams.begin()), resetBeamIter(ResetBeams.begin());
245 originalBeamIter != OriginalBeams.end() && resetBeamIter != ResetBeams.end();
246 ++originalBeamIter, ++resetBeamIter
247 ) {
248 if (compareGenParticle(*originalBeamIter,*resetBeamIter).isFailure()) {
249 ATH_MSG_ERROR ( "Beam particle properties differ!" );
250 }
252 if (originalEvent.particles().size() != resetEvent.particles().size() ) {
253 ATH_MSG_ERROR ("particles_size differs! Original: "<<originalEvent.particles().size()<<", Reset: "<<resetEvent.particles().size());
254 }
255
256 if (originalEvent.vertices().size() != resetEvent.vertices().size() ) {
257 ATH_MSG_ERROR ("vertices_size differs! Original: "<<originalEvent.vertices().size()<<", Reset: "<<resetEvent.vertices().size());
258 }
259 }
260
261 //loop over vertices in Background GenEvent
262 std::vector<HepMC::ConstGenVertexPtr> OriginalListOfVertices = originalEvent.vertices();
263 std::vector<HepMC::ConstGenVertexPtr> ResetListOfVertices = resetEvent.vertices();
264
265 for( std::vector<HepMC::ConstGenVertexPtr>::iterator origVertexIter(OriginalListOfVertices.begin()),resetVertexIter(ResetListOfVertices.begin());
266 origVertexIter != OriginalListOfVertices.end() && resetVertexIter != ResetListOfVertices.end();
267 ++origVertexIter, ++resetVertexIter
268 ) {
269 if (compareGenVertex(*origVertexIter,*resetVertexIter).isFailure()) {
270 ATH_MSG_ERROR ( "vertices differ!" );
271 printGenVertex(*origVertexIter,*resetVertexIter);
272 }
273 }
274 ATH_MSG_INFO( "Completed Truth reset closure check ..... " );
275
276 return StatusCode::SUCCESS;
277
278}
#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_DEBUG(x)
ATLAS-specific HepMC functions.
static Double_t a
Handle class for reading from StoreGate.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
std::string store() const
Return the name of the store holding the object we are proxying.
const std::string & name() const
Return the StoreGate ID for the referenced object.
StatusCode compareGenVertex(const HepMC::ConstGenVertexPtr &origVertex, const HepMC::ConstGenVertexPtr &resetVertex) const
SG::ReadHandleKey< McEventCollection > m_originalMcEventCollection
virtual StatusCode execute(const EventContext &ctx) const override final
StatusCode compareMomenta(const HepMC::FourVector &origMomenta, const HepMC::FourVector &resetMomenta) const
void printGenVertex(const HepMC::ConstGenVertexPtr &origVertex, const HepMC::ConstGenVertexPtr &resetVertex) const
StatusCode sanityCheck(const HepMC::GenEvent &event) const
virtual StatusCode initialize() override final
Gaudi::Property< bool > m_compareMomenta
StatusCode compareGenParticle(const HepMC::ConstGenParticlePtr &origParticle, const HepMC::ConstGenParticlePtr &resetParticle) const
Gaudi::Property< bool > m_postSimulation
SG::ReadHandleKey< McEventCollection > m_resetMcEventCollection
int signal_process_id(const GenEvent &evt)
Definition GenEvent.h:572
int barcode(const T *p)
Definition Barcode.h:15
HepMC3::FourVector FourVector
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
HepMC3::ConstGenVertexPtr ConstGenVertexPtr
Definition GenVertex.h:24
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
bool isDecayed(const T &p)
Identify if the particle decayed.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.