19#include "BDSException.hh"
20#include "BDSFieldLoaderQueryPoints.hh"
21#include "BDSFourVector.hh"
22#include "BDSUtilities.hh"
27#include "CLHEP/Units/SystemOfUnits.h"
39#include "src-external/gzstream/gzstream.h"
52 std::vector<G4String>* columnNamesIn)
const
54 G4String functionName =
"BDSFieldLoaderQueryPoints::Load> ";
61 bool validFile = file.rdbuf()->is_open();
63 bool validFile = file.is_open();
67 {
throw BDSException(functionName,
"Cannot open file \"" + fileName +
"\"");}
69 {G4cout << functionName <<
"loading \"" << fileName <<
"\"" << G4endl;}
72 std::vector<BDSFourVector<G4double>> result;
78 std::map<G4String, G4double*> columnNameToVariableAddress = { {
"x",&x},
82 std::map<G4String, G4double> columnNameToUnits = { {
"x", CLHEP::m},
86 std::vector<G4double*> values;
87 std::vector<G4double> units;
88 std::vector<G4String> columnNamesToPrint;
89 G4int nCoordinates = 0;
90 G4bool intoData =
false;
92 while (std::getline(file, line))
100 if (std::all_of(line.begin(), line.end(), isspace))
108 std::regex columnRow(
"^\\s*[!\\#]");
109 if (std::regex_search(line, columnRow))
111 std::regex afterExclamation(
"\\s*!\\s*(.+)");
113 std::regex_search(line, match, afterExclamation);
114 std::string restOfLine = match[1];
116 if (restOfLine.empty())
118 G4String msg =
"Error on line> " + std::to_string(lineNo);
119 msg +=
": column specification missing variables";
124 for (
const auto& columnName : columnNames)
127 auto search = columnNameToVariableAddress.find(variableName);
128 if (search == columnNameToVariableAddress.end())
130 G4String msg =
"Error on line> " + std::to_string(lineNo) +
"> variable name \"";
131 msg += variableName +
"\" is not one of 'x', 'y', 'z', 't'";
134 values.push_back(search->second);
135 units.push_back(columnNameToUnits[search->first]);
136 if (std::find(columnNamesToPrint.begin(), columnNamesToPrint.end(), search->first) != columnNamesToPrint.end())
137 {
throw BDSException(functionName,
"duplicate column name");}
138 columnNamesToPrint.push_back(search->first);
140 nCoordinates = (G4int)values.size();
141 G4cout << functionName <<
"assuming " << nCoordinates <<
" coordinate";
142 if (nCoordinates > 1)
144 G4cout <<
" in each line: (";
145 for (
const auto& coordName : columnNamesToPrint)
146 {G4cout <<
" " << coordName;}
147 G4cout <<
" )" << G4endl;
149 {*columnNamesIn = columnNamesToPrint;}
158 if ((G4int)wordsInLine.size() != nCoordinates)
159 {
throw BDSException(functionName,
"invalid number of coordinates on line " + std::to_string(lineNo));}
161 for (G4int i = 0; i < (G4int)values.size(); i++)
165 {coord = std::stod(wordsInLine[i]);}
166 catch (std::exception& e)
167 {
throw BDSException(functionName,
"Error on line> " + std::to_string(lineNo) +
"> cannot convert to number");}
168 (*values[i]) = coord * units[i];
178 G4cout << functionName <<
"loaded " << result.size() <<
" points" << G4endl;
184 std::vector<G4String>* columnNamesIn)
186 G4String functionName =
"BDS::LoadFieldQueryPoints>";
190 {
throw BDSException(functionName,
"no such file: \"" + fullFilePath +
"\"");}
192 std::vector<BDSFourVector<G4double>> result;
193 if (fullFilePath.rfind(
"gz") != std::string::npos)
197 result = loader.Load(fullFilePath, columnNamesIn);
199 throw BDSException(functionName,
"Compressed file loading - but BDSIM not compiled with ZLIB.");
205 result = loader.Load(fullFilePath, columnNamesIn);
General exception with possible name of object and message.
A loader for up to 4D points for querying fields.
A simple templated four vector class.
std::vector< BDSFourVector< G4double > > LoadFieldQueryPoints(const G4String &fileName, std::vector< G4String > *columnNamesIn)
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4String LowerCase(const G4String &str)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
G4bool FileExists(const G4String &filename)
Checks if filename exists.
std::vector< G4String > SplitOnWhiteSpace(const G4String &input)
Split a string on whitespace and return a vector of these 'words'.