LDMX Software
simcore::geo::AuxInfoReader Class Reference

Reads auxiliary information from GDML userinfo block. More...

#include <AuxInfoReader.h>

Public Member Functions

 AuxInfoReader (G4GDMLParser *parser, const framework::config::Parameters &ps)
 Class constructor.
 
virtual ~AuxInfoReader ()
 Class destructor.
 
void readGlobalAuxInfo ()
 Read the global auxiliary information from the auxinfo block.
 
void assignAuxInfoToVolumes ()
 Assign auxiliary info to volumes such as sensitive detectors.
 
ldmx::DetectorHeader * getDetectorHeader ()
 Get the detector header that was created from the userinfo block.
 

Private Member Functions

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.
 
void selectColorMode (const G4String &mode)
 Select the 'mode' for coloring in the visualization.
 
void createVisAttributes (const G4String &name, const G4GDMLAuxListType *auxInfoList)
 Create visualization attributes from GDML data.
 
void createDetectorHeader (const G4String &detectorVersion, const G4GDMLAuxListType *auxInfoList)
 Create the detector header from the global auxinfo.
 

Private Attributes

G4GDMLParser * parser_
 The GDML parser.
 
G4GDMLEvaluator * eval_
 The GDML expression evaluator.
 
ldmx::DetectorHeader * detector_header_ {nullptr}
 Detector header with name and version.
 
std::string color_mode_
 Color mode for visattributes.
 
std::vector< std::string > universal_visattributes_
 

Detailed Description

Reads auxiliary information from GDML userinfo block.

Note
This class reads information to define a detector header block, sensitive detectors, visualization attributes, magnetic fields, detector IDs, and detector regions from the userinfo block of a GDML file. These objects are then assigned to the appropriate logical volumes which have auxiliary tags that reference these objects by name.

Definition at line 28 of file AuxInfoReader.h.

Constructor & Destructor Documentation

◆ AuxInfoReader()

simcore::geo::AuxInfoReader::AuxInfoReader ( G4GDMLParser * parser,
const framework::config::Parameters & ps )

Class constructor.

Parameters
parserThe GDML parser.
psconfiguration parameters

Definition at line 30 of file AuxInfoReader.cxx.

32 : parser_(theParser), eval_(new G4GDMLEvaluator) {}
G4GDMLEvaluator * eval_
The GDML expression evaluator.
G4GDMLParser * parser_
The GDML parser.

◆ ~AuxInfoReader()

simcore::geo::AuxInfoReader::~AuxInfoReader ( )
virtual

Class destructor.

Definition at line 34 of file AuxInfoReader.cxx.

34 {
35 delete eval_;
36 delete detector_header_;
37}
ldmx::DetectorHeader * detector_header_
Detector header with name and version.

References detector_header_, and eval_.

Member Function Documentation

◆ assignAuxInfoToVolumes()

void simcore::geo::AuxInfoReader::assignAuxInfoToVolumes ( )

Assign auxiliary info to volumes such as sensitive detectors.

Definition at line 65 of file AuxInfoReader.cxx.

