LDMX Software
AuxInfoReader.cxx
1#include "SimCore/Geo/AuxInfoReader.h"
2
3// LDMX
4#include "Framework/Exception/Exception.h"
9
10// Geant4
11#include "G4FieldManager.hh"
12#include "G4GDMLEvaluator.hh"
13#include "G4LogicalVolumeStore.hh"
14#include "G4Region.hh"
15#include "G4RegionStore.hh"
16#include "G4SDManager.hh"
17#include "G4SystemOfUnits.hh"
18#include "G4UniformMagField.hh"
19
20// STL
21#include <cstdlib>
22#include <string>
23
24using std::string;
25
26namespace simcore::geo {
27
28AuxInfoReader::AuxInfoReader(G4GDMLParser* theParser,
30 : parser_(theParser), eval_(new G4GDMLEvaluator) {}
31
36
38 const G4GDMLAuxListType* auxInfoList = parser_->GetAuxList();
39 for (const auto& auxInfo : *auxInfoList) {
40 G4String auxType = auxInfo.type;
41 G4String auxVal = auxInfo.value;
42
43 if (auxType == "SensDet") {
44 std::cerr
45 << "[ WARN ] : Not defining SensDet in GDML since v1.0 of SimCore. "
46 "See https://github.com/LDMX-Software/SimCore/issues/39"
47 << std::endl;
48 } else if (auxType == "MagneticField") {
49 createMagneticField(auxVal, auxInfo.auxList);
50 } else if (auxType == "Region") {
51 createRegion(auxVal, auxInfo.auxList);
52 } else if (auxType == "VisAttributes") {
53 createVisAttributes(auxVal, auxInfo.auxList);
54 } else if (auxType == "DetectorVersion") {
55 createDetectorHeader(auxVal, auxInfo.auxList);
56 }
57 }
58 return;
59}
60
62 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
63 std::vector<G4LogicalVolume*>::const_iterator lvciter;
64 for (lvciter = lvs->begin(); lvciter != lvs->end(); lvciter++) {
65 G4GDMLAuxListType auxInfoList =
66 parser_->GetVolumeAuxiliaryInformation(*lvciter);
67
68 for (const auto& auxInfo : auxInfoList) {
69 G4String auxType = auxInfo.type;
70 G4String auxVal = auxInfo.value;
71
72 G4LogicalVolume* lv = (*lvciter);
73
74 if (auxType == "MagneticField") {
75 const G4String& magFieldName = auxVal;
76 G4MagneticField* magField =
78 if (magField != nullptr) {
79 auto mgr = new G4FieldManager(magField);
80 lv->SetFieldManager(
81 mgr,
82 true /* FIXME: hard-coded to force field manager to daughters */);
83 // G4cout << "Assigned magnetic field " << magFieldName << " to
84 // volume " << lv->GetName() << G4endl;
85 } else {
86 EXCEPTION_RAISE(
87 "MissingInfo",
88 "Unknown MagneticField ref in volume's auxiliary info: " +
89 std::string(magFieldName.data()));
90 }
91 } else if (auxType == "Region") {
92 const G4String& regionName = auxVal;
93 G4Region* region = G4RegionStore::GetInstance()->GetRegion(regionName);
94 if (region != nullptr) {
95 region->AddRootLogicalVolume(lv);
96 // G4cout << "Added volume " << lv->GetName() << " to region " <<
97 // regionName << G4endl;
98 } else {
99 EXCEPTION_RAISE("MissingInfo", "Reference region '" +
100 std::string(regionName.data()) +
101 "' was not found!");
102 }
103 } else if (auxType == "VisAttributes") {
104 const G4String& visName = auxVal;
105 G4VisAttributes* visAttributes =
107 if (visAttributes != nullptr) {
108 lv->SetVisAttributes(visAttributes);
109 // G4cout << "Assigned VisAttributes " << visName << " to volume "
110 // << lv->GetName() << G4endl;
111 } else {
112 EXCEPTION_RAISE("MissingInfo", "Referenced VisAttributes '" +
113 std::string(visName.data()) +
114 "' was not found!");
115 }
116 }
117 }
118 }
119}
120
121void AuxInfoReader::createMagneticField(const G4String& magFieldName,
122 const G4GDMLAuxListType* auxInfoList) {
123 // Find type of the mag field.
124 G4String magFieldType("");
125 for (const auto& auxInfo : *auxInfoList) {
126 G4String auxType = auxInfo.type;
127 G4String auxVal = auxInfo.value;
128
129 if (auxType == "MagneticFieldType") {
130 magFieldType = auxVal;
131 break;
132 }
133 }
134
135 if (magFieldType == "") {
136 EXCEPTION_RAISE("MissingInfo",
137 "Missing MagFieldType for magnetic field definition.");
138 }
139
140 G4MagneticField* magField = nullptr;
141
142 // Create a uniform mag field using the built-in Geant4 type.
143 if (magFieldType == "G4UniformMagField") {
144 double bx, by, bz;
145 bx = by = bz = 0.;
146 for (const auto& auxInfo : *auxInfoList) {
147 G4String auxType = auxInfo.type;
148 G4String auxVal = auxInfo.value;
149 G4String auxUnit = auxInfo.unit;
150
151 G4String expr = auxVal + "*" + auxUnit;
152 if (auxType == "bx") {
153 bx = eval_->Evaluate(expr);
154 } else if (auxType == "by") {
155 by = eval_->Evaluate(expr);
156 } else if (auxType == "bz") {
157 bz = eval_->Evaluate(expr);
158 }
159 }
160 G4ThreeVector fieldComponents(bx, by, bz);
161 magField = new G4UniformMagField(fieldComponents);
162
163 // G4cout << "Created G4UniformMagField " << magFieldName << " with field
164 // components " << fieldComponents << G4endl << G4endl;
165
166 // Create a global 3D field map by reading from a data file.
167 } else if (magFieldType == "MagneticFieldMap3D") {
168 string fileName;
169 double offsetX{};
170 double offsetY{};
171 double offsetZ{};
172
173 for (const auto& auxInfo : *auxInfoList) {
174 G4String auxType = auxInfo.type;
175 G4String auxVal = auxInfo.value;
176 G4String auxUnit = auxInfo.unit;
177
178 G4String expr = auxVal + "*" + auxUnit;
179
180 if (auxType == "File") {
181 fileName = auxVal;
182 } else if (auxType == "OffsetX") {
183 offsetX = eval_->Evaluate(expr);
184 } else if (auxType == "OffsetY") {
185 offsetY = eval_->Evaluate(expr);
186 } else if (auxType == "OffsetZ") {
187 offsetZ = eval_->Evaluate(expr);
188 }
189 }
190
191 if (fileName.size() == 0) {
192 EXCEPTION_RAISE("MissingInfo",
193 "File info with field data was not provided.");
194 }
195
196 // Create new 3D field map.
197 magField =
198 new MagneticFieldMap3D(fileName.c_str(), offsetX, offsetY, offsetZ);
199
200 // Assign field map as global field.
201 G4FieldManager* fieldMgr =
202 G4TransportationManager::GetTransportationManager()->GetFieldManager();
203 if (fieldMgr->GetDetectorField() != nullptr) {
204 EXCEPTION_RAISE("MisAssign", "Global mag field was already assigned.");
205 }
206 fieldMgr->SetDetectorField(magField);
207 fieldMgr->CreateChordFinder(magField);
208
209 } else {
210 EXCEPTION_RAISE("UnknownType", "Unknown MagFieldType '" +
211 std::string(magFieldType.data()) +
212 "' in auxiliary info.");
213 }
214
215 MagneticFieldStore::getInstance()->addMagneticField(magFieldName, magField);
216}
217
218void AuxInfoReader::createRegion(const G4String& name,
219 const G4GDMLAuxListType* auxInfoList) {
220 bool storeTrajectories = true;
221 for (const auto& auxInfo : *auxInfoList) {
222 G4String auxType = auxInfo.type;
223 G4String auxVal = auxInfo.value;
224
225 if (auxType == "StoreTrajectories") {
226 if (auxVal == "false") {
227 storeTrajectories = false;
228 } else if (auxVal == "true") {
229 storeTrajectories = true;
230 }
231 }
232 }
233 G4VUserRegionInformation* regionInfo =
234 new UserRegionInformation(storeTrajectories);
235 // This looks like a memory leak, but isn't. I (Einar) have checked. Geant4
236 // registers the region in the constructor and deletes it at the end.
237 //
238 // Some static analysis tools may struggle with identifying that this one
239 // happens to be fine. The NOLINT comment tells clang-tidy to not bother
240 // within the region
241 //
242 // NOLINTBEGIN
243 auto region = new G4Region(name);
244 region->SetUserInformation(regionInfo);
245}
246// NOLINTEND
247
248void AuxInfoReader::createVisAttributes(const G4String& name,
249 const G4GDMLAuxListType* auxInfoList) {
250 std::array<G4double, 4> rgba = {1., 1., 1., 1.};
251 G4bool visible = true;
252 G4bool dauInvisible = false;
253 G4bool forceWireframe = false;
254 G4bool forceSolid = false;
255 G4double lineWidth = 1.0;
256 G4VisAttributes::LineStyle lineStyle = G4VisAttributes::unbroken;
257
258 for (const auto& auxInfo : *auxInfoList) {
259 G4String auxType = auxInfo.type;
260 G4String auxVal = auxInfo.value;
261
262 if (auxType == "R") {
263 rgba[0] = atof(auxVal.c_str());
264 } else if (auxType == "G") {
265 rgba[1] = atof(auxVal.c_str());
266 } else if (auxType == "B") {
267 rgba[2] = atof(auxVal.c_str());
268 } else if (auxType == "A") {
269 rgba[3] = atof(auxVal.c_str());
270 } else if (auxType == "Style") {
271 if (auxVal == "wireframe") {
272 forceWireframe = true;
273 } else if (auxVal == "solid") {
274 forceSolid = true;
275 }
276 } else if (auxType == "DaughtersInvisible") {
277 if (auxVal == "true") {
278 dauInvisible = true;
279 } else if (auxVal == "false") {
280 dauInvisible = false;
281 }
282 } else if (auxType == "Visible") {
283 if (auxVal == "true") {
284 visible = true;
285 } else if (auxVal == "false") {
286 visible = false;
287 }
288 } else if (auxType == "LineStyle") {
289 if (auxVal == "unbroken") {
290 lineStyle = G4VisAttributes::unbroken;
291 } else if (auxVal == "dashed") {
292 lineStyle = G4VisAttributes::dashed;
293 } else if (auxVal == "dotted") {
294 lineStyle = G4VisAttributes::dotted;
295 }
296 } else if (auxType == "LineWidth") {
297 lineWidth = atof(auxVal.c_str());
298 }
299 }
300
301 auto visAttributes = new G4VisAttributes();
302 visAttributes->SetColor(rgba[0], rgba[1], rgba[2], rgba[3]);
303 visAttributes->SetVisibility(visible);
304 visAttributes->SetDaughtersInvisible(dauInvisible);
305 visAttributes->SetForceWireframe(forceWireframe);
306 visAttributes->SetForceSolid(forceSolid);
307 visAttributes->SetLineWidth(lineWidth);
308 visAttributes->SetLineStyle(lineStyle);
310
311 // G4cout << "Created VisAttributes " << name << G4endl << (*visAttributes) <<
312 // G4endl << G4endl;
313}
314
315void AuxInfoReader::createDetectorHeader(const G4String& auxValue,
316 const G4GDMLAuxListType* auxInfoList) {
317 int detectorVersion = atoi(auxValue.c_str());
318
319 std::string detectorName("");
320 std::string author("");
321 std::string description("");
322
323 for (const auto& auxInfo : *auxInfoList) {
324 G4String auxType = auxInfo.type;
325 G4String auxVal = auxInfo.value;
326
327 if (auxType == "DetectorName") {
328 detectorName = auxVal;
329 } else if (auxType == "Author") {
330 author = auxVal;
331 } else if (auxType == "Description") {
332 description = auxVal;
333 }
334 }
335
336 detectorHeader_ = new ldmx::DetectorHeader(detectorName, detectorVersion,
337 description, author);
338
339 /*G4cout << G4endl;
340 G4cout << "Read detector header from userinfo: " << G4endl;
341 G4cout << " DetectorName: " << detectorHeader_->getName() << G4endl;
342 G4cout << " DetectorVersion: " << detectorHeader_->getVersion() << G4endl;
343 G4cout << " Author: " << detectorHeader_->getAuthor() << G4endl;
344 G4cout << " Description: " << detectorHeader_->getDescription() << G4endl;
345 G4cout << G4endl;*/
346}
347} // namespace simcore::geo
Class for defining a global 3D magnetic field.
Class providing a global store to access magnetic field objects.
Class which provides extra information for a detector region.
Class that provides a global visualization attributes store.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
Defines detector header information.
A 3D B-field map defined as a grid of points with associated B-field values.
static MagneticFieldStore * getInstance()
Get the global instance of the magnetic field store.
G4MagneticField * getMagneticField(const std::string &name)
Get a magnetic field by name.
void addMagneticField(const std::string &name, G4MagneticField *magField)
Add a magnetic field by name.
Defines extra information for a detector region.
G4VisAttributes * getVisAttributes(const std::string &name)
Get vis attributes by name.
void addVisAttributes(const std::string &name, G4VisAttributes *visAttributes)
Register a vis attributes by name.
static VisAttributesStore * getInstance()
Get the global instance of the store.
void createDetectorHeader(const G4String &detectorVersion, const G4GDMLAuxListType *auxInfoList)
Create the detector header from the global auxinfo.
virtual ~AuxInfoReader()
Class destructor.
void assignAuxInfoToVolumes()
Assign auxiliary info to volumes such as sensitive detectors.
void readGlobalAuxInfo()
Read the global auxiliary information from the auxinfo block.
AuxInfoReader(G4GDMLParser *parser, const framework::config::Parameters &ps)
Class constructor.
void createVisAttributes(const G4String &name, const G4GDMLAuxListType *auxInfoList)
Create visualization attributes from GDML data.
G4GDMLEvaluator * eval_
The GDML expression evaluator.
G4GDMLParser * parser_
The GDML parser.
ldmx::DetectorHeader * detectorHeader_
Detector header with name and version.
void createMagneticField(const G4String &name, const G4GDMLAuxListType *auxInfoList)
Create a magnetic field from GDML data.
void createRegion(const G4String &name, const G4GDMLAuxListType *auxInfoList)
Create a detector region from GDML data.