REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGDMLParser.cxx
1 #include "TRestGDMLParser.h"
2 
3 #include <filesystem>
4 
5 using namespace std;
6 
7 string 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 
16 void 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);
36  fGdmlVersion = ReplaceMathematicalExpressions(ReplaceConstants(ReplaceVariables(fGdmlVersion)));
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);
47  fElementGlobal = GetElement("define", fElement);
48 
49  LoadSectionMetadata();
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 
84 TGeoManager* 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 
97 void TRestGDMLParser::PrintContent() { cout << fFileString << endl; }
98 
99 void 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 
133  str = ReplaceConstants(ReplaceVariables(str));
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 
157 void 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);
175  string replace = ReplaceMathematicalExpressions(ReplaceConstants(ReplaceVariables(target)));
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 }
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.