65 {
66 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
67 std::vector<G4LogicalVolume*>::const_iterator lvciter;
68 for (lvciter = lvs->begin(); lvciter != lvs->end(); lvciter++) {
69 G4GDMLAuxListType aux_info_list =
70 parser_->GetVolumeAuxiliaryInformation(*lvciter);
71
72 for (const auto& aux_info : aux_info_list) {
73 G4String aux_type = aux_info.type;
74 G4String aux_val = aux_info.value;
75
76 G4LogicalVolume* lv = (*lvciter);
77
78 if (aux_type == "MagneticField") {
79 const G4String& mag_field_name = aux_val;
80 G4MagneticField* mag_field =
82 if (mag_field != nullptr) {
83 auto mgr = new G4FieldManager(mag_field);
84 lv->SetFieldManager(
85 mgr,
86 true /* FIXME: hard-coded to force field manager to daughters */);
87 // G4cout << "Assigned magnetic field " << magFieldName << " to
88 // volume " << lv->GetName() << G4endl;
89 } else {
90 EXCEPTION_RAISE(
91 "MissingInfo",
92 "Unknown MagneticField ref in volume's auxiliary info: " +
93 std::string(mag_field_name.data()));
94 }
95 } else if (aux_type == "Region") {
96 const G4String& region_name = aux_val;
97 G4Region* region = G4RegionStore::GetInstance()->GetRegion(region_name);
98 if (region != nullptr) {
99 region->AddRootLogicalVolume(lv);
100 // G4cout << "Added volume " << lv->GetName() << " to region " <<
101 // regionName << G4endl;
102 } else {
103 EXCEPTION_RAISE("MissingInfo", "Reference region '" +
104 std::string(region_name.data()) +
105 "' was not found!");
106 }
107 } else if (aux_type == "VisAttributes") {
108 // Same as when registering visattributes, must match mode (if in use)
109 auto match = std::find(universal_visattributes_.begin(),
110 universal_visattributes_.end(), aux_val);
111 if (match == universal_visattributes_.end() && color_mode_ != "" &&
112 aux_val.find(color_mode_) == std::string::npos) {
113 continue;
114 }
115 const G4String& vis_name = aux_val;
116 G4VisAttributes* vis_attributes =
118 if (vis_attributes != nullptr) {
119 lv->SetVisAttributes(vis_attributes);
120 // G4cout << "Assigned VisAttributes " << visName << " to volume "
121 // << lv->GetName() << G4endl;
122 } else {
123 EXCEPTION_RAISE("MissingInfo", "Referenced VisAttributes '" +
124 std::string(vis_name.data()) +
125 "' was not found!");
126 }
127 }
128 }
129 }
130}
static MagneticFieldStore * getInstance()
Get the global instance of the magnetic field store.
G4MagneticField * getMagneticField(const std::string &name)
Get a magnetic field by name.
G4VisAttributes * getVisAttributes(const std::string &name)
Get vis attributes by name.
static VisAttributesStore * getInstance()
Get the global instance of the store.
std::string color_mode_
Color mode for visattributes.

References color_mode_, simcore::MagneticFieldStore::getInstance(), simcore::VisAttributesStore::getInstance(), simcore::MagneticFieldStore::getMagneticField(), simcore::VisAttributesStore::getVisAttributes(), and parser_.

◆ createDetectorHeader()

void simcore::geo::AuxInfoReader::createDetectorHeader ( const G4String & detectorVersion,
const G4GDMLAuxListType * auxInfoList )
private

Create the detector header from the global auxinfo.

Parameters
detectorVersionThe aux value with the detector version.
auxInfoListThe aux info with the detector header information.

Definition at line 374 of file AuxInfoReader.cxx.

375 {
376 int detector_version = atoi(auxValue.c_str());
377
378 std::string detector_name("");
379 std::string author("");
380 std::string description("");
381
382 for (const auto& aux_info : *auxInfoList) {
383 G4String aux_type = aux_info.type;
384 G4String aux_val = aux_info.value;
385
386 if (aux_type == "DetectorName") {
387 detector_name = aux_val;
388 } else if (aux_type == "Author") {
389 author = aux_val;
390 } else if (aux_type == "Description") {
391 description = aux_val;
392 }
393 }
394
395 detector_header_ = new ldmx::DetectorHeader(detector_name, detector_version,
396 description, author);
397
398 /*G4cout << G4endl;
399 G4cout << "Read detector header from userinfo: " << G4endl;
400 G4cout << " DetectorName: " << detector_header_->getName() << G4endl;
401 G4cout << " DetectorVersion: " << detector_header_->getVersion() << G4endl;
402 G4cout << " Author: " << detector_header_->getAuthor() << G4endl;
403 G4cout << " Description: " << detector_header_->getDescription() << G4endl;
404 G4cout << G4endl;*/
405}
Defines detector header information.

References detector_header_.

Referenced by readGlobalAuxInfo().

◆ createMagneticField()

void simcore::geo::AuxInfoReader::createMagneticField ( const G4String & name,
const G4GDMLAuxListType * auxInfoList )
private

Create a magnetic field from GDML data.

Parameters
nameThe name of the magnetic field.
auxInfoListThe aux info defining the magnetic field.

Definition at line 132 of file AuxInfoReader.cxx.

