REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGDMLParser.cxx
1#include "TRestGDMLParser.h"
2
3#include <filesystem>
4
5using namespace std;
6
7string TRestGDMLParser::GetEntityVersion(const string& name) const {
8 for (auto& [entityName, entityVersion] : fEntityVersionMap) {
9 if (entityName == name) {
10 return entityVersion;
11 }
12 }
13 return "0.0";
14}
15
16void TRestGDMLParser::Load(const string& filename) {
17 const string filenameAbsolute = TRestTools::ToAbsoluteName(filename);
18 if (!TRestTools::fileExists(filenameAbsolute)) {
19 RESTError << "TRestGDMLParser: Input GDML file: \"" << filenameAbsolute
20 << "\" does not exist. Please double check your current path and filename" << RESTendl;
21 exit(1);
22 }
23
24 fConfigFileName = filenameAbsolute;
25 fPath = TRestTools::SeparatePathAndName(filenameAbsolute).first;
26
27 std::ifstream t(filenameAbsolute);
28 std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
29 fFileString = str;
30 t.close();
31
32 size_t pp = fFileString.find("##VERSION", 0);
33 if (pp != string::npos) {
34 size_t pp2 = fFileString.find("##", pp + 4);
35 if (pp2 != string::npos) fGdmlVersion = fFileString.substr(pp + 9, pp2 - pp - 9);
37 }
38
39 fFileString = ReplaceConstants(ReplaceVariables(fFileString));
40
41 cout << "TRestGDMLParser: Initializing variables" << endl;
42 int pos = fFileString.find("<gdml", 0);
43 if (pos != -1) {
44 string elementString = fFileString.substr(pos, -1);
45
46 fElement = StringToElement(elementString);
48
50 }
51
52 cout << "TRestGDMLParser: Replacing expressions in GDML" << endl;
53 ReplaceEntity();
54 fFileString = Replace(fFileString, "= \"", "=\"");
55 fFileString = Replace(fFileString, " =\"", "=\"");
56 fFileString = Replace(fFileString, " = \"", "=\"");
57
58 ReplaceAttributeWithKeyWord("cos(");
59 ReplaceAttributeWithKeyWord("sin(");
60 ReplaceAttributeWithKeyWord("tan(");
61 ReplaceAttributeWithKeyWord("sqrt(");
62 ReplaceAttributeWithKeyWord("log(");
63 ReplaceAttributeWithKeyWord("exp(");
64
65 string filenameNoPath = TRestTools::SeparatePathAndName(filenameAbsolute).second;
66 // we have to use a unique identifier on the file to prevent collision when launching multiple jobs
67 fOutputGdmlFilename = fOutputGdmlDirectory + "PID" + std::to_string(getpid()) + "_" + filenameNoPath;
68 cout << "TRestGDMLParser: Creating temporary file at: \"" << fOutputGdmlFilename << "\"" << endl;
69
70 filesystem::create_directories(fOutputGdmlDirectory);
71
72 ofstream outputFile;
73 outputFile.open(fOutputGdmlFilename, ios::trunc);
74 outputFile << fFileString << endl;
75 outputFile.close();
76
77 std::ifstream fileToCheckExistence(fOutputGdmlFilename);
78 if (!fileToCheckExistence) {
79 std::cout << "TRestGDMLParser: Problem writing temporary file." << std::endl;
80 exit(1);
81 }
82}
83
84TGeoManager* TRestGDMLParser::CreateGeoManager() {
85 // We must change to the gdml file directory, otherwise ROOT cannot load.
86 if (!fOutputGdmlFilename.empty()) {
87 const auto currentPath = filesystem::current_path();
88 filesystem::current_path(fOutputGdmlDirectory);
89 auto geoManager = new TGeoManager();
90 geoManager->Import(fOutputGdmlFilename.c_str());
91 filesystem::current_path(currentPath);
92 return geoManager;
93 }
94 return nullptr;
95}
96
97void TRestGDMLParser::PrintContent() { cout << fFileString << endl; }
98
99void TRestGDMLParser::ReplaceEntity() {
100 int pos = 0;
101 while ((pos = fFileString.find("<!ENTITY", pos)) != -1) {
102 int pos1 = fFileString.find_first_not_of(" ", pos + 8);
103 int pos2 = fFileString.find("SYSTEM", pos1);
104 string entityName = RemoveWhiteSpaces(fFileString.substr(pos1, pos2 - pos1));
105
106 int pos3 = fFileString.find("\"", pos2) + 1;
107 int pos4 = fFileString.find("\"", pos3);
108 string entityFile = RemoveWhiteSpaces(fFileString.substr(pos3, pos4 - pos3));
109
110 cout << "TRestGDMLParser: Replacing entity: " << entityName << ", file: " << entityFile << endl;
111
112 if ((int)entityFile.find("http") != -1) {
113 string entityField =
114 fOutputGdmlDirectory + "PID" + std::to_string(getpid()) + "_" + entityName + ".xml";
115 int a = TRestTools::DownloadRemoteFile(entityFile, entityField);
116 if (a != 0) {
117 cout << "TRestGDMLParser: Download failed!" << endl;
118 exit(1);
119 }
120 entityFile = entityField;
121 } else {
122 entityFile = fPath + "/" + entityFile;
123 }
124
125 int pos5 = 0;
126 if ((pos5 = fFileString.find("&" + entityName + ";")) != -1) {
127 if (TRestTools::fileExists(entityFile)) {
128 std::ifstream entityFileRead(entityFile);
129 std::string str((std::istreambuf_iterator<char>(entityFileRead)),
130 std::istreambuf_iterator<char>());
131 entityFileRead.close();
132
134
135 fEntityVersionMap[entityName] = "";
136 size_t pp = str.find("##VERSION", 0);
137 if (pp != string::npos) {
138 size_t pp2 = str.find("##", pp + 4);
139 if (pp2 != string::npos) {
140 fEntityVersionMap[entityName] = str.substr(pp + 9, pp2 - pp - 9);
141 }
142 }
143
144 fFileString.replace(pos5, entityName.length() + 2, str);
145 } else {
146 cout << "GDML ERROR! No matching reference file for entity: \"" << entityName << "\"" << endl;
147 cout << "file name: \"" << entityFile << "\"" << endl;
148 exit(1);
149 }
150 } else {
151 cout << "TRestGDMLParser: Warning! redundant entity: \"" << entityName << "\"" << endl;
152 }
153 pos++;
154 }
155}
156
157void TRestGDMLParser::ReplaceAttributeWithKeyWord(const string& keyword) {
158 int n;
159 while ((n = fFileString.find(keyword, 0)) != -1) {
160 int pos1 = 0, pos2 = 0;
161 for (int i = n; i >= 0; i--) {
162 if (fFileString[i] == '"') {
163 pos1 = i + 1;
164 break;
165 }
166 }
167
168 for (unsigned int i = n; i < fFileString.size(); i++) {
169 if (fFileString[i] == '"') {
170 pos2 = i;
171 break;
172 }
173 }
174 string target = fFileString.substr(pos1, pos2 - pos1);
176
177 if (replace == target) {
178 cout << "Error! failed to replace mathematical expressions! check the file!" << endl;
179 cout << replace << endl;
180 exit(1);
181 }
182 fFileString.replace(pos1, pos2 - pos1, replace);
183 }
184}
endl_t RESTendl
Termination flag object for TRestStringOutput.
TiXmlElement * GetElement(std::string eleDeclare, TiXmlElement *e=nullptr)
Get an xml element from a given parent element, according to its declaration.
TiXmlElement * fElementGlobal
Saving the global element, to be passed to the resident class, if necessary.
TiXmlElement * StringToElement(std::string definition)
Parsing a string into TiXmlElement object.
std::string ReplaceVariables(const std::string buffer)
Identifies environmental variable replacing marks in the input buffer, and replace them with correspo...
virtual Int_t LoadSectionMetadata()
This method does some preparation of xml section.
std::string fConfigFileName
Full name of the rml file.
std::string ReplaceConstants(const std::string buffer)
Identifies "constants" in the input buffer, and replace them with corresponding value.
TiXmlElement * fElement
Saving the sectional element together with global element.
static std::pair< std::string, std::string > SeparatePathAndName(const std::string &fullname)
Separate path and filename in a full path+filename string, returns a pair of string.
Definition: TRestTools.cxx:813
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
static std::string DownloadRemoteFile(const std::string &remoteFile, bool pidPrefix=false)
download the remote file automatically, returns the downloaded file name.
static std::string ToAbsoluteName(const std::string &filename)
It takes a path and returns its absolute path.
Definition: TRestTools.cxx:868
std::string RemoveWhiteSpaces(std::string in)
Returns the input string removing all white spaces.
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.
std::string ReplaceMathematicalExpressions(std::string buffer, Int_t precision=0, std::string errorMessage="")
Evaluates and replaces valid mathematical expressions found in the input string buffer.