OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
SDDSParser.h
Go to the documentation of this file.
1//
2// Class SDDSParser
3// This class writes column entries of SDDS files.
4//
5// Copyright (c) 2015, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18#ifndef __SDDSPARSER_H__
19#define __SDDSPARSER_H__
20
24
25#include <cmath>
26#include <cstddef>
27#include <string>
28#include <string_view>
29#include <type_traits>
30#include <unordered_map>
31#include <variant>
32
33namespace SDDS {
34
35 class SDDSParser {
36 private:
37 std::string readFile();
38 static std::string normalizeKey(std::string_view value);
39 std::string sddsFileName_m;
40
42 std::unordered_map<std::string, std::size_t> paramNameToID_m;
44 std::unordered_map<std::string, std::size_t> columnNameToID_m;
45
47
48 public:
49 SDDSParser();
50 SDDSParser(const std::string& input);
51 void setInput(const std::string& input);
52 file run();
53
54 const file& getData() const;
55 const ast::columnData_t& getColumnData(const std::string& columnName) const;
56
57 ast::dataType getColumnType(const std::string& col_name) const {
58 int index = getColumnIndex(col_name);
59 return *sddsData_m.sddsColumns_m[index].type_m;
60 }
61
70 template <typename T>
71 void getValue(int t, const std::string& column_name, T& nval) {
72
73 int col_idx = getColumnIndex(column_name);
74
75 // round timestep to last if not in range
76 std::size_t row_idx = 0;
77 std::size_t num_rows = sddsData_m.sddsColumns_m[col_idx].values_m.size();
78 if (num_rows == 0) {
79 throw SDDSParserException("SDDSParser::getValue",
80 "requested column has no parsed rows");
81 }
82 if (t <= 0 || static_cast<std::size_t>(t) > num_rows) {
83 row_idx = num_rows - 1;
84 } else {
85 row_idx = static_cast<std::size_t>(t) - 1;
86 }
87
88 const ast::variant_t& val = sddsData_m.sddsColumns_m[col_idx].values_m[row_idx];
89 nval = getVariantValue<T>(val, getColumnType(column_name));
90 }
91
101 template <typename T>
102 void getInterpolatedValue(const std::string& ref_name,
103 double ref_val,
104 const std::string& col_name,
105 T& nval) {
106 T value_before = 0;
107 T value_after = 0;
108 double value_before_ref = 0;
109 double value_after_ref = 0;
110
111 std::size_t col_idx_ref = getColumnIndex(ref_name);
112 ast::columnData_t &ref_values = sddsData_m.sddsColumns_m[col_idx_ref].values_m;
113 int index = getColumnIndex(col_name);
114 ast::columnData_t &col_values = sddsData_m.sddsColumns_m[index].values_m;
115
116 std::size_t this_row = 0;
117 std::size_t num_rows = ref_values.size();
118 ast::dataType dataType = getColumnType(col_name);
119 for (this_row = 0; this_row < num_rows; this_row++) {
120 value_after_ref = std::get<double>(ref_values[this_row]);
121
122 if (ref_val < value_after_ref) {
123
124 std::size_t prev_row = 0;
125 if (this_row > 0) prev_row = this_row - 1;
126
127 value_before = getVariantValue<T>(col_values[prev_row], dataType);
128 value_after = getVariantValue<T>(col_values[this_row], dataType);
129
130 value_before_ref = std::get<double>(ref_values[prev_row]);
131 value_after_ref = std::get<double>(ref_values[this_row]);
132
133 break;
134 }
135 }
136
137 if (this_row == num_rows) {
138 throw SDDSParserException("SDDSParser::getInterpolatedValue",
139 "all values < specified reference value");
140 }
141
142 // simple linear interpolation
143 if (ref_val - value_before_ref < 1e-8) {
144 nval = value_before;
145 } else {
146 nval = value_before + (ref_val - value_before_ref)
147 * (value_after - value_before)
148 / (value_after_ref - value_before_ref);
149 }
150
151 if (!std::isfinite(nval)) {
152 throw SDDSParserException("SDDSParser::getInterpolatedValue",
153 "Interpolated value either NaN or Inf.");
154 }
155
156 }
157
166 template <typename T>
167 void getInterpolatedValue(double spos, const std::string& col_name, T& nval) {
168 getInterpolatedValue("s", spos, col_name, nval);
169 }
170
178 template <typename T>
179 void getParameterValue(const std::string& parameter_name, T& nval) {
180 auto key = normalizeKey(parameter_name);
181 auto it = paramNameToID_m.find(key);
182 if (it != paramNameToID_m.end()) {
183 const auto& value = sddsData_m.sddsParameters_m[it->second].value_m;
184 nval = std::get<T>(value);
185 } else {
186 throw SDDSParserException("SDDSParser::getParameterValue",
187 "unknown parameter name: '" + key + "'!");
188 }
189 }
190
192 template <typename T>
193 T getVariantValue(const ast::variant_t& val, ast::dataType type) const {
194 static_assert(
195 std::is_same_v<T, float> ||
196 std::is_same_v<T, double> ||
197 std::is_same_v<T, short> ||
198 std::is_same_v<T, long>,
199 "Unsupported type T in SDDSParser::getVariantValue"
200 );
201
202 try {
203 switch (type) {
205 return static_cast<T>(std::get<float>(val));
206 }
208 return static_cast<T>(std::get<double>(val));
209 }
211 return static_cast<T>(std::get<short>(val));
212 }
213 case ast::dataType::LONG: {
214 return static_cast<T>(std::get<long>(val));
215 }
216 default: {
217 throw SDDSParserException("SDDSParser::getVariantValue",
218 "unsupported ast::dataType"
219 );
220 }
221 }
222 }
223 catch (const std::bad_variant_access&) {
224 throw SDDSParserException("SDDSParser::getVariantValue",
225 "variant and dataType mismatch"
226 );
227 }
228 }
229
230 private:
231 int getColumnIndex(const std::string& col_name) const;
232 };
233
234 inline
235 const file& SDDSParser::getData() const {
236 return sddsData_m;
237 }
238}
239
240#endif
std::variant< float, double, short, long, char, std::string > variant_t
Definition ast.hpp:49
std::vector< variant_t > columnData_t
Definition ast.hpp:51
std::string readFile()
static std::string normalizeKey(std::string_view value)
void getParameterValue(const std::string &parameter_name, T &nval)
Definition SDDSParser.h:179
std::unordered_map< std::string, std::size_t > paramNameToID_m
mapping from parameter name to offset in params_m
Definition SDDSParser.h:42
std::string sddsFileName_m
Definition SDDSParser.h:39
int getColumnIndex(const std::string &col_name) const
const file & getData() const
Definition SDDSParser.h:235
void setInput(const std::string &input)
T getVariantValue(const ast::variant_t &val, ast::dataType type) const
Convert value from variant (only numeric types) to a value of type T.
Definition SDDSParser.h:193
void getInterpolatedValue(double spos, const std::string &col_name, T &nval)
Definition SDDSParser.h:167
const ast::columnData_t & getColumnData(const std::string &columnName) const
void getValue(int t, const std::string &column_name, T &nval)
Definition SDDSParser.h:71
void getInterpolatedValue(const std::string &ref_name, double ref_val, const std::string &col_name, T &nval)
Definition SDDSParser.h:102
ast::dataType getColumnType(const std::string &col_name) const
Definition SDDSParser.h:57
SDDS::file sddsData_m
Definition SDDSParser.h:46
std::unordered_map< std::string, std::size_t > columnNameToID_m
mapping from column name to ID in columns_m
Definition SDDSParser.h:44
columnList sddsColumns_m
Definition file.hpp:37
parameterList sddsParameters_m
Definition file.hpp:36