133 {
134 // Find type of the mag field.
135 G4String mag_field_type("");
136 for (const auto& aux_info : *auxInfoList) {
137 G4String aux_type = aux_info.type;
138 G4String aux_val = aux_info.value;
139
140 if (aux_type == "MagneticFieldType") {
141 mag_field_type = aux_val;
142 break;
143 }
144 }
145
146 if (mag_field_type == "") {
147 EXCEPTION_RAISE("MissingInfo",
148 "Missing MagFieldType for magnetic field definition.");
149 }
150
151 G4MagneticField* mag_field = nullptr;
152
153 // Create a uniform mag field using the built-in Geant4 type.
154 if (mag_field_type == "G4UniformMagField") {
155 double bx, by, bz;
156 bx = by = bz = 0.;
157 for (const auto& aux_info : *auxInfoList) {
158 G4String aux_type = aux_info.type;
159 G4String aux_val = aux_info.value;
160 G4String aux_unit = aux_info.unit;
161
162 G4String expr = aux_val + "*" + aux_unit;
163 if (aux_type == "bx") {
164 bx = eval_->Evaluate(expr);
165 } else if (aux_type == "by") {
166 by = eval_->Evaluate(expr);
167 } else if (aux_type == "bz") {
168 bz = eval_->Evaluate(expr);
169 }
170 }
171 G4ThreeVector field_components(bx, by, bz);
172 mag_field = new G4UniformMagField(field_components);
173
174 // G4cout << "Created G4UniformMagField " << magFieldName << " with field
175 // components " << fieldComponents << G4endl << G4endl;
176
177 // Create a global 3D field map by reading from a data file.
178 } else if (mag_field_type == "MagneticFieldMap3D") {
179 string file_name;
180 double offset_x{};
181 double offset_y{};
182 double offset_z{};
183
184 for (const auto& aux_info : *auxInfoList) {
185 G4String aux_type = aux_info.type;
186 G4String aux_val = aux_info.value;
187 G4String aux_unit = aux_info.unit;
188
189 G4String expr = aux_val + "*" + aux_unit;
190
191 if (aux_type == "File") {
192 file_name = aux_val;
193 } else if (aux_type == "OffsetX") {
194 offset_x = eval_->Evaluate(expr);
195 } else if (aux_type == "OffsetY") {
196 offset_y = eval_->Evaluate(expr);
197 } else if (aux_type == "OffsetZ") {
198 offset_z = eval_->Evaluate(expr);
199 }
200 }
201
202 if (file_name.size() == 0) {
203 EXCEPTION_RAISE("MissingInfo",
204 "File info with field data was not provided.");
205 }
206
207 // Create new 3D field map.
208 mag_field =
209 new MagneticFieldMap3D(file_name.c_str(), offset_x, offset_y, offset_z);
210
211 // Assign field map as global field.
212 G4FieldManager* field_mgr =
213 G4TransportationManager::GetTransportationManager()->GetFieldManager();
214 if (field_mgr->GetDetectorField() != nullptr) {
215 EXCEPTION_RAISE("MisAssign", "Global mag field was already assigned.");
216 }
217 field_mgr->SetDetectorField(mag_field);
218 field_mgr->CreateChordFinder(mag_field);
219
220 } else {
221 EXCEPTION_RAISE("UnknownType", "Unknown MagFieldType '" +
222 std::string(mag_field_type.data()) +
223 "' in auxiliary info.");
224 }
225
226 MagneticFieldStore::getInstance()->addMagneticField(magFieldName, mag_field);
227}
void addMagneticField(const std::string &name, G4MagneticField *magField)
Add a magnetic field by name.

References simcore::MagneticFieldStore::addMagneticField(), eval_, and simcore::MagneticFieldStore::getInstance().

Referenced by readGlobalAuxInfo().

◆ createRegion()

void simcore::geo::AuxInfoReader::createRegion ( const G4String & name,
const G4GDMLAuxListType * auxInfoList )
private

Create a detector region from GDML data.

Parameters
nameThe name of the detector region.
auxInfoListThe aux info defining the detector region.

Definition at line 229 of file AuxInfoReader.cxx.

230 {
231 bool store_trajectories = true;
232 for (const auto& aux_info : *auxInfoList) {
233 G4String aux_type = aux_info.type;
234 G4String aux_val = aux_info.value;
235
236 if (aux_type == "StoreTrajectories") {
237 if (aux_val == "false") {
238 store_trajectories = false;
239 } else if (aux_val == "true") {
240 store_trajectories = true;
241 }
242 }
243 }
244 G4VUserRegionInformation* region_info =
245 new UserRegionInformation(store_trajectories);
246 // This looks like a memory leak, but isn't. I (Einar) have checked. Geant4
247 // registers the region in the constructor and deletes it at the end.
248 //
249 // Some static analysis tools may struggle with identifying that this one
250 // happens to be fine. The NOLINT comment tells clang-tidy to not bother
251 // within the region
252 //
253 // NOLINTBEGIN
254 auto region = new G4Region(name);
255 region->SetUserInformation(region_info);
256 // To get rid of those pesky G4 warnings
257 region->SetProductionCuts(G4ProductionCutsTable::GetProductionCutsTable()
258 ->GetDefaultProductionCuts());
259}

Referenced by readGlobalAuxInfo().

◆ createVisAttributes()

