REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
Loading...
Searching...
No Matches
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 delete fElementGlobal;
47 delete fElement;
48 fElement = StringToElement(elementString);
49 // TRestMetadata owns and deletes both XML trees independently. The
50 // define element is a child of fElement, so it must not be owned twice.
51 const auto define = GetElement("define", fElement);
52 fElementGlobal = define == nullptr ? nullptr : new TiXmlElement(*define);
53
55 }
56
57 cout << "TRestGDMLParser: Replacing expressions in GDML" << endl;
58 ReplaceEntity();
59 fFileString = Replace(fFileString, "= \"", "=\"");
60 fFileString = Replace(fFileString, " =\"", "=\"");
61 fFileString = Replace(fFileString, " = \"", "=\"");
62
63 ReplaceAttributeWithKeyWord("cos(");
64 ReplaceAttributeWithKeyWord("sin(");
65 ReplaceAttributeWithKeyWord("tan(");
66 ReplaceAttributeWithKeyWord("sqrt(");
67 ReplaceAttributeWithKeyWord("log(");
68 ReplaceAttributeWithKeyWord("exp(");
69
70 string filenameNoPath = TRestTools::SeparatePathAndName(filenameAbsolute).second;
71 // we have to use a unique identifier on the file to prevent collision when launching multiple jobs
72 fOutputGdmlFilename = fOutputGdmlDirectory + "PID" + std::to_string(getpid()) + "_" + filenameNoPath;
73 cout << "TRestGDMLParser: Creating temporary file at: \"" << fOutputGdmlFilename << "\"" << endl;
74
75 filesystem::create_directories(fOutputGdmlDirectory);
76
77 ofstream outputFile;
78 outputFile.open(fOutputGdmlFilename, ios::trunc);
79 outputFile << fFileString << endl;
80 outputFile.close();
81
82 std::ifstream fileToCheckExistence(fOutputGdmlFilename);
83 if (!fileToCheckExistence) {
84 std::cout << "TRestGDMLParser: Problem writing temporary file." << std::endl;
85 exit(1);
86 }
87}
88
89TGeoManager* TRestGDMLParser::CreateGeoManager() {
90 // We must change to the gdml file directory, otherwise ROOT cannot load.
91 if (!fOutputGdmlFilename.empty()) {
92 const auto currentPath = filesystem::current_path();
93 filesystem::current_path(fOutputGdmlDirectory);
94 auto geoManager = new TGeoManager();
95 geoManager->Import(fOutputGdmlFilename.c_str());
96 filesystem::current_path(currentPath);
97 return geoManager;
98 }
99 return nullptr;
100}
101
102void TRestGDMLParser::PrintContent() { cout << fFileString << endl; }
103
104void TRestGDMLParser::ReplaceEntity() {
105 int pos = 0;
106 while ((pos = fFileString.find("<!ENTITY", pos)) != -1) {
107 int pos1 = fFileString.find_first_not_of(" ", pos + 8);
108 int pos2 = fFileString.find("SYSTEM", pos1);
109 string entityName = RemoveWhiteSpaces(fFileString.substr(pos1, pos2 - pos1));
110
111 int pos3 = fFileString.find("\"", pos2) + 1;
112 int pos4 = fFileString.find("\"", pos3);
113 string entityFile = RemoveWhiteSpaces(fFileString.substr(pos3, pos4 - pos3));
114
115 cout << "TRestGDMLParser: Replacing entity: " << entityName << ", file: " << entityFile << endl;
116
117 if ((int)entityFile.find("http") != -1) {
118 string entityField =
119 fOutputGdmlDirectory + "PID" + std::to_string(getpid()) + "_" + entityName + ".xml";
120 int a = TRestTools::DownloadRemoteFile(entityFile, entityField);
121 if (a != 0) {
122 cout << "TRestGDMLParser: Download failed!" << endl;
123 exit(1);
124 }
125 entityFile = entityField;
126 } else {
127 entityFile = fPath + "/" + entityFile;
128 }
129
130 int pos5 = 0;
131 if ((pos5 = fFileString.find("&" + entityName + ";")) != -1) {
132 if (TRestTools::fileExists(entityFile)) {
133 std::ifstream entityFileRead(entityFile);
134 std::string str((std::istreambuf_iterator<char>(entityFileRead)),
135 std::istreambuf_iterator<char>());
136 entityFileRead.close();
137
139
140 fEntityVersionMap[entityName] = "";
141 size_t pp = str.find("##VERSION", 0);
142 if (pp != string::npos) {
143 size_t pp2 = str.find("##", pp + 4);
144 if (pp2 != string::npos) {
145 fEntityVersionMap[entityName] = str.substr(pp + 9, pp2 - pp - 9);
146 }
147 }
148
149 fFileString.replace(pos5, entityName.length() + 2, str);
150 } else {
151 cout << "GDML ERROR! No matching reference file for entity: \"" << entityName << "\"" << endl;
152 cout << "file name: \"" << entityFile << "\"" << endl;
153 exit(1);
154 }
155 } else {
156 cout << "TRestGDMLParser: Warning! redundant entity: \"" << entityName << "\"" << endl;
157 }
158 pos++;
159 }
160}
161
162void TRestGDMLParser::ReplaceAttributeWithKeyWord(const string& keyword) {
163 int n;
164 while ((n = fFileString.find(keyword, 0)) != -1) {
165 int pos1 = 0, pos2 = 0;
166 for (int i = n; i >= 0; i--) {
167 if (fFileString[i] == '"') {
168 pos1 = i + 1;
169 break;
170 }
171 }
172
173 for (unsigned int i = n; i < fFileString.size(); i++) {
174 if (fFileString[i] == '"') {
175 pos2 = i;
176 break;
177 }
178 }
179 string target = fFileString.substr(pos1, pos2 - pos1);
181
182 if (replace == target) {
183 cout << "Error! failed to replace mathematical expressions! check the file!" << endl;
184 cout << replace << endl;
185 exit(1);
186 }
187 fFileString.replace(pos1, pos2 - pos1, replace);
188 }
189}
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.
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
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.
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.