18#include "BDSException.hh"
19#include "BDSFieldLoaderQueryPoints.hh"
20#include "BDSFourVector.hh"
21#include "BDSUtilities.hh"
26#include "CLHEP/Units/SystemOfUnits.h"
38#include "src-external/gzstream/gzstream.h"
51 std::vector<G4String>* columnNamesIn)
const
53 G4String functionName =
"BDSFieldLoaderQueryPoints::Load> ";
60 bool validFile = file.rdbuf()->is_open();
62 bool validFile = file.is_open();
66 {
throw BDSException(functionName,
"Cannot open file \"" + fileName +
"\"");}
68 {G4cout << functionName <<
"loading \"" << fileName <<
"\"" << G4endl;}
71 std::vector<BDSFourVector<G4double>> result;
77 std::map<G4String, G4double*> columnNameToVariableAddress = { {
"x",&x},
81 std::map<G4String, G4double> columnNameToUnits = { {
"x", CLHEP::m},
85 std::vector<G4double*> values;
86 std::vector<G4double> units;
87 std::vector<G4String> columnNamesToPrint;
88 G4int nCoordinates = 0;
89 G4bool intoData =
false;
91 while (std::getline(file, line))
99 if (std::all_of(line.begin(), line.end(), isspace))
107 std::regex columnRow(
"^\\s*[!\\#]");
108 if (std::regex_search(line, columnRow))
110 std::regex afterExclamation(
"\\s*!\\s*(.+)");
112 std::regex_search(line, match, afterExclamation);
113 std::string restOfLine = match[1];
115 if (restOfLine.empty())
117 G4String msg =
"Error on line> " + std::to_string(lineNo);
118 msg +=
": column specification missing variables";
123 for (
const auto& columnName : columnNames)
126 auto search = columnNameToVariableAddress.find(variableName);
127 if (search == columnNameToVariableAddress.end())
129 G4String msg =
"Error on line> " + std::to_string(lineNo) +
"> variable name \"";
130 msg += variableName +
"\" is not one of 'x', 'y', 'z', 't'";
133 values.push_back(search->second);
134 units.push_back(columnNameToUnits[search->first]);
135 if (std::find(columnNamesToPrint.begin(), columnNamesToPrint.end(), search->first) != columnNamesToPrint.end())
136 {
throw BDSException(functionName,
"duplicate column name");}
137 columnNamesToPrint.push_back(search->first);
139 nCoordinates = (G4int)values.size();
140 G4cout << functionName <<
"assuming " << nCoordinates <<
" coordinate";
141 if (nCoordinates > 1)
143 G4cout <<
" in each line: (";
144 for (
const auto& coordName : columnNamesToPrint)
145 {G4cout <<
" " << coordName;}
146 G4cout <<
" )" << G4endl;
148 {*columnNamesIn = columnNamesToPrint;}
157 if ((G4int)wordsInLine.size() != nCoordinates)
158 {
throw BDSException(functionName,
"invalid number of coordinates on line " + std::to_string(lineNo));}
160 for (G4int i = 0; i < (G4int)values.size(); i++)
164 {coord = std::stod(wordsInLine[i]);}
165 catch (std::exception& e)
166 {
throw BDSException(functionName,
"Error on line> " + std::to_string(lineNo) +
"> cannot convert to number");}
167 (*values[i]) = coord * units[i];
177 G4cout << functionName <<
"loaded " << result.size() <<
" points" << G4endl;
183 std::vector<G4String>* columnNamesIn)
185 G4String functionName =
"BDS::LoadFieldQueryPoints>";
189 {
throw BDSException(functionName,
"no such file: \"" + fullFilePath +
"\"");}
191 std::vector<BDSFourVector<G4double>> result;
192 if (fullFilePath.rfind(
"gz") != std::string::npos)
196 result = loader.Load(fullFilePath, columnNamesIn);
198 throw BDSException(functionName,
"Compressed file loading - but BDSIM not compiled with ZLIB.");
204 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'.