REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestTools.cxx
1 /******************** REST disclaimer ***********************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
44 #include "TRestTools.h"
45 
46 #include <TClass.h>
47 #include <TFile.h>
48 #include <TKey.h>
49 #include <TSystem.h>
50 #include <TUrl.h>
51 
52 #include <regex>
53 
54 #ifdef USE_Curl
55 #include <curl/curl.h>
56 #endif
57 
58 #ifdef WIN32
59 #include <io.h>
60 #else
61 #include "unistd.h"
62 #endif // !WIN32
63 
64 #ifdef __APPLE__
65 #include <array>
66 #endif
67 
68 #include <chrono>
69 #include <filesystem>
70 #include <iostream>
71 #include <limits>
72 #include <memory>
73 #include <thread>
74 
75 #include "TRestStringHelper.h"
76 #include "TRestStringOutput.h"
77 
78 using namespace std;
79 
86 std::vector<string> TRestTools::GetOptions(string optionsStr) { return Split(optionsStr, ":"); }
87 
95 void TRestTools::LoadRESTLibrary(bool silent) {
96  const set<string> libraryExtension{".so", ".dylib", ".dll"};
97  const set<string> excludedLibraries{
98  "RestG4"}; // Ignoring package libraries if they exist. TODO: do not hardcode this
99 
100  vector<string> ldPaths;
101 #ifdef WIN32
102  ldPaths.push_back(REST_PATH + "/bin/");
103 #elif __APPLE__
104  ldPaths.push_back(REST_PATH + "/bin/");
105 #else
106  ldPaths.push_back(REST_PATH + "/lib/");
107 #endif // WIN32
108  ldPaths.push_back(REST_USER_PATH + "/userlib/");
109 
110  vector<string> fileList;
111  for (const std::filesystem::path path : ldPaths) {
112  if (!exists(path)) {
113  // RESTWarning << "Directory " << string(path) << " for library loading not exist" << RESTendl;
114  continue;
115  }
116  for (const auto& it : std::filesystem::directory_iterator(path)) {
117  if (!it.is_regular_file()) {
118  continue;
119  }
120  if (libraryExtension.count(it.path().extension().string()) == 0) {
121  // needs correct extension e.g. ".so"
122  continue;
123  }
124  const TString pathRootString = it.path().string();
125  TString libName = TRestTools::SeparatePathAndName((std::string)pathRootString).second;
126  if (!libName.Contains("Rest", TString::kExact)) {
127  // e.g. "libRestFramework.so"
128  continue;
129  }
130  // Check if library is excluded from loading e.g. is from a package
131  bool excluded = false;
132  for (const TString excludedLibrary : excludedLibraries) {
133  if (libName.Contains(excludedLibrary, TString::kExact)) {
134  excluded = true;
135  // RESTWarning << "Library '" << pathRootString << "' excluded from loading" << RESTendl;
136  break;
137  }
138  }
139  if (excluded) {
140  continue;
141  }
142  fileList.emplace_back(it.path().string());
143  }
144  }
145 
146  // load the found REST libraries
147  if (!silent) cout << "= Loading libraries ..." << endl;
148  for (const auto& library : fileList) {
149  if (!silent) cout << " - " << library << endl;
150  gSystem->Load(library.c_str());
151  }
152  if (!silent) cout << endl;
153 }
154 
162 template <typename T>
163 int TRestTools::PrintTable(std::vector<std::vector<T>> data, Int_t start, Int_t end) {
164  Int_t size = data.size();
165  if (end > 0 && size > end) size = end;
166  for (int n = start; n < size; n++) {
167  for (unsigned int m = 0; m < data[n].size(); m++) cout << data[n][m] << "\t";
168  cout << endl;
169  }
170  return 0;
171 }
172 
173 template int TRestTools::PrintTable<Int_t>(std::vector<std::vector<Int_t>> data, Int_t start, Int_t end);
174 template int TRestTools::PrintTable<Float_t>(std::vector<std::vector<Float_t>> data, Int_t start, Int_t end);
175 template int TRestTools::PrintTable<Double_t>(std::vector<std::vector<Double_t>> data, Int_t start,
176  Int_t end);
177 template int TRestTools::PrintTable<std::string>(std::vector<std::vector<std::string>> data, Int_t start,
178  Int_t end);
179 
184 template <typename T>
185 int TRestTools::ExportASCIITable(std::string fname, std::vector<std::vector<T>>& data) {
186  ofstream file(fname);
187  if (!file.is_open()) {
188  RESTError << "Unable to open file for writing : " << fname << RESTendl;
189  return 1;
190  }
191 
192  for (unsigned int n = 0; n < data.size(); n++)
193  for (unsigned int m = 0; m < data[n].size(); m++) {
194  file << data[n][m];
195  if (m + 1 < data[n].size()) file << "\t";
196  if (m + 1 == data[n].size()) file << "\n";
197  }
198  file.close();
199 
200  return 0;
201 }
202 
203 template int TRestTools::ExportASCIITable<Int_t>(std::string fname, std::vector<std::vector<Int_t>>& data);
204 template int TRestTools::ExportASCIITable<Float_t>(std::string fname,
205  std::vector<std::vector<Float_t>>& data);
206 template int TRestTools::ExportASCIITable<Double_t>(std::string fname,
207  std::vector<std::vector<Double_t>>& data);
208 
213 template <typename T>
214 int TRestTools::ExportBinaryTable(std::string fname, std::vector<std::vector<T>>& data) {
215  ofstream file(fname, ios::out | ios::binary);
216  if (!file.is_open()) {
217  RESTError << "Unable to open file for writing : " << fname << RESTendl;
218  return 1;
219  }
220 
221  for (unsigned int n = 0; n < data.size(); n++)
222  for (unsigned int m = 0; m < data[n].size(); m++) {
223  file.write((char*)&data[n][m], sizeof(T));
224  }
225  file.close();
226 
227  return 0;
228 }
229 
230 template int TRestTools::ExportBinaryTable<Int_t>(std::string fname, std::vector<std::vector<Int_t>>& data);
231 template int TRestTools::ExportBinaryTable<Float_t>(std::string fname,
232  std::vector<std::vector<Float_t>>& data);
233 template int TRestTools::ExportBinaryTable<Double_t>(std::string fname,
234  std::vector<std::vector<Double_t>>& data);
235 
252 template <typename T>
253 int TRestTools::ReadBinaryTable(string fName, std::vector<std::vector<T>>& data, Int_t columns) {
254  if (!TRestTools::isValidFile((string)fName)) {
255  RESTError << "TRestTools::ReadBinaryTable. Error." << RESTendl;
256  RESTError << "Cannot open file : " << fName << RESTendl;
257  return 0;
258  }
259 
260  if (columns == -1) {
261  columns = GetBinaryFileColumns(fName);
262  if (columns == -1) {
263  RESTError << "TRestTools::ReadBinaryTable. Format extension error." << RESTendl;
264  RESTError << "Please, specify the number of columns at the method 3rd argument" << RESTendl;
265  return 0;
266  }
267  }
268 
269  std::ifstream fin(fName, std::ios::binary);
270  fin.seekg(0, std::ios::end);
271  const size_t num_elements = fin.tellg() / sizeof(T);
272  fin.seekg(0, std::ios::beg);
273 
274  if (num_elements % columns != 0) {
275  cout << "TRestTools::ReadBinaryTable. Error." << endl;
276  cout << "Number of elements : " << num_elements
277  << " is not compatible with the number of columns : " << columns << endl;
278  fin.close();
279  return 0;
280  }
281 
282  std::vector<T> dataArray(columns);
283  fin.read(reinterpret_cast<char*>(&dataArray[0]), columns * sizeof(T));
284  while (fin.good()) {
285  data.push_back(dataArray);
286  fin.read(reinterpret_cast<char*>(&dataArray[0]), columns * sizeof(T));
287  }
288  return 1;
289 }
290 
291 template int TRestTools::ReadBinaryTable<Int_t>(string fName, std::vector<std::vector<Int_t>>& data,
292  Int_t columns);
293 template int TRestTools::ReadBinaryTable<Float_t>(string fName, std::vector<std::vector<Float_t>>& data,
294  Int_t columns);
295 template int TRestTools::ReadBinaryTable<Double_t>(string fName, std::vector<std::vector<Double_t>>& data,
296  Int_t columns);
297 
303 Bool_t TRestTools::IsBinaryFile(string fname) {
304  if (GetBinaryFileColumns(fname) > 0) return true;
305  return false;
306 }
307 
316  string extension = GetFileNameExtension(fname);
317  if (extension.find("N") != 0) {
318  return -1;
319  }
320 
321  size_t pos = extension.find("i");
322  if (pos != string::npos) {
323  return StringToInteger(extension.substr(1, pos - 1));
324  }
325 
326  pos = extension.find("f");
327  if (pos != string::npos) {
328  return StringToInteger(extension.substr(1, pos - 1));
329  }
330 
331  pos = extension.find("d");
332  if (pos != string::npos) {
333  return StringToInteger(extension.substr(1, pos - 1));
334  }
335 
336  RESTError << "Format " << ToUpper(extension) << " not recognized" << RESTendl;
337  return -1;
338 }
339 
344 template <typename T>
345 void TRestTools::TransposeTable(std::vector<std::vector<T>>& data) {
346  if (data.size() == 0) return;
347 
348  std::vector<std::vector<T>> trans_vec(data[0].size(), std::vector<T>());
349 
350  for (unsigned int i = 0; i < data.size(); i++)
351  for (unsigned int j = 0; j < data[i].size(); j++) trans_vec[j].push_back(data[i][j]);
352 
353  data = trans_vec;
354 }
355 
356 template void TRestTools::TransposeTable<Double_t>(std::vector<std::vector<Double_t>>& data);
357 
358 template void TRestTools::TransposeTable<Float_t>(std::vector<std::vector<Float_t>>& data);
359 
360 template void TRestTools::TransposeTable<Int_t>(std::vector<std::vector<Int_t>>& data);
361 
369 template <typename T>
370 T TRestTools::GetMaxValueFromTable(const std::vector<std::vector<T>>& data, Int_t column) {
371  if (data.size() == 0) return 0;
372  if (column > -1 && data[0].size() <= (unsigned int)column) return 0;
373 
374  T maxValue = data[0][0];
375  if (column == -1) {
376  for (unsigned int n = 0; n < data.size(); n++)
377  for (unsigned int c = 0; c < data[n].size(); c++)
378  if (maxValue < data[n][c]) maxValue = data[n][c];
379  } else {
380  maxValue = data[0][column];
381  for (unsigned int n = 0; n < data.size(); n++)
382  if (maxValue < data[n][column]) maxValue = data[n][column];
383  }
384 
385  return maxValue;
386 }
387 
388 template Int_t TRestTools::GetMaxValueFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
389  Int_t column);
390 
391 template Float_t TRestTools::GetMaxValueFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data,
392  Int_t column);
393 
394 template Double_t TRestTools::GetMaxValueFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data,
395  Int_t column);
396 
404 template <typename T>
405 T TRestTools::GetMinValueFromTable(const std::vector<std::vector<T>>& data, Int_t column) {
406  if (data.empty()) return 0;
407  if (column != -1 && data[0].size() <= (unsigned int)column) return 0;
408 
409  T minValue = data[0][0];
410  if (column == -1) {
411  for (unsigned int n = 0; n < data.size(); n++)
412  for (unsigned int c = 0; c < data[n].size(); c++)
413  if (minValue > data[n][c]) minValue = data[n][c];
414  } else {
415  minValue = data[0][column];
416  for (unsigned int n = 0; n < data.size(); n++)
417  if (minValue > data[n][column]) minValue = data[n][column];
418  }
419 
420  return minValue;
421 }
422 
423 template Int_t TRestTools::GetMinValueFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
424  Int_t column);
425 
426 template Float_t TRestTools::GetMinValueFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data,
427  Int_t column);
428 
429 template Double_t TRestTools::GetMinValueFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data,
430  Int_t column);
431 
441 template <typename T>
442 T TRestTools::GetLowestIncreaseFromTable(std::vector<std::vector<T>> data, Int_t column) {
443  if (data.size() == 0 || data[0].size() <= (unsigned int)column) return 0;
444  T lowestIncrease = abs(data[0][column] - data[1][column]);
445  for (unsigned int n = 1; n < data.size(); n++) {
446  T value = abs(data[n - 1][column] - data[n][column]);
447  if (lowestIncrease == 0) lowestIncrease = value;
448  if (value > 0 && value < lowestIncrease) lowestIncrease = value;
449  }
450  return lowestIncrease;
451 }
452 
453 template Int_t TRestTools::GetLowestIncreaseFromTable<Int_t>(std::vector<std::vector<Int_t>> data,
454  Int_t column);
455 
456 template Float_t TRestTools::GetLowestIncreaseFromTable<Float_t>(std::vector<std::vector<Float_t>> data,
457  Int_t column);
458 
459 template Double_t TRestTools::GetLowestIncreaseFromTable<Double_t>(std::vector<std::vector<Double_t>> data,
460  Int_t column);
461 
471 template <typename T>
472 T TRestTools::GetIntegralFromTable(const std::vector<std::vector<T>>& data) {
473  if (data.size() == 0) return 0;
474  T sum = 0;
475  for (unsigned int n = 0; n < data.size(); n++) {
476  for (unsigned int m = 0; m < data[n].size(); m++) sum += data[n][m];
477  }
478  return sum;
479 }
480 
481 template Int_t TRestTools::GetIntegralFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data);
482 
483 template Float_t TRestTools::GetIntegralFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data);
484 
485 template Double_t TRestTools::GetIntegralFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data);
486 
493 template <typename T>
494 std::vector<T> TRestTools::GetColumnFromTable(const std::vector<std::vector<T>>& data, unsigned int column) {
495  std::vector<T> columnData;
496  if (data.size() == 0 || data[0].size() <= column) return columnData;
497 
498  for (unsigned int n = 0; n < data.size(); n++) columnData.push_back(data[n][column]);
499 
500  return columnData;
501 }
502 
503 template std::vector<Int_t> TRestTools::GetColumnFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
504  unsigned int column);
505 
506 template std::vector<Float_t> TRestTools::GetColumnFromTable<Float_t>(
507  const std::vector<std::vector<Float_t>>& data, unsigned int column);
508 
509 template std::vector<Double_t> TRestTools::GetColumnFromTable<Double_t>(
510  const std::vector<std::vector<Double_t>>& data, unsigned int column);
511 
512 template std::vector<std::string> TRestTools::GetColumnFromTable<std::string>(
513  const std::vector<std::vector<std::string>>& data, unsigned int column);
514 
528 int TRestTools::ReadASCIITable(string fName, std::vector<std::vector<std::string>>& data, Int_t skipLines,
529  std::string separator) {
530  if (!TRestTools::isValidFile((string)fName)) {
531  cout << "TRestTools::ReadASCIITable. Error" << endl;
532  cout << "Cannot open file : " << fName << endl;
533  return 0;
534  }
535 
536  data.clear();
537 
538  std::ifstream fin(fName);
539 
540  // First we create a table with string values
541  std::vector<std::vector<string>> values;
542 
543  for (string line; std::getline(fin, line);) {
544  if (skipLines > 0) {
545  skipLines--;
546  continue;
547  }
548 
549  if (line.find("#") == string::npos) {
550  std::istringstream in(line);
551 
552  std::string token;
553  std::vector<std::string> tokens;
554  while (std::getline(in, token, (char)separator[0])) {
555  tokens.push_back(token);
556  }
557  data.push_back(tokens);
558  }
559  }
560 
561  return 1;
562 }
563 
577 int TRestTools::ReadASCIITable(string fName, std::vector<std::vector<Double_t>>& data, Int_t skipLines,
578  std::string separator) {
579  if (!TRestTools::isValidFile((string)fName)) {
580  cout << "TRestTools::ReadASCIITable. Error" << endl;
581  cout << "Cannot open file : " << fName << endl;
582  return 0;
583  }
584 
585  data.clear();
586 
587  std::ifstream fin(fName);
588 
589  // First we create a table with string values
590  std::vector<std::vector<string>> values;
591 
592  for (string line; std::getline(fin, line);) {
593  if (skipLines > 0) {
594  skipLines--;
595  continue;
596  }
597 
598  if (line.find("#") == string::npos) {
599  std::istringstream in(line);
600 
601  std::string token;
602  std::vector<std::string> tokens;
603  while (std::getline(in, token, (char)separator[0])) {
604  tokens.push_back(token);
605  }
606  values.push_back(tokens);
607  }
608  }
609 
610  // Filling the double values table (TODO error handling in case ToDouble conversion fails)
611  for (unsigned int n = 0; n < values.size(); n++) {
612  std::vector<Double_t> dblTmp;
613  dblTmp.clear();
614 
615  for (unsigned int m = 0; m < values[n].size(); m++) dblTmp.push_back(StringToDouble(values[n][m]));
616 
617  data.push_back(dblTmp);
618  }
619 
620  return 1;
621 }
622 
636 int TRestTools::ReadASCIITable(string fName, std::vector<std::vector<Float_t>>& data, Int_t skipLines,
637  std::string separator) {
638  if (!TRestTools::isValidFile((string)fName)) {
639  cout << "TRestTools::ReadASCIITable. Error" << endl;
640  cout << "Cannot open file : " << fName << endl;
641  return 0;
642  }
643 
644  data.clear();
645 
646  std::ifstream fin(fName);
647 
648  // First we create a table with string values
649  std::vector<std::vector<string>> values;
650 
651  for (string line; std::getline(fin, line);) {
652  if (skipLines > 0) {
653  skipLines--;
654  continue;
655  }
656 
657  if (line.find("#") == string::npos) {
658  std::istringstream in(line);
659 
660  std::string token;
661  std::vector<std::string> tokens;
662  while (std::getline(in, token, (char)separator[0])) {
663  tokens.push_back(token);
664  }
665  values.push_back(tokens);
666  }
667  }
668 
669  // Filling the float values table (TODO error handling in case ToFloat conversion fails)
670  for (unsigned int n = 0; n < values.size(); n++) {
671  std::vector<Float_t> dblTmp;
672  dblTmp.clear();
673 
674  for (unsigned int m = 0; m < values[n].size(); m++) dblTmp.push_back(StringToFloat(values[n][m]));
675 
676  data.push_back(dblTmp);
677  }
678 
679  return 1;
680 }
681 
695 int TRestTools::ReadCSVFile(std::string fName, std::vector<std::vector<Double_t>>& data, Int_t skipLines) {
696  return ReadASCIITable(fName, data, skipLines, ",");
697 }
698 
712 int TRestTools::ReadCSVFile(std::string fName, std::vector<std::vector<Float_t>>& data, Int_t skipLines) {
713  return ReadASCIITable(fName, data, skipLines, ",");
714 }
715 
719 Int_t TRestTools::isValidFile(const string& path) { return std::filesystem::is_regular_file(path); }
720 
728 bool TRestTools::fileExists(const string& filename) { return std::filesystem::exists(filename); }
729 
733 bool TRestTools::isRootFile(const string& filename) { return GetFileNameExtension(filename) == "root"; }
734 
738 bool TRestTools::isRunFile(const std::string& filename) {
739  if (!isRootFile(filename)) return false;
740 
741  TFile* f = TFile::Open((TString)filename);
742 
743  TIter nextkey(f->GetListOfKeys());
744  TKey* key;
745  while ((key = (TKey*)nextkey())) {
746  if ((std::string)key->GetClassName() == "TRestRun") return true;
747  }
748  return false;
749 }
750 
754 bool TRestTools::isDataSet(const std::string& filename) {
755  if (!isRootFile(filename)) return false;
756 
757  TFile* f = TFile::Open((TString)filename);
758 
759  TIter nextkey(f->GetListOfKeys());
760  TKey* key;
761  while ((key = (TKey*)nextkey())) {
762  if ((std::string)key->GetClassName() == "TRestDataSet") return true;
763  }
764  return false;
765 }
766 
770 bool TRestTools::isURL(const string& s) {
771  std::regex pattern("^https?://(.+)");
772  return std::regex_match(s, pattern);
773 }
774 
778 bool TRestTools::isPathWritable(const string& path) {
779  int result = 0;
780 #ifdef WIN32
781  result = _access(path.c_str(), 2);
782 #else
783  result = access(path.c_str(), 2);
784 #endif
785 
786  if (result == 0)
787  return true;
788  else
789  return false;
790 }
791 
795 bool TRestTools::isAbsolutePath(const string& path) {
796  if (path[0] == '/' || path[0] == '~' || path.find(':') != string::npos) {
797  return true;
798  }
799  return false;
800 }
801 
813 std::pair<string, string> TRestTools::SeparatePathAndName(const string& fullname) {
814  filesystem::path path(fullname);
815  return {path.parent_path().string(), path.filename().string()};
816 }
817 
823 string TRestTools::GetFileNameExtension(const string& fullname) {
824  string extension = filesystem::path(fullname).extension().string();
825  if (extension.size() > 1) return extension.substr(1);
826  return extension;
827 }
828 
834 string TRestTools::GetFileNameRoot(const string& fullname) {
835  return filesystem::path(fullname).stem().string();
836 }
837 
845  // we replace multiple appearances of "/" (slash) by a single "/"
846  string to_replace = "//";
847  size_t start_pos = str.find(to_replace);
848  while (start_pos != string::npos) {
849  str.replace(start_pos, to_replace.length(), "/");
850  start_pos = str.find(to_replace);
851  }
852  return str;
853 }
854 
863 string TRestTools::GetPureFileName(const string& path) { return filesystem::path(path).filename().string(); }
864 
868 string TRestTools::ToAbsoluteName(const string& filename) {
869  filesystem::path path;
870  for (const auto& directory : filesystem::path(filename)) {
871  if (path.empty() && directory == "~") {
872  // path starts with ~
873  const auto envVariableHome = getenv("HOME");
874  if (envVariableHome == nullptr) {
875  cout << "TRestTools::ToAbsoluteName - ERROR - "
876  "cannot resolve ~ because 'HOME' env variable does not exist"
877  << endl;
878  exit(1);
879  }
880  const auto userHomePath = filesystem::path(envVariableHome);
881  if (userHomePath.empty()) {
882  cout << "TRestTools::ToAbsoluteName - ERROR - "
883  "cannot resolve ~ because 'HOME' env variable is not set to a valid value"
884  << endl;
885  exit(1);
886  }
887  path /= userHomePath;
888  } else {
889  path /= directory;
890  }
891  }
892  return filesystem::weakly_canonical(path).string();
893 }
894 
904 vector<string> TRestTools::GetSubdirectories(const string& _path, int recursion) {
905  vector<string> result;
906 
907  std::filesystem::path path(_path);
908  if (exists(path)) {
909  std::filesystem::directory_iterator iter(path);
910  for (auto& it : iter) {
911  if (it.is_directory()) {
912  result.push_back(it.path().string());
913 
914  if (recursion != 0) {
915  vector<string> subD = GetSubdirectories(it.path().string(), recursion - 1);
916  result.insert(result.begin(), subD.begin(), subD.end());
917  }
918  }
919  }
920  }
921 
922  return result;
923 }
924 
929 string TRestTools::SearchFileInPath(vector<string> paths, string filename) {
930  if (fileExists(filename)) {
931  return filename;
932  } else {
933  for (unsigned int i = 0; i < paths.size(); i++) {
934  string path = paths[i];
935  if (path[path.size() - 1] != '/') {
936  path = path + "/";
937  }
938 
939  if (fileExists(path + filename)) {
940  return path + filename;
941  }
942 
943  // search also in subdirectory, but only 5 times of recursion
944  vector<string> pathsExpanded = GetSubdirectories(paths[i], 5);
945  for (unsigned int j = 0; j < pathsExpanded.size(); j++)
946  if (fileExists(pathsExpanded[j] + "/" + filename)) return pathsExpanded[j] + "/" + filename;
947  }
948  }
949  return "";
950 }
951 
956 bool TRestTools::CheckFileIsAccessible(const std::string& filename) {
957  ifstream ifs;
958  ifs.open(filename.c_str());
959 
960  if (!ifs) {
961  return false;
962  } else {
963  ifs.close();
964  }
965  return true;
966 }
967 
976 vector<string> TRestTools::GetFilesMatchingPattern(string pattern, bool unlimited) {
977  std::vector<string> outputFileNames;
978  if (pattern != "") {
979  vector<string> items = Split(pattern, "\n");
980  for (auto item : items) {
981  if (item.find_first_of("*?") != string::npos) {
982 #ifdef WIN32
983  item = Replace(item, "/", "\\");
984  string item_trim =
985  item.substr(0, item.find_first_of("*?")); // trim string to before wildcard character
986  auto path_name = SeparatePathAndName(item_trim);
987  string _path = path_name.first;
988  if (!std::filesystem::exists(_path)) {
989  RESTError << "TRestTools::GetFilesMatchingPattern(): path " << _path << " does not exist!"
990  << RESTendl;
991  return outputFileNames;
992  }
993 
994  std::filesystem::path path(_path);
995  std::filesystem::recursive_directory_iterator iter(path);
996  for (auto& it : iter) {
997  if (it.is_regular_file()) {
998  string filename = it.path().string();
999  if (MatchString(filename, item)) {
1000  outputFileNames.push_back(it.path().string());
1001  }
1002  }
1003  }
1004 #else
1005  auto path_name = SeparatePathAndName(item);
1006  if (unlimited) {
1007  std::string currentDir = filesystem::current_path();
1008  ChangeDirectory(path_name.first);
1009  string a = Execute("find -type f -name \'" + path_name.second + "\'");
1010  ChangeDirectory(currentDir);
1011  auto b = Split(a, "\n");
1012 
1013  for (unsigned int i = 0; i < b.size(); i++) {
1014  outputFileNames.push_back(path_name.first + "/" + b[i]);
1015  }
1016 
1017  } else {
1018  string a = Execute("find " + item);
1019  auto b = Split(a, "\n");
1020 
1021  for (unsigned int i = 0; i < b.size(); i++) {
1022  outputFileNames.push_back(b[i]);
1023  }
1024  }
1025 #endif
1026 
1027  } else {
1028  if (fileExists(item)) outputFileNames.push_back(item);
1029  }
1030  }
1031  }
1032  return outputFileNames;
1033 }
1034 
1039 #ifndef REST_Version
1040 #define REST_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
1041 #endif
1042  vector<string> ver = Split(in, ".");
1043  if (ver.size() == 3) {
1044  vector<int> verint;
1045  for (auto v : ver) {
1046  int n = StringToInteger(v.substr(0, v.find_first_not_of("0123456789")));
1047  if (n != -1) {
1048  verint.push_back(n);
1049  } else {
1050  return -1;
1051  }
1052  }
1053  return REST_VERSION(verint[0], verint[1], verint[2]);
1054  }
1055  return -1;
1056 }
1057 
1061 string TRestTools::Execute(string cmd) {
1062  std::array<char, 128> buffer;
1063  string result;
1064 #ifdef WIN32
1065  std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(("powershell.exe " + cmd).c_str(), "r"), _pclose);
1066 #else
1067  std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
1068 #endif // WIN32
1069 
1070  if (!pipe) {
1071  throw std::runtime_error("popen() failed!");
1072  }
1073  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
1074  result += buffer.data();
1075  }
1076 
1077  if (result.size() > 0 && result[result.size() - 1] == '\n')
1078  result = result.substr(0, result.size() - 1); // remove last "\n"
1079 
1080  return result;
1081 }
1082 
1087 std::istream& TRestTools::GetLine(std::istream& is, std::string& t) {
1088  t.clear();
1089 
1090  // The characters in the stream are read one-by-one using a std::streambuf.
1091  // That is faster than reading them one-by-one using the std::istream.
1092  // Code that uses streambuf this way must be guarded by a sentry object.
1093  // The sentry object performs various tasks,
1094  // such as thread synchronization and updating the stream state.
1095 
1096  std::istream::sentry se(is, true);
1097  std::streambuf* sb = is.rdbuf();
1098 
1099  for (;;) {
1100  int c = sb->sbumpc();
1101  switch (c) {
1102  case '\n':
1103  return is;
1104  case '\r':
1105  if (sb->sgetc() == '\n') sb->sbumpc();
1106  return is;
1107  case std::streambuf::traits_type::eof():
1108  // Also handle the case when the last line has no line ending
1109  if (t.empty()) is.setstate(std::ios::eofbit);
1110  return is;
1111  default:
1112  t += (char)c;
1113  }
1114  }
1115 }
1116 
1124 std::string TRestTools::DownloadRemoteFile(const string& url, bool pidPrefix) {
1125  string pureName = TRestTools::GetPureFileName(url);
1126  if (pureName.empty()) {
1127  RESTWarning << "error! (TRestTools::DownloadRemoteFile): url is not a file!" << RESTendl;
1128  RESTWarning << "please specify a concrete file name in this url" << RESTendl;
1129  RESTWarning << "url: " << url << RESTendl;
1130  return "";
1131  }
1132 
1133  if (url.find("local:") == 0) {
1134  return Replace(url, "local:", "");
1135  } else {
1136  string fullpath =
1137  REST_USER_PATH + "/download/" + (pidPrefix ? "PID_" + ToString(getpid()) + "_" : "") + pureName;
1138  int out;
1139  int attempts = 10;
1140  do {
1141  out = TRestTools::DownloadRemoteFile(url, fullpath);
1142  if (out == 1024) {
1143  RESTWarning << "Retrying download in 5 seconds" << RESTendl;
1144  std::this_thread::sleep_for(std::chrono::seconds(5));
1145  } else if (attempts < 10) {
1146  RESTSuccess << "Download succeeded after " << 10 - attempts << " attempts" << RESTendl;
1147  }
1148  attempts--;
1149  } while (out == 1024 && attempts > 0);
1150 
1151  if (out == 0 || TRestTools::fileExists(fullpath)) {
1152  return fullpath;
1153  } else {
1154  return "";
1155  }
1156  }
1157 }
1158 
1165 int TRestTools::DownloadRemoteFile(string remoteFile, string localFile) {
1166  TUrl url(remoteFile.c_str());
1167 
1168  RESTInfo << "Downloading remote file : " << remoteFile << RESTendl;
1169  RESTInfo << "To local file : " << localFile << RESTendl;
1170 
1171  string localFiletmp = localFile + ".restdownload";
1172  if ((string)url.GetProtocol() == "https" || (string)url.GetProtocol() == "http") {
1173  string path = TRestTools::SeparatePathAndName(localFiletmp).first;
1174  if (!TRestTools::fileExists(path)) {
1175  if (!filesystem::create_directories(path)) {
1176  std::cerr << "mkdir failed to create directory: " << path << std::endl;
1177  return -1;
1178  }
1179  }
1180 
1181  string cmd = "wget --no-check-certificate " + EscapeSpecialLetters(remoteFile) + " -O " +
1182  EscapeSpecialLetters(localFiletmp) + " -q";
1183  RESTDebug << cmd << RESTendl;
1184  int a = system(cmd.c_str());
1185 
1186  if (a == 0) {
1187  rename(localFiletmp.c_str(), localFile.c_str());
1188  return 0;
1189  } else {
1190  RESTError << "download failed! (" << remoteFile << ")" << RESTendl;
1191  if (a == 1024) {
1192  RESTError << "Network connection problem?" << RESTendl;
1193  return 1024;
1194  }
1195  if (a == 2048) {
1196  RESTError << "File does NOT exist in remotely?" << RESTendl;
1197  return 2048;
1198  }
1199  }
1200  } else if ((string)url.GetProtocol() == "ssh") {
1201  string cmd = "scp -P " + ToString(url.GetPort() == 0 ? 22 : url.GetPort()) + " " + url.GetUser() +
1202  "@" + url.GetHost() + ":" + EscapeSpecialLetters(url.GetFile()) + " " + localFiletmp;
1203  cout << cmd << endl;
1204  int a = system(cmd.c_str());
1205  if (a == 0) {
1206  rename(localFiletmp.c_str(), localFile.c_str());
1207  return 0;
1208  }
1209  } else {
1210  if (!TRestTools::fileExists(remoteFile)) {
1211  RESTWarning << "Trying to download: " << remoteFile << RESTendl;
1212  RESTWarning << "Unknown protocol!" << RESTendl;
1213  }
1214  }
1215 
1216  return -1;
1217 }
1218 
1223 std::string TRestTools::POSTRequest(const std::string& url, const std::map<std::string, std::string>& keys) {
1224  std::string file_content = "";
1225 #ifdef USE_Curl
1226  CURL* curl;
1227  CURLcode res;
1228 
1229  string filename = REST_USER_PATH + "/download/curl.out";
1230 
1231  /* In windows, this will init the winsock stuff */
1232  curl_global_init(CURL_GLOBAL_ALL);
1233 
1234  FILE* f = fopen(filename.c_str(), "wt");
1235 
1236  std::string request = "";
1237  int n = 0;
1238  for (auto const& x : keys) {
1239  if (n > 0) request += "&";
1240  request += x.first + "=" + x.second;
1241  n++;
1242  }
1243  /* get a curl handle */
1244  curl = curl_easy_init();
1245  if (curl) {
1246  /* First set the URL that is about to receive our POST. This URL can
1247  just as well be a https:// URL if that is what should receive the
1248  data. */
1249  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
1250  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)f);
1251  /* Now specify the POST data */
1252  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str());
1253 
1254  /* Perform the request, res will get the return code */
1255  res = curl_easy_perform(curl);
1256  /* Check for errors */
1257  if (res != CURLE_OK)
1258  RESTError << "curl_easy_perform() failed: " << curl_easy_strerror(res) << RESTendl;
1259 
1260  /* always cleanup */
1261  curl_easy_cleanup(curl);
1262  }
1263  fclose(f);
1264  curl_global_cleanup();
1265 
1266  std::getline(std::ifstream(filename), file_content, '\0');
1267 #else
1268  RESTError << "TRestTools::POSTRequest. REST framework was compiled without CURL support" << RESTendl;
1269  RESTError << "Please recompile REST after installing curl development libraries." << RESTendl;
1270  RESTError << "Depending on your system this might be: curl-dev, curl-devel or libcurl-openssl-dev. "
1271  << RESTendl;
1272  RESTError << "No file will be downloaded" << RESTendl;
1273 #endif
1274 
1275  return file_content;
1276 }
1277 
1285 int TRestTools::UploadToServer(string localFile, string remoteFile, string methodUrl) {
1286  if (!TRestTools::fileExists(localFile)) {
1287  cout << "error! local file not exist!" << endl;
1288  return -1;
1289  }
1290  // construct path
1291  // [proto://][user[:passwd]@]host[:port]/file.ext[#anchor][?options]
1292  TUrl url(remoteFile.c_str());
1293  TUrl method(methodUrl.c_str());
1294  if (method.GetProtocol() != (string) "") url.SetProtocol(method.GetProtocol());
1295  if (method.GetPort() != 0) url.SetPort(method.GetPort());
1296  if (method.GetUser() != (string) "") url.SetUser(method.GetUser());
1297  if (method.GetPasswd() != (string) "") url.SetPasswd(method.GetPasswd());
1298 
1299  if ((string)url.GetProtocol() == "https" || (string)url.GetProtocol() == "http") {
1300  // maybe we use curl to upload to http in future
1301  } else if ((string)url.GetProtocol() == "ssh") {
1302  string cmd = "scp -P " + ToString(url.GetPort() == 0 ? 22 : url.GetPort()) + " " +
1303  EscapeSpecialLetters(localFile) + " " + url.GetUser() + "@" + url.GetHost() + ":" +
1304  EscapeSpecialLetters(url.GetFile());
1305  cout << cmd << endl;
1306  int a = system(cmd.c_str());
1307 
1308  if (a != 0) {
1309  RESTError << __PRETTY_FUNCTION__ << RESTendl;
1310  RESTError << "problem copying gases definitions to remote server" << RESTendl;
1311  RESTError << "Please report this problem at "
1312  "http://gifna.unizar.es/rest-forum/"
1313  << RESTendl;
1314  return -1;
1315  }
1316 
1317  return 0;
1318  }
1319  return 0;
1320 }
1321 
1322 void TRestTools::ChangeDirectory(const string& toDirectory) { filesystem::current_path(toDirectory); }
1323 
1332 std::vector<int> TRestTools::CanvasDivisions(int n) {
1333  std::vector<int> r;
1334  for (int i = 2; i * i <= n; i += 1 + (i > 2)) {
1335  while ((n % i) == 0) {
1336  r.push_back(i);
1337  n /= i;
1338  }
1339  }
1340  if (n != 1) r.push_back(n);
1341 
1342  while (r.size() > 2) {
1343  // We multiply the 2 lowest elements and
1344  // replace the elements in the vector by the result
1345  auto min1 = std::min_element(r.begin(), r.end());
1346  int low1 = *min1;
1347 
1348  // Remove the first element equal to min1 (efficient way)
1349  auto it = std::find(r.begin(), r.end(), low1);
1350  if (it != r.end()) {
1351  std::iter_swap(it, r.end() - 1);
1352  r.erase(r.end() - 1);
1353  }
1354 
1355  auto min2 = std::min_element(r.begin(), r.end());
1356  int low2 = *min2;
1357 
1358  // Remove the first element equal to min2 (efficient way)
1359  it = std::find(r.begin(), r.end(), low2);
1360  if (it != r.end()) {
1361  std::iter_swap(it, r.end() - 1);
1362  r.erase(r.end() - 1);
1363  }
1364 
1365  int resultado = low1 * low2;
1366  r.push_back(resultado);
1367  }
1368 
1369  std::sort(r.begin(), r.end());
1370 
1371  if (r.size() == 1) r.push_back(1);
1372 
1373  return r;
1374 }
1375 
1376 string ValueWithQuantity::ToString() const {
1377  string unit;
1378  auto value = fValue;
1379  if (fQuantity == ENERGY) {
1380  unit = "eV";
1381  value *= 1E3; // since we store energy in keV, not in eV
1382  } else if (fQuantity == TIME) {
1383  unit = "s"; // time is stored in microseconds
1384  value *= 1E-6;
1385  } else if (fQuantity == LENGTH) {
1386  unit = "m";
1387  value *= 1E-3; // since we store length in mm, not in m
1388  } else {
1389  return "";
1390  }
1391 
1392  const auto abs = TMath::Abs(value);
1393  if (abs == 0) {
1394  return TString::Format("%d", 0).Data();
1395  } else if (abs < 1E-6) {
1396  return TString::Format("%.2f %s%s", value * 1E9, "n", unit.c_str()).Data();
1397  } else if (abs < 1E-3) {
1398  return TString::Format("%.2f %s%s", value * 1E6, "u", unit.c_str()).Data();
1399  } else if (abs < 1E0) {
1400  return TString::Format("%.2f %s%s", value * 1E3, "m", unit.c_str()).Data();
1401  } else if (abs < 1E3) {
1402  return TString::Format("%.2f %s%s", value * 1E0, "", unit.c_str()).Data();
1403  } else if (abs < 1E6) {
1404  return TString::Format("%.2f %s%s", value * 1E-3, "k", unit.c_str()).Data();
1405  } else if (abs < 1E9) {
1406  return TString::Format("%.2f %s%s", value * 1E-6, "M", unit.c_str()).Data();
1407  } else if (abs < 1E12) {
1408  return TString::Format("%.2f %s%s", value * 1E-9, "G", unit.c_str()).Data();
1409  } else {
1410  return TString::Format("%.2f %s%s", value * 1E-12, "T", unit.c_str()).Data();
1411  }
1412 }
1413 
1414 string ToTimeStringLong(double seconds) {
1415  const auto abs = TMath::Abs(seconds);
1416  if (abs < 60) {
1417  return TString::Format("%.2f %s", seconds, "seconds").Data();
1418  } else if (abs < 60 * 60) {
1419  return TString::Format("%.2f %s", seconds / 60.0, "minutes").Data();
1420  } else if (abs < 60 * 60 * 24) {
1421  return TString::Format("%.2f %s", seconds / (60.0 * 60.0), "hours").Data();
1422  } else {
1423  return TString::Format("%.2f %s", seconds / (60.0 * 60.0 * 24.0), "days").Data();
1424  }
1425 }
static void TransposeTable(std::vector< std::vector< T >> &data)
It transposes the std::vector<std::vector> table given in the argument. It will transform rows in col...
Definition: TRestTools.cxx:345
static std::string Execute(std::string cmd)
Executes a shell command and returns its output in a string.
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 Int_t isValidFile(const std::string &path)
Returns true if the file with path filename exists.
Definition: TRestTools.cxx:719
static int ExportASCIITable(std::string fname, std::vector< std::vector< T >> &data)
Writes the contents of the vector table given as argument to fname. Allowed types are Int_t,...
Definition: TRestTools.cxx:185
static std::string GetFileNameExtension(const std::string &fullname)
Gets the file extension as the substring found after the latest ".".
Definition: TRestTools.cxx:823
static std::string POSTRequest(const std::string &url, const std::map< std::string, std::string > &keys)
It performs a POST web protocol request using a set of keys and values given by argument,...
static int ReadCSVFile(std::string fName, std::vector< std::vector< Double_t >> &data, Int_t skipLines=0)
Reads a CSV file containing a table with comma separated values.
Definition: TRestTools.cxx:695
static std::vector< std::string > GetSubdirectories(const std::string &path, int recursion=-1)
It lists all the subdirectories inside path and adds them to the result vector.
Definition: TRestTools.cxx:904
static bool CheckFileIsAccessible(const std::string &)
Checks if the config file can be opened (and thus exists). It returns true in case of success,...
Definition: TRestTools.cxx:956
static std::string GetPureFileName(const std::string &fullPathFileName)
Removes all directories in the full path filename description given in the argument.
Definition: TRestTools.cxx:863
static int GetBinaryFileColumns(std::string fname)
It extracts the number of columns from the filename extension given by argument. The file should cont...
Definition: TRestTools.cxx:315
static std::vector< std::string > GetOptions(std::string optionsStr)
Returns all the options in an option string.
Definition: TRestTools.cxx:86
static std::string GetFileNameRoot(const std::string &fullname)
Gets the filename root as the substring found before the latest ".".
Definition: TRestTools.cxx:834
static void LoadRESTLibrary(bool silent=false)
Calls gSystem to load REST library.
Definition: TRestTools.cxx:95
static bool isRunFile(const std::string &filename)
It checks if the file has been processed using a REST event processing chain.
Definition: TRestTools.cxx:738
static std::vector< T > GetColumnFromTable(const std::vector< std::vector< T >> &data, unsigned int column)
It returns a vector with the values extracted from the particular column inside the data table given ...
Definition: TRestTools.cxx:494
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
static std::vector< int > CanvasDivisions(int n)
It returns a vector with 2 components {a,b}, the components satisfy that a x b = n,...
static std::string DownloadRemoteFile(const std::string &remoteFile, bool pidPrefix=false)
download the remote file automatically, returns the downloaded file name.
static T GetMinValueFromTable(const std::vector< std::vector< T >> &data, Int_t column=-1)
It returns the minimum value for a particular column from the table given by argument....
Definition: TRestTools.cxx:405
static std::vector< std::string > GetFilesMatchingPattern(std::string pattern, bool unlimited=false)
Returns a list of files whose name match the pattern string. Key word is "*". e.g....
Definition: TRestTools.cxx:976
static int ConvertVersionCode(std::string in)
Convert version to a unique string.
static bool isPathWritable(const std::string &path)
Returns true if the path given by argument is writable.
Definition: TRestTools.cxx:778
static bool isAbsolutePath(const std::string &path)
Check if the path is absolute path or not.
Definition: TRestTools.cxx:795
static int PrintTable(std::vector< std::vector< T >> data, Int_t start=0, Int_t end=0)
Prints the contents of the vector table given as argument in screen. Allowed types are Int_t,...
Definition: TRestTools.cxx:163
static Bool_t IsBinaryFile(std::string fname)
It identifies if the filename extension follows the formatting ".Nxyzf", where the number of columns ...
Definition: TRestTools.cxx:303
static std::string RemoveMultipleSlash(std::string)
Returns the input string but without multiple slashes ("/")
Definition: TRestTools.cxx:844
static bool isDataSet(const std::string &filename)
It checks if the file contains a dataset object.
Definition: TRestTools.cxx:754
static bool isURL(const std::string &filename)
Returns true if filename is an http address.
Definition: TRestTools.cxx:770
static std::istream & GetLine(std::istream &is, std::string &t)
It reads the next line from the incoming istream and puts it in the string argument t....
static int ReadBinaryTable(std::string fName, std::vector< std::vector< T >> &data, Int_t columns=-1)
Reads a binary file containing a fixed-columns table with values.
Definition: TRestTools.cxx:253
static T GetIntegralFromTable(const std::vector< std::vector< T >> &data)
It returns the lowest increase, different from zero, between the elements of a particular column from...
Definition: TRestTools.cxx:472
static int UploadToServer(std::string localFile, std::string remoteFile, std::string methodUrl="")
static bool isRootFile(const std::string &filename)
Returns true if the filename has *.root* extension.
Definition: TRestTools.cxx:733
static std::string SearchFileInPath(std::vector< std::string > path, std::string filename)
Search file in the given vector of path strings, return a full name if found, return "" if not.
Definition: TRestTools.cxx:929
static int ReadASCIITable(std::string fName, std::vector< std::vector< Double_t >> &data, Int_t skipLines=0, std::string separator="\t")
Reads an ASCII file containing a table with values.
Definition: TRestTools.cxx:577
static T GetLowestIncreaseFromTable(std::vector< std::vector< T >> data, Int_t column)
It returns the lowest increase, different from zero, between the elements of a particular column from...
Definition: TRestTools.cxx:442
static T GetMaxValueFromTable(const std::vector< std::vector< T >> &data, Int_t column=-1)
It returns the maximum value for a particular column from the table given by argument....
Definition: TRestTools.cxx:370
static int ExportBinaryTable(std::string fname, std::vector< std::vector< T >> &data)
Writes the contents of the vector table given as argument to fname as a binary file....
Definition: TRestTools.cxx:214
static std::string ToAbsoluteName(const std::string &filename)
It takes a path and returns its absolute path.
Definition: TRestTools.cxx:868
Float_t StringToFloat(std::string in)
Gets a float from a string.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
Bool_t MatchString(std::string str, std::string matcher)
This method matches a string with certain matcher. Returns true if matched. Supports wildcard charact...
Double_t StringToDouble(std::string in)
Gets a double from a string.
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
Int_t StringToInteger(std::string in)
Gets an integer from a string.
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.