void simcore::geo::AuxInfoReader::createVisAttributes ( const G4String & name,
const G4GDMLAuxListType * auxInfoList )
private

Create visualization attributes from GDML data.

Parameters
nameThe name of the visualization attributes.
auxInfoListThe aux info defining the visualization attributes.

Definition at line 289 of file AuxInfoReader.cxx.

290 {
291 std::array<G4double, 4> rgba = {1., 1., 1., 1.};
292 G4bool visible = true;
293 G4bool dau_invisible = false;
294 G4bool force_wireframe = false;
295 G4bool force_solid = false;
296 G4double line_width = 1.0;
297 G4VisAttributes::LineStyle line_style = G4VisAttributes::unbroken;
298
299 // There are some visattributes which should be accepted regardless of mode
300 universal_visattributes_ = {
301 "InvisibleNoDau", "InvisibleShowDau", "NoDau", "GrayWireFrame",
302 "BlueWireFrame", "BlueSolid", "Invisible", "SpVis"};
303 auto match = std::find(universal_visattributes_.begin(),
304 universal_visattributes_.end(), name);
305
306 // If a visattribute is not universal, a color mode is set, and the
307 // visattribute doesn't match the current mode, don't register it
308 if (match == universal_visattributes_.end() && color_mode_ != "" &&
309 name.find(color_mode_) == std::string::npos) {
310 ldmx_log(debug) << "VisAttribute " << name
311 << " doesn't match current mode. Skipping...";
312 return;
313 // Note that if color mode is not set, the last visattributes
314 // defined for each volume will be the active ones
315 }
316
317 for (const auto& aux_info : *auxInfoList) {
318 G4String aux_type = aux_info.type;
319 G4String aux_val = aux_info.value;
320
321 if (aux_type == "R") {
322 rgba[0] = atof(aux_val.c_str());
323 } else if (aux_type == "G") {
324 rgba[1] = atof(aux_val.c_str());
325 } else if (aux_type == "B") {
326 rgba[2] = atof(aux_val.c_str());
327 } else if (aux_type == "A") {
328 rgba[3] = atof(aux_val.c_str());
329 } else if (aux_type == "Style") {
330 if (aux_val == "wireframe") {
331 force_wireframe = true;
332 } else if (aux_val == "solid") {
333 force_solid = true;
334 }
335 } else if (aux_type == "DaughtersInvisible") {
336 if (aux_val == "true") {
337 dau_invisible = true;
338 } else if (aux_val == "false") {
339 dau_invisible = false;
340 }
341 } else if (aux_type == "Visible") {
342 if (aux_val == "true") {
343 visible = true;
344 } else if (aux_val == "false") {
345 visible = false;
346 }
347 } else if (aux_type == "LineStyle") {
348 if (aux_val == "unbroken") {
349 line_style = G4VisAttributes::unbroken;
350 } else if (aux_val == "dashed") {
351 line_style = G4VisAttributes::dashed;
352 } else if (aux_val == "dotted") {
353 line_style = G4VisAttributes::dotted;
354 }
355 } else if (aux_type == "LineWidth") {
356 line_width = atof(aux_val.c_str());
357 }
358 }
359
360 auto vis_attributes = new G4VisAttributes();
361 vis_attributes->SetColor(rgba[0], rgba[1], rgba[2], rgba[3]);
362 vis_attributes->SetVisibility(visible);
363 vis_attributes->SetDaughtersInvisible(dau_invisible);
364 vis_attributes->SetForceWireframe(force_wireframe);
365 vis_attributes->SetForceSolid(force_solid);
366 vis_attributes->SetLineWidth(line_width);
367 vis_attributes->SetLineStyle(line_style);
368 VisAttributesStore::getInstance()->addVisAttributes(name, vis_attributes);
369
370 // G4cout << "Created VisAttributes " << name << G4endl << (*visAttributes) <<
371 // G4endl << G4endl;
372}
void addVisAttributes(const std::string &name, G4VisAttributes *visAttributes)
Register a vis attributes by name.

References simcore::VisAttributesStore::addVisAttributes(), color_mode_, and simcore::VisAttributesStore::getInstance().

Referenced by readGlobalAuxInfo().

◆ getDetectorHeader()

ldmx::DetectorHeader * simcore::geo::AuxInfoReader::getDetectorHeader ( )
inline

Get the detector header that was created from the userinfo block.

Returns
The detector header.

Definition at line 56 of file AuxInfoReader.h.

56{ return detector_header_; }

References detector_header_.

◆ readGlobalAuxInfo()

