ATLAS Offline Software
Loading...
Searching...
No Matches
DumpGeo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Initial version:
6// - 2017, Sep -- Riccardo Maria BIANCHI
7// <riccardo.maria.bianchi@cern.ch>
8// Main updates:
9// - 2024, Feb -- Riccardo Maria BIANCHI
10// <riccardo.maria.bianchi@cern.ch>
11// Moved configuration to ComponentAccumulator (CA)
12// - 2024, Mar -- Riccardo Maria BIANCHI
13// <riccardo.maria.bianchi@cern.ch>
14// Removed GeoExporter, moved all to DumpGeo
15// - 2024, Apr -- Added missing sub-systems: Cavern, HGTD, FWD detectors, ...
16
17#include "DumpGeo/DumpGeo.h"
18
19// Athena includes
23
24// From GeoModel in Externals
25#include "GeoModelDBManager/GMDBManager.h"
26#include "GeoModelKernel/GeoBox.h"
27#include "GeoModelKernel/GeoVDetectorManager.h"
28#include "GeoModelKernel/GeoVolumeCursor.h"
29#include "GeoModelWrite/WriteGeoModel.h"
30// #include "GeoModelHelpers/defineWorld.h" // not available in 24.0...
31
32// C++ includes
33#include <cstdlib> //For setenv
34#include <filesystem>
35#include <iomanip>
36#include <iostream>
37#include <stdexcept>
38#include <system_error>
39#include <vector>
40
41// Units
42#include "GeoModelKernel/Units.h"
43#define UNITS GeoModelKernelUnits // so we can use, e.g., 'UNITS::cm'
44
45// TODO: replace this with GeoModelHelpers/defineWorld.h
46//_____________________________________________________________________________________
47GeoPhysVol* createTheWorld() {
48// Define the units
49#define gr UNITS::gram
50#define mole UNITS::mole
51#define cm3 UNITS::cm3
52
53 // Define the chemical elements
54 GeoElement* Nitrogen =
55 new GeoElement("Nitrogen", "N", 7.0, 14.0067 * gr / mole);
56 GeoElement* Oxygen = new GeoElement("Oxygen", "O", 8.0, 15.9995 * gr / mole);
57 GeoElement* Argon = new GeoElement("Argon", "Ar", 18.0, 39.948 * gr / mole);
58 GeoElement* Hydrogen =
59 new GeoElement("Hydrogen", "H", 1.0, 1.00797 * gr / mole);
60
61 // Define the materials
62 double densityOfAir = 0.001214 * gr / cm3;
63 GeoMaterial* air = new GeoMaterial("Air", densityOfAir);
64 air->add(Nitrogen, 0.7494);
65 air->add(Oxygen, 0.2369);
66 air->add(Argon, 0.0129);
67 air->add(Hydrogen, 0.0008);
68 air->lock();
69
70 //-----------------------------------------------------------------------------------//
71 // create the world volume container and
72 // get the 'world' volume, i.e. the root volume of the GeoModel tree
73 const GeoBox* worldBox =
74 new GeoBox(1000 * UNITS::cm, 1000 * UNITS::cm, 1000 * UNITS::cm);
75 const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air);
76 GeoPhysVol* world = new GeoPhysVol(worldLog);
77 return world;
78}
79
80//____________________________________________________________________
81DumpGeo::DumpGeo(const std::string& name, ISvcLocator* svcLocator)
82 : AthAlgorithm(name, svcLocator) {}
83
84//____________________________________________________________________
85StatusCode DumpGeo::initialize() {
86 ATH_MSG_DEBUG("in initialize()");
87
88 ATH_MSG_INFO("===================================================");
89 ATH_MSG_INFO("\t\tLaunching DumpGeo");
90 ATH_MSG_INFO("===================================================");
91
92 ATH_MSG_INFO("Accessing the ATLAS geometry...");
93 const GeoModelExperiment* theExpt = nullptr;
94 ATH_CHECK(detStore()->retrieve(theExpt, "ATLAS"));
95
96 // Get the ATLAS GEOMETRY 'World' volume
97 PVConstLink world(theExpt->getPhysVol());
98
100 "User filter DetectorManagers: " << m_user_filterDetManagersList);
101
102 ServiceHandle<IGeoDbTagSvc> geoDbTag("GeoDbTagSvc", name());
103 ATH_CHECK(geoDbTag.retrieve());
105 "This is the Geometry TAG we are dumping: " << geoDbTag->atlasVersion());
106
107 GeoPhysVol* volTop = createTheWorld();
108
109 // Get list of managers
110 // We fill a set from the output vector,
111 // so we can use its built-in 'count' method later,
112 // to search for DetManagers
113 ATH_MSG_INFO("Dumping the GeoModel tree...");
114 std::set<std::string> managersList{};
115 {
116 std::vector<std::string> blub = theExpt->getListOfManagers();
117 managersList.insert(blub.begin(), blub.end());
118 }
119 if (msgLvl(MSG::INFO)) {
120 ATH_MSG_INFO("List of the GeoModel Detector Managers that are being dumped: ");
121 for (auto const& man : managersList) {
122 // get the DetectorManager
123 const GeoVDetectorManager* manager = theExpt->getManager(man);
124 unsigned int nTreetops = manager->getNumTreeTops();
125 std::cout << "\t" << man << " [contains " << nTreetops << " treetops]"
126 << std::endl;
127 for (unsigned int i = 0; i < nTreetops; ++i) {
128 PVConstLink treetop(manager->getTreeTop(i));
129 // get treetop's volume
130 const GeoVPhysVol* vol = treetop;
131 // get treetop's logvol's name
132 std::string volName = vol->getLogVol()->getName();
133 std::cout << "\t\t treetop: " << volName << std::endl;
134 }
135 }
136 }
137
138 if (!(m_user_filterDetManagersList.empty())) {
139 // Convert the list of det managers passed by the user into a set
140 std::set<std::string> user_managersList{};
141 {
142 user_managersList.insert(m_user_filterDetManagersList.begin(),
144 }
145 // safety check:
146 // check that all DetManagers requested by the user are in the list
147 // If not, print an error message to warn the user and return
148 for (auto& userDet : user_managersList) {
149 if (!managersList.count(userDet)) {
151 "This Detector Manager you requested to dump is not in the list of "
152 "DetectorManagers for the geometry tag you are using: "
153 << userDet);
154 throw GaudiException(
155 "The Detector Manager you requested to dump is not in the list of "
156 "DetectorManagers.",
157 "DumpGeo", StatusCode::FAILURE);
158 }
159 }
160
161 if (!(managersList.empty())) {
162 for (auto const& mm : managersList) {
163 // get the DetectorManager
164 const GeoVDetectorManager* manager = theExpt->getManager(mm);
165
166 // get the name of the DetectorManager
167 std::string detManName = manager->getName();
168 ATH_MSG_INFO("\tDetectorManager: " << detManName);
169
170 // get the DetManager's TreeTops
171 unsigned int nTreetops = manager->getNumTreeTops();
172 ATH_MSG_INFO("\t" << mm << " - # TreeTops: " << nTreetops);
173
174 if ((nTreetops > 0) && user_managersList.count(detManName)) {
175
176 for (unsigned int i = 0; i < nTreetops; ++i) {
177
178 PVConstLink treetop(manager->getTreeTop(i));
179
180 // get treetop's volume
181 const GeoVPhysVol* vol = treetop;
182
183 // get volume's transform
184 // NOTE: we use getDefX() to get the transform without any alignment
185 GeoTransform* volXf = new GeoTransform(vol->getDefX());
186
187 // get volume's logvol's name
188 std::string volName = vol->getLogVol()->getName();
189 ATH_MSG_INFO("\t* treetop " << i << ": " << volName);
190
191 // Add to the main volume a GeoNameTag with the name of the
192 // DetectorManager
193 volTop->add(new GeoNameTag(detManName));
194 // add Transform and Volume to the main PhysVol
195 volTop->add(volXf);
196 volTop->add(const_cast<GeoVPhysVol*>(vol));
197
199 ATH_MSG_INFO("You enabled the option 'showTreetopContent', so we now print the content of the first layers of child volumes of the Treetops...");
200 unsigned v1{0};
201 GeoVolumeCursor av(treetop);
202 while (!av.atEnd()) {
203 ++v1;
204 if(1==v1) ATH_MSG_INFO("first level of child volumes:");
205 ATH_MSG_INFO("\t\t- child's name: " << av.getName());
206 ATH_MSG_INFO("\t\t- child's n. sub-nodes: " << av.getVolume()->getNChildNodes());
207 ATH_MSG_INFO("\t\t- child's n. sub-volumes: " << av.getVolume()->getNChildVols());
208
209
210 unsigned v2{0};
211 GeoVolumeCursor av2(av.getVolume());
212 while (!av2.atEnd()) {
213 ++v2;
214 if(1==v2) ATH_MSG_INFO("second level of child volumes:");
215 ATH_MSG_INFO("\t\t\t- child's logvol's name: " << av2.getVolume()->getLogVol()->getName());
216
217 unsigned v3{0};
218 GeoVolumeCursor av3(av2.getVolume());
219 while (!av3.atEnd()) {
220 ++v3;
221 if(1==v3) ATH_MSG_INFO("third level of child volumes:");
222 ATH_MSG_INFO("\t\t\t\t- child's logvol's name: " << av3.getVolume()->getLogVol()->getName());
223 av3.next(); // increment volume cursor.
224 } // end while
225
226 av2.next(); // increment volume cursor.
227 } // end while
228
229 av.next(); // increment volume cursor.
230 } // end while
231 }
232 }
233 }
234 }
235 }
236 }
237
238 // DEBUG inspection
239 if (msgLvl(MSG::DEBUG)) {
241 "Looping over top volumes in the GeoModel tree (children of the "
242 "'World' volume)...");
243 GeoVolumeCursor av(world);
244 while (!av.atEnd()) {
245 std::string volname = av.getName();
246 ATH_MSG_DEBUG("\t* relevant NameTag:" << volname);
247 av.next(); // increment volume cursor.
248 }
249 }
250
251 ATH_MSG_INFO("Creating the SQLite DB file...");
252 if (m_outFileName.empty()) {
253 ATH_MSG_FATAL("The name of the output SQLite file is not set!");
254 throw GaudiException("The name of the output SQLite file is not set!",
255 "DumpGeo", StatusCode::FAILURE);
256 }
257 ATH_MSG_INFO("Output file name: " << m_outFileName);
258
259 // Delay destructive overwrite handling until the algorithm is actually
260 // initialized, immediately before opening the output database. Use one
261 // removal attempt without a preceding existence check: a missing file is
262 // harmless, while any real filesystem error must stop the job.
263 if (m_forceOverwrite) {
264 std::error_code error;
265 const bool removed = std::filesystem::remove(m_outFileName.value(), error);
266 if (error) {
267 ATH_MSG_FATAL("Could not remove existing output file '"
268 << m_outFileName << "': " << error.message());
269 return StatusCode::FAILURE;
270 }
271 if (removed) {
272 ATH_MSG_INFO("Removed existing output file '" << m_outFileName << "'.");
273 }
274 }
275
276 // open the DB connection
277 GMDBManager db(m_outFileName);
278
279 // check the DB connection
280 if (db.checkIsDBOpen())
281 ATH_MSG_INFO("OK! Database is open!");
282 else {
283 ATH_MSG_ERROR(" ***** Database ERROR!! Exiting...");
284 throw GaudiException(
285 "The GeoModel SQLite .db file could not be opened successfully.",
286 "DumpGeo", StatusCode::FAILURE);
287 }
288
289 ATH_MSG_INFO("Traversing the GeoModel tree...");
290 // Dump the tree volumes into a DB
291 // 1. init the GeoModel node action
292 GeoModelIO::WriteGeoModel dumpGeoModelGraph(db);
293 // 2. visit all GeoModel nodes
294 if (!(m_user_filterDetManagersList.empty())) {
295 volTop->exec(&dumpGeoModelGraph);
296 } else {
297 world->exec(&dumpGeoModelGraph);
298 }
299 ATH_MSG_INFO("Saving the GeoModel tree to the DB...");
300 // 3. save it to an SQLite file
301 dumpGeoModelGraph.saveToDB();
302 ATH_MSG_ALWAYS("DONE. Geometry saved to " << m_outFileName);
303
304 // Quick test if DEBUG
305 if (msgLvl(MSG::DEBUG)) {
307 "Test - list of all the GeoMaterial nodes in the persistified "
308 "geometry:");
309 db.printAllMaterials();
311 "Test - list of all the GeoElement nodes in the persistified "
312 "geometry:");
313 db.printAllElements();
314 }
315
316 ATH_MSG_DEBUG("End of DumpGeo::init().");
317 return StatusCode::SUCCESS;
318}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_ALWAYS(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
#define cm3
GeoPhysVol * createTheWorld()
Definition DumpGeo.cxx:47
#define gr
#define mole
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
Gaudi::Property< bool > m_showTreetopContent
Definition DumpGeo.h:54
StatusCode initialize()
Definition DumpGeo.cxx:85
Gaudi::Property< std::vector< std::string > > m_user_filterDetManagersList
Definition DumpGeo.h:53
Gaudi::Property< std::string > m_outFileName
Definition DumpGeo.h:48
DumpGeo(const std::string &name, ISvcLocator *pSvcLocator) ATLAS_CTORDTOR_NOT_THREAD_SAFE
Definition DumpGeo.cxx:81
Gaudi::Property< bool > m_forceOverwrite
Definition DumpGeo.h:49
const GeoVDetectorManager * getManager(const std::string &name) const
GeoPhysVol * getPhysVol()
Destructor.
std::vector< std::string > getListOfManagers() const