5#include "TRestGeant4GeometryInfo.h"
15XMLNodePointer_t FindChildByName(TXMLEngine xml, XMLNodePointer_t node,
const TString& name) {
16 XMLNodePointer_t child = xml.GetChild(node);
18 TString childName = xml.GetNodeName(child);
19 if (childName.EqualTo(name)) {
22 child = xml.GetNext(child);
26TString GetNodeAttribute(TXMLEngine xml, XMLNodePointer_t node,
const TString& attributeName) {
27 XMLAttrPointer_t attr = xml.GetFirstAttr(node);
29 if (TString(xml.GetAttrName(attr)).EqualTo(attributeName)) {
30 TString refName = xml.GetAttrValue(attr);
33 attr = xml.GetNextAttr(attr);
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);
46 for (
const auto& childName : children) {
47 const auto newName = name +
"_" + childName;
48 nameTable[newName] = nameTable[childName];
49 AddVolumesRecursively(physicalNames, logicalNames, childrenTable[nameTable[childName]], nameTable,
50 childrenTable, newName);
55void TRestGeant4GeometryInfo::PopulateFromGdml(
const TString& gdmlFilename) {
59 cout <<
"TRestGeant4GeometryInfo::PopulateFromGdml - " << gdmlFilename << endl;
62 XMLDocPointer_t xmldoc = xml.ParseFile(gdmlFilename.Data());
64 cout <<
"TRestGeant4GeometryInfo::PopulateFromGdml - GDML file " << gdmlFilename.Data()
65 <<
" not found" << endl;
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);
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);
88 volumeRefNode = xml.GetNext(volumeRefNode);
90 physicalVolumeNode = xml.GetNext(physicalVolumeNode);
92 child = xml.GetNext(child);
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'";
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);
115 if (fGdmlNewPhysicalNames.empty()) {
116 cout <<
"TRestGeant4GeometryInfo::PopulateFromGdml - ERROR - No physical volumes have been added!"
122 for (
const auto& name : fGdmlNewPhysicalNames) {
125 if (s.size() != fGdmlNewPhysicalNames.size()) {
126 cout <<
"TRestGeant4GeometryInfo::PopulateFromGdml - ERROR - Generated a duplicate name, please "
133TString TRestGeant4GeometryInfo::GetAlternativeNameFromGeant4PhysicalName(
134 const TString& geant4PhysicalName)
const {
135 if (fGeant4PhysicalNameToNewPhysicalNameMap.count(geant4PhysicalName) > 0) {
136 return fGeant4PhysicalNameToNewPhysicalNameMap.at(geant4PhysicalName);
138 return geant4PhysicalName;
141TString TRestGeant4GeometryInfo::GetGeant4PhysicalNameFromAlternativeName(
142 const TString& alternativeName)
const {
143 for (
const auto& kv : fGeant4PhysicalNameToNewPhysicalNameMap) {
144 if (kv.second == alternativeName) {
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);
159TString TRestGeant4GeometryInfo::GetVolumeFromID(Int_t
id)
const {
160 return GetOrDefaultMapValueFromKey<Int_t, TString>(&fVolumeNameMap,
id);
163Int_t TRestGeant4GeometryInfo::GetIDFromVolume(
const TString& volumeName)
const {
164 if (fVolumeNameReverseMap.count(volumeName) == 0) {
166 cout <<
"TRestGeant4GeometryInfo::GetIDFromVolume - volume '" << volumeName <<
"' not found in store!"
170 return GetOrDefaultMapValueFromKey<TString, Int_t>(&fVolumeNameReverseMap, volumeName);
173void TRestGeant4GeometryInfo::InsertVolumeName(Int_t
id,
const TString& volumeName) {
174 fVolumeNameMap[id] = volumeName;
175 fVolumeNameReverseMap[volumeName] = id;
178void TRestGeant4GeometryInfo::Print()
const {
179 cout <<
"Assembly Geometry: " << (fIsAssembly ?
"yes" :
"no") << endl;
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"
195 const auto logicalVolumes = GetAllLogicalVolumes();
196 cout <<
"Logical volumes (" << logicalVolumes.size() <<
"):" << endl;
197 for (
const auto& logical : logicalVolumes) {
198 cout <<
"\t- " << logical << endl;
202std::vector<TString> TRestGeant4GeometryInfo::GetAllLogicalVolumes()
const {
203 auto volumes = std::vector<TString>();
205 for (
const auto& kv : fLogicalToPhysicalMap) {
206 volumes.emplace_back(kv.first);
212std::vector<TString> TRestGeant4GeometryInfo::GetAllPhysicalVolumes()
const {
213 auto volumes = std::vector<TString>();
215 for (
const auto& kv : fPhysicalToLogicalVolumeMap) {
216 volumes.emplace_back(kv.first);
222std::vector<TString> TRestGeant4GeometryInfo::GetAllAlternativePhysicalVolumes()
const {
223 auto volumes = std::vector<TString>();
225 for (
const auto& kv : fPhysicalToLogicalVolumeMap) {
226 volumes.emplace_back(GetAlternativeNameFromGeant4PhysicalName(kv.first));
232std::vector<TString> TRestGeant4GeometryInfo::GetAllPhysicalVolumesMatchingExpression(
233 const TString& regularExpression)
const {
234 auto volumes = std::vector<TString>();
236 TPRegexp regex(regularExpression);
238 for (
const auto& volume : GetAllPhysicalVolumes()) {
239 if (regex.Match(volume)) {
240 volumes.emplace_back(volume);
247std::vector<TString> TRestGeant4GeometryInfo::GetAllLogicalVolumesMatchingExpression(
248 const TString& regularExpression)
const {
249 auto volumes = std::vector<TString>();
251 TPRegexp regex(regularExpression);
253 for (
const auto& volume : GetAllLogicalVolumes()) {
254 if (regex.Match(volume)) {
255 volumes.emplace_back(volume);