void simcore::geo::AuxInfoReader::readGlobalAuxInfo ( )

Read the global auxiliary information from the auxinfo block.

Definition at line 39 of file AuxInfoReader.cxx.

39 {
40 const G4GDMLAuxListType* aux_info_list = parser_->GetAuxList();
41 for (const auto& aux_info : *aux_info_list) {
42 G4String aux_type = aux_info.type;
43 G4String aux_val = aux_info.value;
44
45 if (aux_type == "SensDet") {
46 std::cerr
47 << "[ WARN ] : Not defining SensDet in GDML since v1.0 of SimCore. "
48 "See https://github.com/LDMX-Software/SimCore/issues/39"
49 << std::endl;
50 } else if (aux_type == "MagneticField") {
51 createMagneticField(aux_val, aux_info.auxList);
52 } else if (aux_type == "Region") {
53 createRegion(aux_val, aux_info.auxList);
54 } else if (aux_type == "ColorMode") {
55 selectColorMode(aux_val);
56 } else if (aux_type == "VisAttributes") {
57 createVisAttributes(aux_val, aux_info.auxList);
58 } else if (aux_type == "DetectorVersion") {
59 createDetectorHeader(aux_val, aux_info.auxList);
60 }
61 }
62 return;
63}
void createDetectorHeader(const G4String &detectorVersion, const G4GDMLAuxListType *auxInfoList)
Create the detector header from the global auxinfo.
void createVisAttributes(const G4String &name, const G4GDMLAuxListType *auxInfoList)
Create visualization attributes from GDML data.
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.
void selectColorMode(const G4String &mode)
Select the 'mode' for coloring in the visualization.

References createDetectorHeader(), createMagneticField(), createRegion(), createVisAttributes(), parser_, and selectColorMode().

◆ selectColorMode()

void simcore::geo::AuxInfoReader::selectColorMode ( const G4String & mode)
private

Select the 'mode' for coloring in the visualization.

Parameters
nameThe selected mode

Definition at line 262 of file AuxInfoReader.cxx.

262 {
263 // Chooses which coloring scheme to use for the visattributes
264 // Currently (March 2026) there are two modes implemented:
265 // Region: Only visattributes with "Region" in the name will be applied
266 // Material: Only visattributes with "Material" in the name will be applied
267 // The Region mode colors all volumes in the same subdetector the same color
268 // For example, all volumes in the HCal will be colored orange
269 // The Material mode colors each volume based on which material it's made from
270 //'Unimportant' materials (like glue) are left uncolored or invisible
271 // To add more modes follow these steps:
272 // 1) Make more visattributes in 'visattributes.gdml'
273 // Your new attribute names must share a common string, like "Region"
274 // 2) Add the shared string as a valid option in this function
275
276 std::vector<std::string> valid_modes = {"Region", "Material"};
277
278 auto match = std::find(valid_modes.begin(), valid_modes.end(), mode);
279
280 if (match == valid_modes.end()) {
281 EXCEPTION_RAISE("InvalidMode", "Color mode setting " + mode +
282 " doesn't match any available modes!");
283 }
284
285 // If the input matches a valid mode (doesn't matter which one), proceed
286 color_mode_ = mode;
287}

References color_mode_.

Referenced by readGlobalAuxInfo().

Member Data Documentation

◆ color_mode_

std::string simcore::geo::AuxInfoReader::color_mode_
private

Color mode for visattributes.

Definition at line 115 of file AuxInfoReader.h.

Referenced by assignAuxInfoToVolumes(), createVisAttributes(), and selectColorMode().

◆ detector_header_

ldmx::DetectorHeader* simcore::geo::AuxInfoReader::detector_header_ {nullptr}
private

Detector header with name and version.

Definition at line 110 of file AuxInfoReader.h.

110{nullptr};

Referenced by createDetectorHeader(), getDetectorHeader(), and ~AuxInfoReader().

◆ eval_

G4GDMLEvaluator* simcore::geo::AuxInfoReader::eval_
private

The GDML expression evaluator.

Definition at line 105 of file AuxInfoReader.h.

Referenced by createMagneticField(), and ~AuxInfoReader().

◆ parser_

G4GDMLParser* simcore::geo::AuxInfoReader::parser_
private

The GDML parser.

Definition at line 100 of file AuxInfoReader.h.

Referenced by assignAuxInfoToVolumes(), and readGlobalAuxInfo().

◆ universal_visattributes_

std::vector<std::string> simcore::geo::AuxInfoReader::universal_visattributes_
private

Definition at line 116 of file AuxInfoReader.h.


The documentation for this class was generated from the following files: