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
78using namespace std;
79
86std::vector<string> TRestTools::GetOptions(string optionsStr) { return Split(optionsStr, ":"); }
87
95void 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
162template <typename T>
163int 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
173template int TRestTools::PrintTable<Int_t>(std::vector<std::vector<Int_t>> data, Int_t start, Int_t end);
174template int TRestTools::PrintTable<Float_t>(std::vector<std::vector<Float_t>> data, Int_t start, Int_t end);
175template int TRestTools::PrintTable<Double_t>(std::vector<std::vector<Double_t>> data, Int_t start,
176 Int_t end);
177
182template <typename T>
183int TRestTools::ExportASCIITable(std::string fname, std::vector<std::vector<T>>& data) {
184 ofstream file(fname);
185 if (!file.is_open()) {
186 RESTError << "Unable to open file for writing : " << fname << RESTendl;
187 return 1;
188 }
189
190 for (unsigned int n = 0; n < data.size(); n++)
191 for (unsigned int m = 0; m < data[n].size(); m++) {
192 file << data[n][m];
193 if (m + 1 < data[n].size()) file << "\t";
194 if (m + 1 == data[n].size()) file << "\n";
195 }
196 file.close();
197
198 return 0;
199}
200
201template int TRestTools::ExportASCIITable<Int_t>(std::string fname, std::vector<std::vector<Int_t>>& data);
202template int TRestTools::ExportASCIITable<Float_t>(std::string fname,
203 std::vector<std::vector<Float_t>>& data);
204template int TRestTools::ExportASCIITable<Double_t>(std::string fname,
205 std::vector<std::vector<Double_t>>& data);
206
211template <typename T>
212int TRestTools::ExportBinaryTable(std::string fname, std::vector<std::vector<T>>& data) {
213 ofstream file(fname, ios::out | ios::binary);
214 if (!file.is_open()) {
215 RESTError << "Unable to open file for writing : " << fname << RESTendl;
216 return 1;
217 }
218
219 for (unsigned int n = 0; n < data.size(); n++)
220 for (unsigned int m = 0; m < data[n].size(); m++) {
221 file.write((char*)&data[n][m], sizeof(T));
222 }
223 file.close();
224
225 return 0;
226}
227
228template int TRestTools::ExportBinaryTable<Int_t>(std::string fname, std::vector<std::vector<Int_t>>& data);
229template int TRestTools::ExportBinaryTable<Float_t>(std::string fname,
230 std::vector<std::vector<Float_t>>& data);
231template int TRestTools::ExportBinaryTable<Double_t>(std::string fname,
232 std::vector<std::vector<Double_t>>& data);
233
250template <typename T>
251int TRestTools::ReadBinaryTable(string fName, std::vector<std::vector<T>>& data, Int_t columns) {
252 if (!TRestTools::isValidFile((string)fName)) {
253 RESTError << "TRestTools::ReadBinaryTable. Error." << RESTendl;
254 RESTError << "Cannot open file : " << fName << RESTendl;
255 return 0;
256 }
257
258 if (columns == -1) {
259 columns = GetBinaryFileColumns(fName);
260 if (columns == -1) {
261 RESTError << "TRestTools::ReadBinaryTable. Format extension error." << RESTendl;
262 RESTError << "Please, specify the number of columns at the method 3rd argument" << RESTendl;
263 return 0;
264 }
265 }
266
267 std::ifstream fin(fName, std::ios::binary);
268 fin.seekg(0, std::ios::end);
269 const size_t num_elements = fin.tellg() / sizeof(T);
270 fin.seekg(0, std::ios::beg);
271
272 if (num_elements % columns != 0) {
273 cout << "TRestTools::ReadBinaryTable. Error." << endl;
274 cout << "Number of elements : " << num_elements
275 << " is not compatible with the number of columns : " << columns << endl;
276 fin.close();
277 return 0;
278 }
279
280 std::vector<T> dataArray(columns);
281 fin.read(reinterpret_cast<char*>(&dataArray[0]), columns * sizeof(T));
282 while (fin.good()) {
283 data.push_back(dataArray);
284 fin.read(reinterpret_cast<char*>(&dataArray[0]), columns * sizeof(T));
285 }
286 return 1;
287}
288
289template int TRestTools::ReadBinaryTable<Int_t>(string fName, std::vector<std::vector<Int_t>>& data,
290 Int_t columns);
291template int TRestTools::ReadBinaryTable<Float_t>(string fName, std::vector<std::vector<Float_t>>& data,
292 Int_t columns);
293template int TRestTools::ReadBinaryTable<Double_t>(string fName, std::vector<std::vector<Double_t>>& data,
294 Int_t columns);
295
301Bool_t TRestTools::IsBinaryFile(string fname) {
302 if (GetBinaryFileColumns(fname) > 0) return true;
303 return false;
304}
305
314 string extension = GetFileNameExtension(fname);
315 if (extension.find("N") != 0) {
316 return -1;
317 }
318
319 size_t pos = extension.find("i");
320 if (pos != string::npos) {
321 return StringToInteger(extension.substr(1, pos - 1));
322 }
323
324 pos = extension.find("f");
325 if (pos != string::npos) {
326 return StringToInteger(extension.substr(1, pos - 1));
327 }
328
329 pos = extension.find("d");
330 if (pos != string::npos) {
331 return StringToInteger(extension.substr(1, pos - 1));
332 }
333
334 RESTError << "Format " << ToUpper(extension) << " not recognized" << RESTendl;
335 return -1;
336}
337
342template <typename T>
343void TRestTools::TransposeTable(std::vector<std::vector<T>>& data) {
344 if (data.size() == 0) return;
345
346 std::vector<std::vector<T>> trans_vec(data[0].size(), std::vector<T>());
347
348 for (unsigned int i = 0; i < data.size(); i++)
349 for (unsigned int j = 0; j < data[i].size(); j++) trans_vec[j].push_back(data[i][j]);
350
351 data = trans_vec;
352}
353
354template void TRestTools::TransposeTable<Double_t>(std::vector<std::vector<Double_t>>& data);
355
356template void TRestTools::TransposeTable<Float_t>(std::vector<std::vector<Float_t>>& data);
357
358template void TRestTools::TransposeTable<Int_t>(std::vector<std::vector<Int_t>>& data);
359
367template <typename T>
368T TRestTools::GetMaxValueFromTable(const std::vector<std::vector<T>>& data, Int_t column) {
369 if (data.size() == 0) return 0;
370 if (column > -1 && data[0].size() <= (unsigned int)column) return 0;
371
372 T maxValue = data[0][0];
373 if (column == -1) {
374 for (unsigned int n = 0; n < data.size(); n++)
375 for (unsigned int c = 0; c < data[n].size(); c++)
376 if (maxValue < data[n][c]) maxValue = data[n][c];
377 } else {
378 maxValue = data[0][column];
379 for (unsigned int n = 0; n < data.size(); n++)
380 if (maxValue < data[n][column]) maxValue = data[n][column];
381 }
382
383 return maxValue;
384}
385
386template Int_t TRestTools::GetMaxValueFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
387 Int_t column);
388
389template Float_t TRestTools::GetMaxValueFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data,
390 Int_t column);
391
392template Double_t TRestTools::GetMaxValueFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data,
393 Int_t column);
394
402template <typename T>
403T TRestTools::GetMinValueFromTable(const std::vector<std::vector<T>>& data, Int_t column) {
404 if (data.empty()) return 0;
405 if (column != -1 && data[0].size() <= (unsigned int)column) return 0;
406
407 T minValue = data[0][0];
408 if (column == -1) {
409 for (unsigned int n = 0; n < data.size(); n++)
410 for (unsigned int c = 0; c < data[n].size(); c++)
411 if (minValue > data[n][c]) minValue = data[n][c];
412 } else {
413 minValue = data[0][column];
414 for (unsigned int n = 0; n < data.size(); n++)
415 if (minValue > data[n][column]) minValue = data[n][column];
416 }
417
418 return minValue;
419}
420
421template Int_t TRestTools::GetMinValueFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
422 Int_t column);
423
424template Float_t TRestTools::GetMinValueFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data,
425 Int_t column);
426
427template Double_t TRestTools::GetMinValueFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data,
428 Int_t column);
429
439template <typename T>
440T TRestTools::GetLowestIncreaseFromTable(std::vector<std::vector<T>> data, Int_t column) {
441 if (data.size() == 0 || data[0].size() <= (unsigned int)column) return 0;
442 T lowestIncrease = abs(data[0][column] - data[1][column]);
443 for (unsigned int n = 1; n < data.size(); n++) {
444 T value = abs(data[n - 1][column] - data[n][column]);
445 if (lowestIncrease == 0) lowestIncrease = value;
446 if (value > 0 && value < lowestIncrease) lowestIncrease = value;
447 }
448 return lowestIncrease;
449}
450
451template Int_t TRestTools::GetLowestIncreaseFromTable<Int_t>(std::vector<std::vector<Int_t>> data,
452 Int_t column);
453
454template Float_t TRestTools::GetLowestIncreaseFromTable<Float_t>(std::vector<std::vector<Float_t>> data,
455 Int_t column);
456
457template Double_t TRestTools::GetLowestIncreaseFromTable<Double_t>(std::vector<std::vector<Double_t>> data,
458 Int_t column);
459
469template <typename T>
470T TRestTools::GetIntegralFromTable(const std::vector<std::vector<T>>& data) {
471 if (data.size() == 0) return 0;
472 T sum = 0;
473 for (unsigned int n = 0; n < data.size(); n++) {
474 for (unsigned int m = 0; m < data[n].size(); m++) sum += data[n][m];
475 }
476 return sum;
477}
478
479template Int_t TRestTools::GetIntegralFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data);
480
481template Float_t TRestTools::GetIntegralFromTable<Float_t>(const std::vector<std::vector<Float_t>>& data);
482
483template Double_t TRestTools::GetIntegralFromTable<Double_t>(const std::vector<std::vector<Double_t>>& data);
484
491template <typename T>
492std::vector<T> TRestTools::GetColumnFromTable(const std::vector<std::vector<T>>& data, unsigned int column) {
493 std::vector<T> columnData;
494 if (data.size() == 0 || data[0].size() <= column) return columnData;
495
496 for (unsigned int n = 0; n < data.size(); n++) columnData.push_back(data[n][column]);
497
498 return columnData;
499}
500
501template std::vector<Int_t> TRestTools::GetColumnFromTable<Int_t>(const std::vector<std::vector<Int_t>>& data,
502 unsigned int column);
503
504template std::vector<Float_t> TRestTools::GetColumnFromTable<Float_t>(
505 const std::vector<std::vector<Float_t>>& data, unsigned int column);
506
507template std::vector<Double_t> TRestTools::GetColumnFromTable<Double_t>(
508 const std::vector<std::vector<Double_t>>& data, unsigned int column);
509
523int TRestTools::ReadASCIITable(string fName, std::vector<std::vector<Double_t>>& data, Int_t skipLines,
524 std::string separator) {
525 if (!TRestTools::isValidFile((string)fName)) {
526 cout << "TRestTools::ReadASCIITable. Error" << endl;
527 cout << "Cannot open file : " << fName << endl;
528 return 0;
529 }
530
531 data.clear();
532
533 std::ifstream fin(fName);
534
535 // First we create a table with string values
536 std::vector<std::vector<string>> values;
537
538 for (string line; std::getline(fin, line);) {
539 if (skipLines > 0) {
540 skipLines--;
541 continue;
542 }
543
544 if (line.find("#") == string::npos) {
545 std::istringstream in(line);
546
547 std::string token;
548 std::vector<std::string> tokens;
549 while (std::getline(in, token, (char)separator[0])) {
550 tokens.push_back(token);
551 }
552 values.push_back(tokens);
553 }
554 }
555
556 // Filling the double values table (TODO error handling in case ToDouble conversion fails)
557 for (unsigned int n = 0; n < values.size(); n++) {
558 std::vector<Double_t> dblTmp;
559 dblTmp.clear();
560
561 for (unsigned int m = 0; m < values[n].size(); m++) dblTmp.push_back(StringToDouble(values[n][m]));
562
563 data.push_back(dblTmp);
564 }
565
566 return 1;
567}
568
582int TRestTools::ReadASCIITable(string fName, std::vector<std::vector<Float_t>>& data, Int_t skipLines,
583 std::string separator) {
584 if (!TRestTools::isValidFile((string)fName)) {
585 cout << "TRestTools::ReadASCIITable. Error" << endl;
586 cout << "Cannot open file : " << fName << endl;
587 return 0;
588 }
589
590 data.clear();
591
592 std::ifstream fin(fName);
593
594 // First we create a table with string values
595 std::vector<std::vector<string>> values;
596
597 for (string line; std::getline(fin, line);) {
598 if (skipLines > 0) {
599 skipLines--;
600 continue;
601 }
602
603 if (line.find("#") == string::npos) {
604 std::istringstream in(line);
605
606 std::string token;
607 std::vector<std::string> tokens;
608 while (std::getline(in, token, (char)separator[0])) {
609 tokens.push_back(token);
610 }
611 values.push_back(tokens);
612 }
613 }
614
615 // Filling the float values table (TODO error handling in case ToFloat conversion fails)
616 for (unsigned int n = 0; n < values.size(); n++) {
617 std::vector<Float_t> dblTmp;
618 dblTmp.clear();
619
620 for (unsigned int m = 0; m < values[n].size(); m++) dblTmp.push_back(StringToFloat(values[n][m]));
621
622 data.push_back(dblTmp);
623 }
624
625 return 1;
626}
627
641int TRestTools::ReadCSVFile(std::string fName, std::vector<std::vector<Double_t>>& data, Int_t skipLines) {
642 return ReadASCIITable(fName, data, skipLines, ",");
643}
644
658int TRestTools::ReadCSVFile(std::string fName, std::vector<std::vector<Float_t>>& data, Int_t skipLines) {
659 return ReadASCIITable(fName, data, skipLines, ",");
660}
661
665Int_t TRestTools::isValidFile(const string& path) { return std::filesystem::is_regular_file(path); }
666
674bool TRestTools::fileExists(const string& filename) { return std::filesystem::exists(filename); }
675
679bool TRestTools::isRootFile(const string& filename) { return GetFileNameExtension(filename) == "root"; }
680
684bool TRestTools::isRunFile(const std::string& filename) {
685 if (!isRootFile(filename)) return false;
686
687 TFile* f = TFile::Open((TString)filename);
688
689 TIter nextkey(f->GetListOfKeys());
690 TKey* key;
691 while ((key = (TKey*)nextkey())) {
692 if ((std::string)key->GetClassName() == "TRestRun") return true;
693 }
694 return false;
695}
696
700bool TRestTools::isDataSet(const std::string& filename) {
701 if (!isRootFile(filename)) return false;
702
703 TFile* f = TFile::Open((TString)filename);
704
705 TIter nextkey(f->GetListOfKeys());
706 TKey* key;
707 while ((key = (TKey*)nextkey())) {
708 if ((std::string)key->GetClassName() == "TRestDataSet") return true;
709 }
710 return false;
711}
712
716bool TRestTools::isURL(const string& s) {
717 std::regex pattern("^https?://(.+)");
718 return std::regex_match(s, pattern);
719}
720
724bool TRestTools::isPathWritable(const string& path) {
725 int result = 0;
726#ifdef WIN32
727 result = _access(path.c_str(), 2);
728#else
729 result = access(path.c_str(), 2);
730#endif
731
732 if (result == 0)
733 return true;
734 else
735 return false;
736}
737
741bool TRestTools::isAbsolutePath(const string& path) {
742 if (path[0] == '/' || path[0] == '~' || path.find(':') != string::npos) {
743 return true;
744 }
745 return false;
746}
747
759std::pair<string, string> TRestTools::SeparatePathAndName(const string& fullname) {
760 filesystem::path path(fullname);
761 return {path.parent_path().string(), path.filename().string()};
762}
763
769string TRestTools::GetFileNameExtension(const string& fullname) {
770 string extension = filesystem::path(fullname).extension().string();
771 if (extension.size() > 1) return extension.substr(1);
772 return extension;
773}
774
780string TRestTools::GetFileNameRoot(const string& fullname) {
781 return filesystem::path(fullname).stem().string();
782}
783
791 // we replace multiple appearances of "/" (slash) by a single "/"
792 string to_replace = "//";
793 size_t start_pos = str.find(to_replace);
794 while (start_pos != string::npos) {
795 str.replace(start_pos, to_replace.length(), "/");
796 start_pos = str.find(to_replace);
797 }
798 return str;
799}
800
809string TRestTools::GetPureFileName(const string& path) { return filesystem::path(path).filename().string(); }
810
814string TRestTools::ToAbsoluteName(const string& filename) {
815 filesystem::path path;
816 for (const auto& directory : filesystem::path(filename)) {
817 if (path.empty() && directory == "~") {
818 // path starts with ~
819 const auto envVariableHome = getenv("HOME");
820 if (envVariableHome == nullptr) {
821 cout << "TRestTools::ToAbsoluteName - ERROR - "
822 "cannot resolve ~ because 'HOME' env variable does not exist"
823 << endl;
824 exit(1);
825 }
826 const auto userHomePath = filesystem::path(envVariableHome);
827 if (userHomePath.empty()) {
828 cout << "TRestTools::ToAbsoluteName - ERROR - "
829 "cannot resolve ~ because 'HOME' env variable is not set to a valid value"
830 << endl;
831 exit(1);
832 }
833 path /= userHomePath;
834 } else {
835 path /= directory;
836 }
837 }
838 return filesystem::weakly_canonical(path).string();
839}
840
850vector<string> TRestTools::GetSubdirectories(const string& _path, int recursion) {
851 vector<string> result;
852
853 std::filesystem::path path(_path);
854 if (exists(path)) {
855 std::filesystem::directory_iterator iter(path);
856 for (auto& it : iter) {
857 if (it.is_directory()) {
858 result.push_back(it.path().string());
859
860 if (recursion != 0) {
861 vector<string> subD = GetSubdirectories(it.path().string(), recursion - 1);
862 result.insert(result.begin(), subD.begin(), subD.end());
863 }
864 }
865 }
866 }
867
868 return result;
869}
870
875string TRestTools::SearchFileInPath(vector<string> paths, string filename) {
876 if (fileExists(filename)) {
877 return filename;
878 } else {
879 for (unsigned int i = 0; i < paths.size(); i++) {
880 string path = paths[i];
881 if (path[path.size() - 1] != '/') {
882 path = path + "/";
883 }
884
885 if (fileExists(path + filename)) {
886 return path + filename;
887 }
888
889 // search also in subdirectory, but only 5 times of recursion
890 vector<string> pathsExpanded = GetSubdirectories(paths[i], 5);
891 for (unsigned int j = 0; j < pathsExpanded.size(); j++)
892 if (fileExists(pathsExpanded[j] + "/" + filename)) return pathsExpanded[j] + "/" + filename;
893 }
894 }
895 return "";
896}
897
902bool TRestTools::CheckFileIsAccessible(const std::string& filename) {
903 ifstream ifs;
904 ifs.open(filename.c_str());
905
906 if (!ifs) {
907 return false;
908 } else {
909 ifs.close();
910 }
911 return true;
912}
913
918vector<string> TRestTools::GetFilesMatchingPattern(string pattern) {
919 std::vector<string> outputFileNames;
920 if (pattern != "") {
921 vector<string> items = Split(pattern, "\n");
922 for (auto item : items) {
923 if (item.find_first_of("*?") != string::npos) {
924#ifdef WIN32
925 item = Replace(item, "/", "\\");
926 string item_trim =
927 item.substr(0, item.find_first_of("*?")); // trim string to before wildcard character
928 auto path_name = SeparatePathAndName(item_trim);
929 string _path = path_name.first;
930 if (!std::filesystem::exists(_path)) {
931 RESTError << "TRestTools::GetFilesMatchingPattern(): path " << _path << " does not exist!"
932 << RESTendl;
933 return outputFileNames;
934 }
935
936 std::filesystem::path path(_path);
937 std::filesystem::recursive_directory_iterator iter(path);
938 for (auto& it : iter) {
939 if (it.is_regular_file()) {
940 string filename = it.path().string();
941 if (MatchString(filename, item)) {
942 outputFileNames.push_back(it.path().string());
943 }
944 }
945 }
946#else
947 string a = Execute("find " + item);
948 auto b = Split(a, "\n");
949
950 for (unsigned int i = 0; i < b.size(); i++) {
951 outputFileNames.push_back(b[i]);
952 }
953#endif
954
955 } else {
956 if (fileExists(item)) outputFileNames.push_back(item);
957 }
958 }
959 }
960 return outputFileNames;
961}
962
967#ifndef REST_Version
968#define REST_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
969#endif
970 vector<string> ver = Split(in, ".");
971 if (ver.size() == 3) {
972 vector<int> verint;
973 for (auto v : ver) {
974 int n = StringToInteger(v.substr(0, v.find_first_not_of("0123456789")));
975 if (n != -1) {
976 verint.push_back(n);
977 } else {
978 return -1;
979 }
980 }
981 return REST_VERSION(verint[0], verint[1], verint[2]);
982 }
983 return -1;
984}
985
989string TRestTools::Execute(string cmd) {
990 std::array<char, 128> buffer;
991 string result;
992#ifdef WIN32
993 std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(("powershell.exe " + cmd).c_str(), "r"), _pclose);
994#else
995 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
996#endif // WIN32
997
998 if (!pipe) {
999 throw std::runtime_error("popen() failed!");
1000 }
1001 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
1002 result += buffer.data();
1003 }
1004
1005 if (result.size() > 0 && result[result.size() - 1] == '\n')
1006 result = result.substr(0, result.size() - 1); // remove last "\n"
1007
1008 return result;
1009}
1010
1015std::istream& TRestTools::GetLine(std::istream& is, std::string& t) {
1016 t.clear();
1017
1018 // The characters in the stream are read one-by-one using a std::streambuf.
1019 // That is faster than reading them one-by-one using the std::istream.
1020 // Code that uses streambuf this way must be guarded by a sentry object.
1021 // The sentry object performs various tasks,
1022 // such as thread synchronization and updating the stream state.
1023
1024 std::istream::sentry se(is, true);
1025 std::streambuf* sb = is.rdbuf();
1026
1027 for (;;) {
1028 int c = sb->sbumpc();
1029 switch (c) {
1030 case '\n':
1031 return is;
1032 case '\r':
1033 if (sb->sgetc() == '\n') sb->sbumpc();
1034 return is;
1035 case std::streambuf::traits_type::eof():
1036 // Also handle the case when the last line has no line ending
1037 if (t.empty()) is.setstate(std::ios::eofbit);
1038 return is;
1039 default:
1040 t += (char)c;
1041 }
1042 }
1043}
1044
1052std::string TRestTools::DownloadRemoteFile(const string& url) {
1053 string pureName = TRestTools::GetPureFileName(url);
1054 if (pureName.empty()) {
1055 RESTWarning << "error! (TRestTools::DownloadRemoteFile): url is not a file!" << RESTendl;
1056 RESTWarning << "please specify a concrete file name in this url" << RESTendl;
1057 RESTWarning << "url: " << url << RESTendl;
1058 return "";
1059 }
1060
1061 if (url.find("local:") == 0) {
1062 return Replace(url, "local:", "");
1063 } else {
1064 string fullpath = REST_USER_PATH + "/download/" + pureName;
1065 int out;
1066 int attempts = 10;
1067 do {
1068 out = TRestTools::DownloadRemoteFile(url, fullpath);
1069 if (out == 1024) {
1070 RESTWarning << "Retrying download in 5 seconds" << RESTendl;
1071 std::this_thread::sleep_for(std::chrono::seconds(5));
1072 } else if (attempts < 10) {
1073 RESTSuccess << "Download succeeded after " << 10 - attempts << " attempts" << RESTendl;
1074 }
1075 attempts--;
1076 } while (out == 1024 && attempts > 0);
1077
1078 if (out == 0 || TRestTools::fileExists(fullpath)) {
1079 return fullpath;
1080 } else {
1081 return "";
1082 }
1083 }
1084 return "";
1085}
1086
1093int TRestTools::DownloadRemoteFile(string remoteFile, string localFile) {
1094 TUrl url(remoteFile.c_str());
1095
1096 RESTInfo << "Downloading remote file : " << remoteFile << RESTendl;
1097 RESTInfo << "To local file : " << localFile << RESTendl;
1098
1099 string localFiletmp = localFile + ".restdownload";
1100 if ((string)url.GetProtocol() == "https" || (string)url.GetProtocol() == "http") {
1101 string path = TRestTools::SeparatePathAndName(localFiletmp).first;
1102 if (!TRestTools::fileExists(path)) {
1103 if (!filesystem::create_directories(path)) {
1104 std::cerr << "mkdir failed to create directory: " << path << std::endl;
1105 return -1;
1106 }
1107 }
1108
1109 string cmd = "wget --no-check-certificate " + EscapeSpecialLetters(remoteFile) + " -O " +
1110 EscapeSpecialLetters(localFiletmp) + " -q";
1111 RESTDebug << cmd << RESTendl;
1112 int a = system(cmd.c_str());
1113
1114 if (a == 0) {
1115 rename(localFiletmp.c_str(), localFile.c_str());
1116 return 0;
1117 } else {
1118 RESTError << "download failed! (" << remoteFile << ")" << RESTendl;
1119 if (a == 1024) {
1120 RESTError << "Network connection problem?" << RESTendl;
1121 return 1024;
1122 }
1123 if (a == 2048) {
1124 RESTError << "File does NOT exist in remotely?" << RESTendl;
1125 return 2048;
1126 }
1127 }
1128 } else if ((string)url.GetProtocol() == "ssh") {
1129 string cmd = "scp -P " + ToString(url.GetPort() == 0 ? 22 : url.GetPort()) + " " + url.GetUser() +
1130 "@" + url.GetHost() + ":" + EscapeSpecialLetters(url.GetFile()) + " " + localFiletmp;
1131 cout << cmd << endl;
1132 int a = system(cmd.c_str());
1133 if (a == 0) {
1134 rename(localFiletmp.c_str(), localFile.c_str());
1135 return 0;
1136 }
1137 } else {
1138 if (!TRestTools::fileExists(remoteFile)) {
1139 RESTWarning << "Trying to download: " << remoteFile << RESTendl;
1140 RESTWarning << "Unknown protocol!" << RESTendl;
1141 }
1142 }
1143
1144 return -1;
1145}
1146
1151std::string TRestTools::POSTRequest(const std::string& url, const std::map<std::string, std::string>& keys) {
1152 std::string file_content = "";
1153#ifdef USE_Curl
1154 CURL* curl;
1155 CURLcode res;
1156
1157 string filename = REST_USER_PATH + "/download/curl.out";
1158
1159 /* In windows, this will init the winsock stuff */
1160 curl_global_init(CURL_GLOBAL_ALL);
1161
1162 FILE* f = fopen(filename.c_str(), "wt");
1163
1164 std::string request = "";
1165 int n = 0;
1166 for (auto const& x : keys) {
1167 if (n > 0) request += "&";
1168 request += x.first + "=" + x.second;
1169 n++;
1170 }
1171 /* get a curl handle */
1172 curl = curl_easy_init();
1173 if (curl) {
1174 /* First set the URL that is about to receive our POST. This URL can
1175 just as well be a https:// URL if that is what should receive the
1176 data. */
1177 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
1178 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)f);
1179 /* Now specify the POST data */
1180 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str());
1181
1182 /* Perform the request, res will get the return code */
1183 res = curl_easy_perform(curl);
1184 /* Check for errors */
1185 if (res != CURLE_OK)
1186 RESTError << "curl_easy_perform() failed: " << curl_easy_strerror(res) << RESTendl;
1187
1188 /* always cleanup */
1189 curl_easy_cleanup(curl);
1190 }
1191 fclose(f);
1192 curl_global_cleanup();
1193
1194 std::getline(std::ifstream(filename), file_content, '\0');
1195#else
1196 RESTError << "TRestTools::POSTRequest. REST framework was compiled without CURL support" << RESTendl;
1197 RESTError << "Please recompile REST after installing curl development libraries." << RESTendl;
1198 RESTError << "Depending on your system this might be: curl-dev, curl-devel or libcurl-openssl-dev. "
1199 << RESTendl;
1200 RESTError << "No file will be downloaded" << RESTendl;
1201#endif
1202
1203 return file_content;
1204}
1205
1213int TRestTools::UploadToServer(string localFile, string remoteFile, string methodUrl) {
1214 if (!TRestTools::fileExists(localFile)) {
1215 cout << "error! local file not exist!" << endl;
1216 return -1;
1217 }
1218 // construct path
1219 // [proto://][user[:passwd]@]host[:port]/file.ext[#anchor][?options]
1220 TUrl url(remoteFile.c_str());
1221 TUrl method(methodUrl.c_str());
1222 if (method.GetProtocol() != (string) "") url.SetProtocol(method.GetProtocol());
1223 if (method.GetPort() != 0) url.SetPort(method.GetPort());
1224 if (method.GetUser() != (string) "") url.SetUser(method.GetUser());
1225 if (method.GetPasswd() != (string) "") url.SetPasswd(method.GetPasswd());
1226
1227 if ((string)url.GetProtocol() == "https" || (string)url.GetProtocol() == "http") {
1228 // maybe we use curl to upload to http in future
1229 } else if ((string)url.GetProtocol() == "ssh") {
1230 string cmd = "scp -P " + ToString(url.GetPort() == 0 ? 22 : url.GetPort()) + " " +
1231 EscapeSpecialLetters(localFile) + " " + url.GetUser() + "@" + url.GetHost() + ":" +
1232 EscapeSpecialLetters(url.GetFile());
1233 cout << cmd << endl;
1234 int a = system(cmd.c_str());
1235
1236 if (a != 0) {
1237 RESTError << __PRETTY_FUNCTION__ << RESTendl;
1238 RESTError << "problem copying gases definitions to remote server" << RESTendl;
1239 RESTError << "Please report this problem at "
1240 "http://gifna.unizar.es/rest-forum/"
1241 << RESTendl;
1242 return -1;
1243 }
1244
1245 return 0;
1246 }
1247 return 0;
1248}
1249
1250void TRestTools::ChangeDirectory(const string& toDirectory) { filesystem::current_path(toDirectory); }
1251
1252string ValueWithQuantity::ToString() const {
1253 string unit;
1254 auto value = fValue;
1255 if (fQuantity == ENERGY) {
1256 unit = "eV";
1257 value *= 1E3; // since we store energy in keV, not in eV
1258 } else if (fQuantity == TIME) {
1259 unit = "s"; // time is stored in microseconds
1260 value *= 1E-6;
1261 } else if (fQuantity == LENGTH) {
1262 unit = "m";
1263 value *= 1E-3; // since we store length in mm, not in m
1264 } else {
1265 return "";
1266 }
1267
1268 const auto abs = TMath::Abs(value);
1269 if (abs == 0) {
1270 return TString::Format("%d", 0).Data();
1271 } else if (abs < 1E-6) {
1272 return TString::Format("%.2f %s%s", value * 1E9, "n", unit.c_str()).Data();
1273 } else if (abs < 1E-3) {
1274 return TString::Format("%.2f %s%s", value * 1E6, "u", unit.c_str()).Data();
1275 } else if (abs < 1E0) {
1276 return TString::Format("%.2f %s%s", value * 1E3, "m", unit.c_str()).Data();
1277 } else if (abs < 1E3) {
1278 return TString::Format("%.2f %s%s", value * 1E0, "", unit.c_str()).Data();
1279 } else if (abs < 1E6) {
1280 return TString::Format("%.2f %s%s", value * 1E-3, "k", unit.c_str()).Data();
1281 } else if (abs < 1E9) {
1282 return TString::Format("%.2f %s%s", value * 1E-6, "M", unit.c_str()).Data();
1283 } else if (abs < 1E12) {
1284 return TString::Format("%.2f %s%s", value * 1E-9, "G", unit.c_str()).Data();
1285 } else {
1286 return TString::Format("%.2f %s%s", value * 1E-12, "T", unit.c_str()).Data();
1287 }
1288}
1289
1290string ToTimeStringLong(double seconds) {
1291 const auto abs = TMath::Abs(seconds);
1292 if (abs < 60) {
1293 return TString::Format("%.2f %s", seconds, "seconds").Data();
1294 } else if (abs < 60 * 60) {
1295 return TString::Format("%.2f %s", seconds / 60.0, "minutes").Data();
1296 } else if (abs < 60 * 60 * 24) {
1297 return TString::Format("%.2f %s", seconds / (60.0 * 60.0), "hours").Data();
1298 } else {
1299 return TString::Format("%.2f %s", seconds / (60.0 * 60.0 * 24.0), "days").Data();
1300 }
1301}
static std::string Execute(std::string cmd)
Executes a shell command and returns its output in a string.
Definition: TRestTools.cxx:989
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:759
static Int_t isValidFile(const std::string &path)
Returns true if the file with path filename exists.
Definition: TRestTools.cxx:665
static std::string GetFileNameExtension(const std::string &fullname)
Gets the file extension as the substring found after the latest ".".
Definition: TRestTools.cxx:769
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 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:850
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:523
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:902
static std::string GetPureFileName(const std::string &fullPathFileName)
Removes all directories in the full path filename description given in the argument.
Definition: TRestTools.cxx:809
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:251
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:313
static std::vector< std::string > GetOptions(std::string optionsStr)
Returns all the options in an option string.
Definition: TRestTools.cxx:86
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 std::string GetFileNameRoot(const std::string &fullname)
Gets the filename root as the substring found before the latest ".".
Definition: TRestTools.cxx:780
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:368
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:440
static void LoadRESTLibrary(bool silent=false)
Calls gSystem to load REST library.
Definition: TRestTools.cxx:95
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:641
static bool isRunFile(const std::string &filename)
It checks if the file has been processed using a REST event processing chain.
Definition: TRestTools.cxx:684
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:183
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:674
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:403
static int ConvertVersionCode(std::string in)
Convert version to a unique string.
Definition: TRestTools.cxx:966
static bool isPathWritable(const std::string &path)
Returns true if the path given by argument is writable.
Definition: TRestTools.cxx:724
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:470
static bool isAbsolutePath(const std::string &path)
Check if the path is absolute path or not.
Definition: TRestTools.cxx:741
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:212
static std::vector< std::string > GetFilesMatchingPattern(std::string pattern)
Returns a list of files whose name match the pattern string. Key word is "*". e.g....
Definition: TRestTools.cxx:918
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:301
static std::string DownloadRemoteFile(const std::string &remoteFile)
download the remote file automatically, returns the downloaded file name.
static std::string RemoveMultipleSlash(std::string)
Returns the input string but without multiple slashes ("/")
Definition: TRestTools.cxx:790
static bool isDataSet(const std::string &filename)
It checks if the file contains a dataset object.
Definition: TRestTools.cxx:700
static bool isURL(const std::string &filename)
Returns true if filename is an http address.
Definition: TRestTools.cxx:716
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 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:679
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:875
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:343
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:492
static std::string ToAbsoluteName(const std::string &filename)
It takes a path and returns its absolute path.
Definition: TRestTools.cxx:814
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 every occurences of thisSring by byThisString inside string in.