REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGeant4GeometryInfo.cxx
1//
2// Created by lobis on 3/5/2022.
3//
4
5#include "TRestGeant4GeometryInfo.h"
6
7#include <TPRegexp.h>
8#include <TXMLEngine.h>
9
10#include <iostream>
11
12using namespace std;
13
14namespace myXml {
15XMLNodePointer_t FindChildByName(TXMLEngine xml, XMLNodePointer_t node, const TString& name) {
16 XMLNodePointer_t child = xml.GetChild(node);
17 while (child) {
18 TString childName = xml.GetNodeName(child);
19 if (childName.EqualTo(name)) {
20 return child;
21 }
22 child = xml.GetNext(child);
23 }
24 return nullptr;
25}
26TString GetNodeAttribute(TXMLEngine xml, XMLNodePointer_t node, const TString& attributeName) {
27 XMLAttrPointer_t attr = xml.GetFirstAttr(node);
28 while (attr) {
29 if (TString(xml.GetAttrName(attr)).EqualTo(attributeName)) {
30 TString refName = xml.GetAttrValue(attr);
31 return refName;
32 }
33 attr = xml.GetNextAttr(attr);
34 }
35 return {};
36}
37void AddVolumesRecursively(vector<TString>* physicalNames, vector<TString>* logicalNames,
38 const vector<TString>& children, map<TString, TString>& nameTable,
39 map<TString, vector<TString>>& childrenTable, const TString& name = "") {
40 if (children.empty()) {
41 physicalNames->push_back(name);
42 const auto logicalVolumeName = nameTable[name];
43 logicalNames->push_back(logicalVolumeName);
44 return;
45 }
46 for (const auto& childName : children) {
47 const auto newName = name + "_" + childName;
48 nameTable[newName] = nameTable[childName]; // needed to retrieve logical volume name
49 AddVolumesRecursively(physicalNames, logicalNames, childrenTable[nameTable[childName]], nameTable,
50 childrenTable, newName);
51 }
52}
53} // namespace myXml
54
55void TRestGeant4GeometryInfo::PopulateFromGdml(const TString& gdmlFilename) {
56 /*
57 * Fills 'fGdmlNewPhysicalNames' with physical volume names generated from GDML
58 */
59 cout << "TRestGeant4GeometryInfo::PopulateFromGdml - " << gdmlFilename << endl;
60 // Geometry must be in GDML
61 TXMLEngine xml;
62 XMLDocPointer_t xmldoc = xml.ParseFile(gdmlFilename.Data());
63 if (!xmldoc) {
64 cout << "TRestGeant4GeometryInfo::PopulateFromGdml - GDML file " << gdmlFilename.Data()
65 << " not found" << endl;
66 exit(1);
67 }
68 map<TString, TString> nameTable;
69 map<TString, vector<TString>> childrenTable;
70 XMLNodePointer_t mainNode = xml.DocGetRootElement(xmldoc);
71 XMLNodePointer_t structure = myXml::FindChildByName(xml, mainNode, "structure");
72 XMLNodePointer_t child = xml.GetChild(structure);
73 while (child) {
74 TString name = xml.GetNodeName(child);
75 TString volumeName = myXml::GetNodeAttribute(xml, child, "name");
76 auto physicalVolumeNode = xml.GetChild(child);
77 childrenTable[volumeName] = {};
78 while (physicalVolumeNode) {
79 auto physicalVolumeName = myXml::GetNodeAttribute(xml, physicalVolumeNode, "name");
80 auto volumeRefNode = xml.GetChild(physicalVolumeNode);
81 while (volumeRefNode) {
82 TString volumeRefNodeName = xml.GetNodeName(volumeRefNode);
83 if (volumeRefNodeName.EqualTo("volumeref")) {
84 TString refName = myXml::GetNodeAttribute(xml, volumeRefNode, "ref");
85 nameTable[physicalVolumeName] = refName;
86 childrenTable[volumeName].push_back(physicalVolumeName);
87 }
88 volumeRefNode = xml.GetNext(volumeRefNode);
89 }
90 physicalVolumeNode = xml.GetNext(physicalVolumeNode);
91 }
92 child = xml.GetNext(child);
93 }
94
95 string worldVolumeName = "world";
96 if (childrenTable.count(worldVolumeName) == 0) {
97 worldVolumeName = "World";
98 if (childrenTable.count(worldVolumeName) == 0) {
99 cout << "Could not find world volume in GDML, please name it either 'World' or 'world'";
100 exit(1);
101 }
102 }
103
104 fGdmlNewPhysicalNames.clear();
105 fGdmlLogicalNames.clear();
106 for (const auto& topName : childrenTable[worldVolumeName]) {
107 auto children = childrenTable[nameTable[topName]];
108 myXml::AddVolumesRecursively(&fGdmlNewPhysicalNames, &fGdmlLogicalNames, children, nameTable,
109 childrenTable, topName);
110 }
111
112 xml.FreeDoc(xmldoc);
113
114 // Checks
115 if (fGdmlNewPhysicalNames.empty()) {
116 cout << "TRestGeant4GeometryInfo::PopulateFromGdml - ERROR - No physical volumes have been added!"
117 << endl;
118 exit(1);
119 }
120 // Find duplicates
121 set<TString> s;
122 for (const auto& name : fGdmlNewPhysicalNames) {
123 s.insert(name);
124 }
125 if (s.size() != fGdmlNewPhysicalNames.size()) {
126 cout << "TRestGeant4GeometryInfo::PopulateFromGdml - ERROR - Generated a duplicate name, please "
127 "check assembly"
128 << endl;
129 exit(1);
130 }
131}
132
133TString TRestGeant4GeometryInfo::GetAlternativeNameFromGeant4PhysicalName(
134 const TString& geant4PhysicalName) const {
135 if (fGeant4PhysicalNameToNewPhysicalNameMap.count(geant4PhysicalName) > 0) {
136 return fGeant4PhysicalNameToNewPhysicalNameMap.at(geant4PhysicalName);
137 }
138 return geant4PhysicalName;
139}
140
141TString TRestGeant4GeometryInfo::GetGeant4PhysicalNameFromAlternativeName(
142 const TString& alternativeName) const {
143 for (const auto& kv : fGeant4PhysicalNameToNewPhysicalNameMap) {
144 if (kv.second == alternativeName) {
145 return kv.first;
146 }
147 }
148 return "";
149}
150
151template <typename T, typename U>
152U GetOrDefaultMapValueFromKey(const map<T, U>* pMap, const T& key) {
153 if (pMap->count(key) > 0) {
154 return pMap->at(key);
155 }
156 return {};
157}
158
159TString TRestGeant4GeometryInfo::GetVolumeFromID(Int_t id) const {
160 return GetOrDefaultMapValueFromKey<Int_t, TString>(&fVolumeNameMap, id);
161}
162
163Int_t TRestGeant4GeometryInfo::GetIDFromVolume(const TString& volumeName) const {
164 if (fVolumeNameReverseMap.count(volumeName) == 0) {
165 // if we do not find the volume we return -1 instead of default (which is 0 and may be confusing)
166 cout << "TRestGeant4GeometryInfo::GetIDFromVolume - volume '" << volumeName << "' not found in store!"
167 << endl;
168 return -1;
169 }
170 return GetOrDefaultMapValueFromKey<TString, Int_t>(&fVolumeNameReverseMap, volumeName);
171}
172
173void TRestGeant4GeometryInfo::InsertVolumeName(Int_t id, const TString& volumeName) {
174 fVolumeNameMap[id] = volumeName;
175 fVolumeNameReverseMap[volumeName] = id;
176}
177
178void TRestGeant4GeometryInfo::Print() const {
179 cout << "Assembly Geometry: " << (fIsAssembly ? "yes" : "no") << endl;
180
181 const auto physicalVolumes = GetAllPhysicalVolumes();
182 cout << "Physical volumes (" << physicalVolumes.size() << "):" << endl;
183 for (const auto& physical : GetAllPhysicalVolumes()) {
184 auto geant4Name = GetGeant4PhysicalNameFromAlternativeName(physical);
185 const auto& logical = fPhysicalToLogicalVolumeMap.at(physical);
186 const auto& position = GetPosition(physical);
187 cout << "\t- " << (geant4Name == physical ? physical : physical + " (" + geant4Name + ")")
188 << " - ID: " << GetIDFromVolume(physical)
189 << " - Logical: " << fPhysicalToLogicalVolumeMap.at(physical)
190 << " - Material: " << fLogicalToMaterialMap.at(logical) //
191 << " - Position: (" << position.X() << ", " << position.Y() << ", " << position.Z() << ") mm" //
192 << endl;
193 }
194
195 const auto logicalVolumes = GetAllLogicalVolumes();
196 cout << "Logical volumes (" << logicalVolumes.size() << "):" << endl;
197 for (const auto& logical : logicalVolumes) {
198 cout << "\t- " << logical << endl;
199 }
200}
201
202std::vector<TString> TRestGeant4GeometryInfo::GetAllLogicalVolumes() const {
203 auto volumes = std::vector<TString>();
204
205 for (const auto& kv : fLogicalToPhysicalMap) {
206 volumes.emplace_back(kv.first);
207 }
208
209 return volumes;
210}
211
212std::vector<TString> TRestGeant4GeometryInfo::GetAllPhysicalVolumes() const {
213 auto volumes = std::vector<TString>();
214
215 for (const auto& kv : fPhysicalToLogicalVolumeMap) {
216 volumes.emplace_back(kv.first);
217 }
218
219 return volumes;
220}
221
222std::vector<TString> TRestGeant4GeometryInfo::GetAllAlternativePhysicalVolumes() const {
223 auto volumes = std::vector<TString>();
224
225 for (const auto& kv : fPhysicalToLogicalVolumeMap) {
226 volumes.emplace_back(GetAlternativeNameFromGeant4PhysicalName(kv.first));
227 }
228
229 return volumes;
230}
231
232std::vector<TString> TRestGeant4GeometryInfo::GetAllPhysicalVolumesMatchingExpression(
233 const TString& regularExpression) const {
234 auto volumes = std::vector<TString>();
235
236 TPRegexp regex(regularExpression);
237
238 for (const auto& volume : GetAllPhysicalVolumes()) {
239 if (regex.Match(volume)) {
240 volumes.emplace_back(volume);
241 }
242 }
243
244 return volumes;
245}
246
247std::vector<TString> TRestGeant4GeometryInfo::GetAllLogicalVolumesMatchingExpression(
248 const TString& regularExpression) const {
249 auto volumes = std::vector<TString>();
250
251 TPRegexp regex(regularExpression);
252
253 for (const auto& volume : GetAllLogicalVolumes()) {
254 if (regex.Match(volume)) {
255 volumes.emplace_back(volume);
256 }
257 }
258
259 return volumes;
260}