ATLAS Offline Software
Loading...
Searching...
No Matches
GMTreeBrowser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6// GMTreeBrowser.cxx, (c) ATLAS Detector software
8
10
11#include "GeoModelHelpers/GeoShapeSorter.h"
12#include "GeoModelHelpers/TransformSorter.h"
13#include "GeoModelHelpers/GeoMaterialSorter.h"
14#include "GeoModelHelpers/getChildNodesWithTrf.h"
15
16// GeoModel includes
17#include <cmath>
18#include <iomanip>
19#include <iostream>
20
21#include "GeoModelKernel/GeoBox.h"
22#include "GeoModelKernel/GeoCons.h"
23#include "GeoModelKernel/GeoPara.h"
24#include "GeoModelKernel/GeoPcon.h"
25#include "GeoModelKernel/GeoPgon.h"
26#include "GeoModelKernel/GeoShape.h"
27#include "GeoModelKernel/GeoShapeIntersection.h"
28#include "GeoModelKernel/GeoShapeShift.h"
29#include "GeoModelKernel/GeoShapeSubtraction.h"
30#include "GeoModelKernel/GeoShapeUnion.h"
31#include "GeoModelKernel/GeoSimplePolygonBrep.h"
32#include "GeoModelKernel/GeoTrap.h"
33#include "GeoModelKernel/GeoTrd.h"
34#include "GeoModelKernel/GeoTube.h"
35#include "GeoModelKernel/GeoTubs.h"
36#include "GeoModelKernel/GeoVPhysVol.h"
39
40#if defined(FLATTEN)
41 // We compile this package with optimization, even in debug builds; otherwise,
42 // the heavy use of Eigen makes it too slow. However, from here we may call
43 // to out-of-line Eigen code that is linked from other DSOs; in that case,
44 // it would not be optimized. Avoid this by forcing all Eigen code
45 // to be inlined here if possible.
47#endif
48int Trk::GMTreeBrowser::compareGeoVolumes(const GeoVPhysVol* gv1,
49 const GeoVPhysVol* gv2,
50 double tolerance, bool dumpInfo,
51 int level) const {
52
53 int diff = 0;
54
55 // CASE 1: naming difference
56 if (gv1->getLogVol()->getName() != gv2->getLogVol()->getName()) {
57 diff = 1000 * level + 1;
58 if (dumpInfo) {
59 std::cout << "CASE 1: names differ at level:" << level << ":"
60 << gv1->getLogVol()->getName() << ":"
61 << gv2->getLogVol()->getName() << std::endl;
62 }
63 // else return m_diff; // the naming change is harmless and can mask
64 // more serious problems, continue the loop
65 }
66 // CASE 2: material type difference
67 if (GeoMaterialSorter{}.compare(gv1->getLogVol()->getMaterial(),
68 gv2->getLogVol()->getMaterial()) != 0) {
69 diff = 1000 * level + 2;
70 if (dumpInfo) {
71 std::cout << "CASE 2: material types differ for volume:"
72 << gv1->getLogVol()->getName() << ":at level:" << level
73 << ":" << gv1->getLogVol()->getMaterial()->getName()
74 << ":differs from:"
75 << gv2->getLogVol()->getMaterial()->getName()
76 << std::endl;
77 } else
78 return diff;
79 }
80 // CASE 3: difference in shape definition
81 if (!compareShapes(gv1->getLogVol()->getShape(),
82 gv2->getLogVol()->getShape(), tolerance)) {
83 diff = 1000 * level + 3;
84 if (dumpInfo) {
85 std::cout << "CASE 4: shape definition differ at level:" << level
86 << std::endl;
87 } else
88 return diff;
89 }
90 unsigned int nChild1 = gv1->getNChildVols();
91 // CASE 4: difference in the number of child volumes
92 if (nChild1 != gv2->getNChildVols()) {
93 diff = 1000 * level + 4;
94 if (dumpInfo) {
95 std::cout << "CASE 5: number of child vols differ at level:"
96 << level << ":volume name:" << gv1->getLogVol()->getName()
97 << ":nChildVols:" << gv1->getNChildVols()
98 << ":nChildVols ref:" << gv2->getNChildVols()
99 << std::endl;
100 } else
101 return diff;
102 }
103
104 // CASE 6 & 7: transform to child difference
105 // We used to do this with something like
106 // for (unsigned int ic = 0; ic < gv1->getNChildVols(); ic++) {
107 // GeoTrf::Transform3D transf1 = gv1->getXToChildVol(ic);
108 // const GeoVPhysVol* cv1 = &(*(gv1->getChildVol(ic)));
109 //
110 // But getXToChildVol and getChildVol need to walk all the children
111 // until they reach the given index. So this would be N^2,
112 // and each time we repeat it for the transform and the volume.
113 // Better to use geoGetVolumes so that we only need do the walk once.
114 // And examination of profiling data shows that almost never
115 // fail a comparison from here on, so we'll almost always be examining
116 // all children anyway.
117 // (It would be even better if GeoVPhysVol has some sort of iterator
118 // interface. Maybe we can use a generator with C++23...)
119
120
121 const auto children1 = getChildrenWithRef(gv1);
122 const auto children2 = getChildrenWithRef(gv2);
123
124 if (children1.size() != children2.size()) {
125 diff = 1000 * level + 5;
126 if (dumpInfo) {
127 std::cout << "CASE 5: number of child vols differ at level:"
128 << level << ":volume name:" << gv1->getLogVol()->getName()
129 << ":nChildVols:" << gv1->getNChildVols()
130 << ":nChildVols ref:" << gv2->getNChildVols()
131 << std::endl;
132 }
133 return diff;
134 }
135
136 for (std::size_t ic = 0; ic < children1.size(); ++ic) {
137 const auto& child1 = children1.at(ic);
138 const auto& child2 = children2.at(ic);
139
140 if (child1.nCopies != child2.nCopies) {
141 diff = 1000 * level + 6;
142 if (dumpInfo) {
143 std::cout << "CASE 5: number of child vols differ at level:"
144 << level << ":volume name:" << child1.volume->getLogVol()->getName()
145 << std::endl;
146 }
147 return diff;
148 }
149 if (child1.nCopies > 1 &&
150 GeoTrf::TransformSorter{}.compare(child1.inductionRule, child2.inductionRule) !=0) {
151 diff = 1000 * level + 7;
152 if (dumpInfo) {
153 std::cout << "CASE 7: Replication rule is different at level:"
154 << level << ":volume name:" << child1.volume->getLogVol()->getName()
155 << std::endl;
156 }
157 return diff;
158 }
159 if (GeoTrf::TransformSorter{}.compare(child1.transform, child2.transform) != 0) {
160 diff = 1000 * level + 7;
161 if (dumpInfo) {
162 std::cout << "CASE 7: Volume transform is different:"
163 << level << ":volume name:" << child1.volume->getLogVol()->getName()
164 << std::endl;
165 }
166 return diff;
167 }
168 int child_comp = compareGeoVolumes(child1.volume, child2.volume, tolerance, dumpInfo, level + 1);
169 if (child_comp != 0) {
170 return child_comp;
171 }
172 }
173
174 return diff;
175}
176
177#if defined(FLATTEN)
178 // We compile this package with optimization, even in debug builds; otherwise,
179 // the heavy use of Eigen makes it too slow. However, from here we may call
180 // to out-of-line Eigen code that is linked from other DSOs; in that case,
181 // it would not be optimized. Avoid this by forcing all Eigen code
182 // to be inlined here if possible.
184#endif
185bool Trk::GMTreeBrowser::compareShapes(const GeoShape* sh1, const GeoShape* sh2,
186 double /*tol*/) const {
187 return GeoShapeSorter{}.compare(sh1, sh2) == 0;
188}
189
190bool Trk::GMTreeBrowser::findNamePattern(const GeoVPhysVol* gv,
191 std::string_view name) const {
192
193 if (gv->getLogVol()->getName().find(name) != std::string::npos)
194 return true;
195
196 for (unsigned int ic = 0; ic < gv->getNChildVols(); ic++) {
197 const GeoVPhysVol* cv = gv->getChildVol(ic);
198 if (findNamePattern(cv, name))
199 return true;
200 }
201
202 return false;
203}
204
205namespace {
206
207class GeoFindTopName : public GeoNodeAction
208{
209public:
210 explicit GeoFindTopName (const std::string_view name) : m_name (name)
211 {
212 }
213 virtual void handlePhysVol (const GeoPhysVol* v) override
214 { handleVol (v); }
215 virtual void handleFullPhysVol (const GeoFullPhysVol* v) override
216 { handleVol (v); }
217 const GeoVPhysVol* topName() const { return m_topName; }
218private:
219 void handleVol (const GeoVPhysVol* v)
220 {
221 const GeoLogVol* clv = v->getLogVol();
222 if (clv && clv->getName().find(m_name) != std::string::npos) {
223 m_topName = v->getParent();
224 this->terminate();
225 }
226 }
227 const std::string_view m_name;
228 const GeoVPhysVol* m_topName = nullptr;
229};
230
231}
232
234 const GeoVPhysVol* gv, std::string_view name) {
235
236 GeoFindTopName topName (name);
237 gv->exec (&topName);
238 return topName.topName();
239}
240
241bool Trk::GMTreeBrowser::identity_check(GeoTrf::RotationMatrix3D rotation,
242 double tol) {
243
244 if (std::abs(rotation(0, 1)) > tol)
245 return false;
246 if (std::abs(rotation(0, 2)) > tol)
247 return false;
248 if (std::abs(rotation(1, 2)) > tol)
249 return false;
250
251 return true;
252}
253
254void Trk::GMTreeBrowser::printTranslationDiff(GeoTrf::Transform3D tr_test,
255 GeoTrf::Transform3D tr_ref,
256 double tolerance) {
257 std::ios oldState(nullptr);
258 oldState.copyfmt(std::cout);
259 //
260 std::cout << std::fixed << std::setprecision(4);
261 std::cout << "test translation:x:y:z:" << tr_test.translation().x() << ":"
262 << tr_test.translation().y() << ":" << tr_test.translation().z()
263 << std::endl;
264 std::cout << " ref translation:x:y:z:" << tr_ref.translation().x() << ":"
265 << tr_ref.translation().y() << ":" << tr_ref.translation().z()
266 << std::endl;
267 std::cout << " absolute shift :"
268 << (tr_test.translation() - tr_ref.translation()).norm()
269 << ": to be compared with the tolerance limit:" << tolerance
270 << std::endl;
271 std::cout.copyfmt(oldState); // restore ostream state
272}
273
274void Trk::GMTreeBrowser::printRotationDiff(const GeoTrf::Transform3D& tr_test,
275 const GeoTrf::Transform3D& tr_ref,
276 double tolerance) {
277
278 GeoTrf::RotationMatrix3D rotest = tr_test.rotation();
279 GeoTrf::RotationMatrix3D rotref = tr_ref.rotation();
280 GeoTrf::RotationMatrix3D rotid = rotest * rotref.inverse();
281 std::ios oldState(nullptr);
282 oldState.copyfmt(std::cout);
283
284 std::cout << std::fixed << std::setprecision(4);
285 std::cout << "test rotation:" << rotest(0, 0) << ":" << rotest(0, 1) << ":"
286 << rotest(0, 2) << std::endl;
287 std::cout << " " << rotest(1, 0) << ":" << rotest(1, 1)
288 << ":" << rotest(1, 2) << std::endl;
289 std::cout << " " << rotest(2, 0) << ":" << rotest(2, 1)
290 << ":" << rotest(2, 2) << std::endl;
291 std::cout << " ref rotation:" << rotref(0, 0) << ":" << rotref(0, 1) << ":"
292 << rotref(0, 2) << std::endl;
293 std::cout << " " << rotref(1, 0) << ":" << rotref(1, 1)
294 << ":" << rotref(1, 2) << std::endl;
295 std::cout << " " << rotref(2, 0) << ":" << rotref(2, 1)
296 << ":" << rotref(2, 2) << std::endl;
297 std::cout << "test*inv(ref):" << rotid(0, 0) << ":" << rotid(0, 1) << ":"
298 << rotid(0, 2) << std::endl;
299 std::cout << " " << rotid(1, 0) << ":" << rotid(1, 1)
300 << ":" << rotid(1, 2) << std::endl;
301 std::cout << " " << rotid(2, 0) << ":" << rotid(2, 1)
302 << ":" << rotid(2, 2) << std::endl;
303 std::cout << " identity check fails within the tolerance limit:"
304 << tolerance << std::endl;
305 std::cout.copyfmt(oldState); // restore ostream state
306}
Visitor to process all volumes under a GeoModel node.
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
bool findNamePattern(const GeoVPhysVol *gv, std::string_view name) const
search of matching name patterns
static const GeoVPhysVol * findTopBranch(const GeoVPhysVol *gv, std::string_view name)
search of top branch : returns mother volume for children matching name
static void printTranslationDiff(GeoTrf::Transform3D trtest, GeoTrf::Transform3D trref, double tolerance)
printout diff - unify output
static bool identity_check(GeoTrf::RotationMatrix3D rotation, double tol)
check of rotation invariance
bool compareShapes(const GeoShape *gs1, const GeoShape *gv2, double tolerance) const
shape comparison
static void printRotationDiff(const GeoTrf::Transform3D &trtest, const GeoTrf::Transform3D &trref, double tolerance)
int compareGeoVolumes(const GeoVPhysVol *gv1, const GeoVPhysVol *gv2, double tolerance, bool printFullInfo=false, int level=0) const
Recursive comparison of trees/branches/volumes : in quiet mode (printFullInfo=False) ,...
#define ATH_FLATTEN
std::string m_name
The primary name part of this expression.