gsystem
Loading...
Searching...
No Matches
gworld.cc
Go to the documentation of this file.
1// gemc
2#include "gfactory.h"
3#include "gutilities.h"
4
5// gsystem
7#include "gworld.h"
8#include "gmodifier.h"
14
15// See gworld.h for API docs.
16
17// TODO: have getSystems returns the map directly instead of going through the vector
18GWorld::GWorld(const std::shared_ptr<GOptions>& g)
19 : GBase(g, GWORLD_LOGGER),
20 gopts(g) {
21 log->debug(NORMAL, SFUNCTION_NAME, "New");
22
23 // 1. Load system descriptors from options and build the internal map.
24 auto gsystems = gsystem::getSystems(gopts);
25 create_gsystemsMap(gsystems);
26
27 // 2. Load volumes/materials through factories, then apply modifiers, then finalize names.
28 load_systems(); // build factories, load volumes
29 load_gmodifiers(); // load & apply modifiers
30 assignG4Names(); // final bookkeeping
31}
32
33
34// Constructor with rvalue reference: perfect for taking ownership of move-only types
35GWorld::GWorld(const std::shared_ptr<GOptions>& g, SystemList gsystems)
36 : GBase(g, GWORLD_LOGGER),
37 gopts(g) {
38 log->debug(NORMAL, SFUNCTION_NAME, "From SystemList");
39
40 // 1. Adopt external systems and build internal map.
41 create_gsystemsMap(gsystems);
42
43 // 2. Finish world construction as in the main ctor.
44 load_systems(); // instantiate factories, load volumes
45 load_gmodifiers(); // load modifiers
46 assignG4Names(); // apply modifiers & set G4 names
47}
48
49
50// See gworld.h for API docs.
51std::map<std::string, std::unique_ptr<GSystemFactory>> GWorld::createSystemFactory() {
52 GManager manager(gopts);
53
54 std::map<std::string, std::unique_ptr<GSystemFactory>> factoryMap;
55
56 // Always register & create the SQLite factory (needed for ROOT volumes)
57 manager.RegisterObjectFactory<GSystemSQLiteFactory>(gsystem::GSYSTEMSQLITETFACTORYLABEL, gopts);
58 auto sqliteFactory = std::unique_ptr<GSystemFactory>(
60
61 if (!sqliteFactory) {
63 "Failed to create factory <", gsystem::GSYSTEMSQLITETFACTORYLABEL, ">");
64 }
65 factoryMap.emplace(gsystem::GSYSTEMSQLITETFACTORYLABEL, std::move(sqliteFactory));
66
67
68 // Scan all systems and create any missing factories
69 for (auto& [sysName, sysPtr] : *gsystemsMap) {
70 const std::string& facName = sysPtr->getFactoryName();
71
72 if (facName.empty()) {
74 "Factory name for system <", sysName,
75 "> is empty! This system will not be loaded.");
76 }
77
78 // Already have it? Move on.
79 if (factoryMap.count(facName)) continue;
80
81 //------------------ register the correct concrete class ----------------
83 manager.RegisterObjectFactory<GSystemCADFactory>(facName, gopts);
84 else if (facName == gsystem::GSYSTEMGDMLTFACTORYLABEL)
85 manager.RegisterObjectFactory<GSystemGDMLFactory>(facName, gopts);
86 else if (facName == gsystem::GSYSTEMSQLITETFACTORYLABEL)
87 manager.RegisterObjectFactory<GSystemSQLiteFactory>(facName, gopts);
88 else if (facName == gsystem::GSYSTEMASCIIFACTORYLABEL)
89 manager.RegisterObjectFactory<GSystemTextFactory>(facName, gopts);
90 else {
92 "Unrecognized factory name <", facName,
93 "> for system <", sysName, ">");
94 }
95
96 //------------------ create the factory object --------------------------
97 auto facPtr = std::unique_ptr<GSystemFactory>(manager.CreateObject<GSystemFactory>(facName));
98
99 if (!facPtr) {
101 "Failed to create factory <", facName,
102 "> for system <", sysName, ">");
103 }
104
105 factoryMap.emplace(facName, std::move(facPtr));
106 }
107
108 // Clean up any temporarily loaded shared libraries
109 manager.clearDLMap();
110
111 // Return by value (NRVO/move) – no leaks, no manual delete
112 return factoryMap;
113}
114
115
116// See gworld.h for API docs.
117GVolume* GWorld::searchForVolume(const std::string& volumeName, const std::string& purpose) const {
118 for (auto& systemPair : *gsystemsMap) {
119 GVolume* thisVolume = systemPair.second->getGVolume(volumeName);
120 if (thisVolume != nullptr) {
121 log->info(1, "gvolume named <", volumeName, "> found with purpose: ", purpose);
122 return thisVolume;
123 }
124 }
125 // If volume not found, print error and exit.
127 "gvolume named <", volumeName, "> (", purpose, ") not found in gsystemsMap ", purpose);
128}
129
130
131// See gworld.h for API docs.
132std::vector<std::string> GWorld::getSensitiveDetectorsList() {
133 std::vector<std::string> snames;
134
135 // Walk all volumes and collect digitization identifiers, de-duplicating them.
136 for (auto& systemPair : *gsystemsMap) {
137 for (auto& gvolumePair : systemPair.second->getGVolumesMap()) {
138 const auto& digitization = gvolumePair.second->getDigitization();
139 if (digitization && find(snames.begin(), snames.end(), *digitization) == snames.end()) {
140 snames.push_back(*digitization);
141 }
142 }
143 }
144 return snames;
145}
146
147
148// See gworld.h for API docs.
149void GWorld::create_gsystemsMap(SystemList systems) {
150 // Clearing the map before using it ensures this method can be called by both constructors.
151 gsystemsMap->clear();
152
153 for (auto& sysPtr : systems) {
154 // Keying by filename (without path) keeps map keys stable across different path prefixes.
155 std::string key = gutilities::getFileFromPath(sysPtr->getName());
156 gsystemsMap->emplace(key, sysPtr);
157 }
158}
159
160
161// See gworld.h for API docs.
162void GWorld::load_systems() {
163 const std::string dbhost = gopts->getRequiredScalarString("sql");
164
165 auto systemFactories = createSystemFactory();
166 const bool no_systems_defined = gsystemsMap->empty();
167
168 // For every system, find / create its factory and load volumes
169 const auto yamlFiles = gopts->getYamlFiles();
170
171 for (auto& [sysName, sysPtr] : *gsystemsMap) {
172 const std::string& factoryName = sysPtr->getFactoryName();
173
174 if (factoryName.empty()) {
176 "Factory name for system <", sysName, "> is empty!");
177 }
178
179 auto facIt = systemFactories.find(factoryName);
180 if (facIt == systemFactories.end()) {
182 "Factory <", factoryName, "> not found for system <", sysName, ">");
183 }
184
185 auto& factory = facIt->second; // std::unique_ptr<GSystemFactory>&
186 if (!factory) {
188 "Factory pointer <", factoryName, "> is nullptr");
189 }
190
191 // Feed YAML directories as possible file locations.
192 // This allows factories to find external assets alongside YAML configurations.
193 for (const auto& yaml : yamlFiles) {
194 std::string dir = gutilities::getDirFromPath(yaml);
195 if (dir.empty())
196 log->warning("Directory extracted from YAML <", yaml, "> is empty.");
197 factory->addPossibleFileLocation(dir);
198 }
199
200 // Load & close the system.
201 factory->loadSystem(sysPtr.get());
202 factory->closeSystem();
203 }
204
205
206 // loop over gsystemsMap looking for gsystem::ROOTWORLDGVOLUMENAME
207 auto world_is_defined = false;
208 for (auto& [sysName, sysPtr] : *gsystemsMap) {
209 // for each system run getGVolume(gsystem::ROOTWORLDGVOLUMENAME)
210 if (sysPtr->getGVolume(gsystem::ROOTWORLDGVOLUMENAME) != nullptr) {
211 log->info(1, "ROOT world volume found in system <", sysName, ">");
212 world_is_defined = true;
213 }
214 }
215
216 if (!world_is_defined) {
217 // Inject the ROOT “world” volume, if not already present.
218 // This ensures downstream volume placement always has a valid top-level mother.
219 const std::string worldVolumeDefinition =
220 gopts->getRequiredScalarString(gsystem::ROOTWORLDGVOLUMENAME);
221
222 auto rootSystem = std::make_shared<GSystem>(
223 gopts, // logger
224 dbhost,
225 gsystem::ROOTWORLDGVOLUMENAME, // name + path
227 "all", // experiment
228 1, // runNo
229 "default" // variation
230 );
231 rootSystem->addROOTVolume(worldVolumeDefinition);
232
233 if (no_systems_defined) {
234 std::vector<std::string> viewerBoxPars = {
235 "viewer_box", // 01 name
236 "G4Box", // 02 type
237 "1*m, 1*m, 1*m", // 03 parameters
238 "G4_AIR", // 04 material
240 gsystem::DEFAULTPOSITION, // 06 position
241 gsystem::DEFAULTROTATION, // 07 rotation
242 gsystem::DEFAULTG4PLACEMENTTYPE, // 08 Geant4 placement
243 guts::SERIALIZED_NULL_TOKEN, // 09 electromagnetic field
244 "1", // 10 visible
245 "0", // 11 style: wireframe
246 "ffcc33", // 12 color
247 "1", // 13 opacity
248 guts::SERIALIZED_NULL_TOKEN, // 14 digitization
249 guts::SERIALIZED_NULL_TOKEN, // 15 gidentity
250 guts::SERIALIZED_NULL_TOKEN, // 16 copyOf
251 guts::SERIALIZED_NULL_TOKEN, // 17 solidsOpr
252 guts::SERIALIZED_NULL_TOKEN, // 18 mirror
253 "1", // 19 exist flag
254 "default visible volume for field-only visualization"
255 };
256 rootSystem->addGVolume(viewerBoxPars);
257 }
258
259 (*gsystemsMap)[gsystem::ROOTWORLDGVOLUMENAME] = rootSystem;
260 }
261
262 // systemFactories goes out of scope -> all factories destroyed cleanly
263}
264
265
266// See gworld.h for API docs.
267void GWorld::load_gmodifiers() {
268 // Build the map <volumeName → shared_ptr<GModifier>>
269 for (const auto& mod : gsystem::getModifiers(gopts)) // returns vector<GModifier>
270 {
271 auto modPtr = std::make_shared<GModifier>(mod);
272 gmodifiersMap.emplace(modPtr->getName(), modPtr);
273 }
274
275 // Apply every modifier to its target volume
276 for (auto& [volumeName, modPtr] : gmodifiersMap) // modPtr is shared_ptr<GModifier>
277 {
278 // Will exit if not found:
279 GVolume* vol = searchForVolume(volumeName,
280 " is marked for modifications");
281
282 vol->applyShift(modPtr->getShift());
283 vol->applyTilt(modPtr->getTilts());
284 vol->modifyExistence(modPtr->getExistence());
285
286 log->info(2, "g-modifying volume <", volumeName,
287 "> with modifier: ", *modPtr);
288 log->info(2, "After modifications:", *vol);
289 }
290}
291
292
293// See gworld.h for API docs.
294void GWorld::assignG4Names() {
295 for (auto& systemPair : *gsystemsMap) {
296 for (auto& [volumeName, gvolume] : systemPair.second->getGVolumesMap()) {
297 // Skip if the volume's mother is "akasha" (top-level marker) or if this is the ROOT world volume itself.
298 std::string motherVolumeName = gvolume->getMotherName();
299 if (motherVolumeName != gsystem::MOTHEROFUSALL && volumeName != gsystem::ROOTWORLDGVOLUMENAME) {
300 // Mother lookup is required to build fully-qualified mother name.
301 auto motherVolume = searchForVolume(motherVolumeName, "mother of <" + gvolume->getName() + ">");
302 std::string g4name = gvolume->getSystem() + gsystem::GSYSTEM_DELIMITER + volumeName;
303 std::string g4motherName = motherVolume->getSystem() + gsystem::GSYSTEM_DELIMITER + motherVolumeName;
304
305 // ROOT mother is a special case: its Geant4 name is exactly gsystem::ROOTWORLDGVOLUMENAME.
306 if (motherVolumeName == gsystem::ROOTWORLDGVOLUMENAME) { g4motherName = gsystem::ROOTWORLDGVOLUMENAME; }
307
308 gvolume->assignG4Names(g4name, g4motherName);
309 }
310 else {
311 // Top-level volumes are assigned ROOT/world and akasha markers.
313 }
314 }
315 }
316}
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
Abstract base class for loading a GSystem from a specific source.
Load a GSystem from a sqlite database.
Geometry volume record loaded into a GSystem.
Definition gvolume.h:36
void applyTilt(std::optional< std::string > t)
Apply an additional rotation to this volume.
Definition gvolume.h:245
void applyShift(std::optional< std::string > s)
Apply an additional translation to this volume.
Definition gvolume.h:235
void modifyExistence(bool e)
Enable or disable this volume in the final assembled world.
Definition gvolume.h:255
std::vector< std::string > getSensitiveDetectorsList()
Collect the list of sensitive detector identifiers.
Definition gworld.cc:132
GWorld(const std::shared_ptr< GOptions > &gopts)
Construct the world from configuration.
Definition gworld.cc:18
#define SFUNCTION_NAME
NORMAL
Conventions and shared constants for the detector-system module.
std::vector< SystemPtr > SystemList
Definition gsystem.h:280
constexpr const char * GWORLD_LOGGER
constexpr int ERR_FACTORYNOTFOUND
constexpr char GSYSTEMGDMLTFACTORYLABEL[]
constexpr char DEFAULTG4PLACEMENTTYPE[]
constexpr char GSYSTEMCADTFACTORYLABEL[]
constexpr char GSYSTEM_DELIMITER[]
Delimiter used to build fully-qualified names (system/name).
constexpr char DEFAULTROTATION[]
constexpr char GSYSTEMSQLITETFACTORYLABEL[]
constexpr char MOTHEROFUSALL[]
Special mother-name marker for the top-level world root.
constexpr char DEFAULTPOSITION[]
constexpr char GSYSTEMASCIIFACTORYLABEL[]
std::vector< GModifier > getModifiers(const std::shared_ptr< GOptions > &gopts)
Build a list of volume modifiers from options.
constexpr char ROOTWORLDGVOLUMENAME[]
Canonical name for the ROOT/world gvolume entry.
SystemList getSystems(const std::shared_ptr< GOptions > &gopts)
Build a list of systems from options.
constexpr int ERR_GVOLUMENOTFOUND
string getDirFromPath(const std::string &path)
string getFileFromPath(const std::string &path)
constexpr char SERIALIZED_NULL_TOKEN[]