16 #include <TBufferJSON.h>
25 namespace experimental {
29 const std::vector<real_t>& old_x_values,
30 std::vector<real_t>& new_x_values)
const {
31 new_x_values.resize(old_x_values.size());
32 for (
size_t i = 0; i < old_x_values.size(); i++) {
39 const std::vector<real_t>& old_y_values,
40 std::vector<real_t>& new_y_values)
const {
41 new_y_values.resize(old_y_values.size());
42 for (
size_t i = 0; i < old_y_values.size(); i++) {
49 const std::vector<real_t>& old_y_error_low,
50 std::vector<real_t>& new_y_error_low)
const {
51 new_y_error_low.resize(old_y_error_low.size());
52 for (
size_t i = 0; i < old_y_error_low.size(); i++) {
60 const std::vector<real_t>& old_y_error_high,
61 std::vector<real_t>& new_y_error_high)
const {
62 new_y_error_high.resize(old_y_error_high.size());
63 for (
size_t i = 0; i < old_y_error_high.size(); i++) {
98 : ycollector(ycollector), xcollector(xcollector) {}
103 : y_reducer_collector(y_reducer_collector), xcollector(xcollector) {}
107 : ycollector(other.ycollector),
108 xcollector(other.xcollector),
109 x_values(other.x_values),
110 y_values(other.y_values),
111 y_error_low(other.y_error_low),
112 y_error_high(other.y_error_high) {
120 if (
this == &other) {
137 if (y_reducer_collector) {
138 delete y_reducer_collector;
147 "The time series objects that should be merged do not "
148 "contain the same entries. Operation aborted.");
149 return std::numeric_limits<real_t>::infinity();
151 for (
auto& p : ts1.
data_) {
152 if (ts2.
data_.find(p.first) == ts2.
data_.end()) {
154 "The time series objects that should be merged do not "
155 "contain the same entries. Operation aborted");
156 return std::numeric_limits<real_t>::infinity();
160 for (
auto& pair : ts1.
data_) {
161 auto& key = pair.first;
163 auto& xref = ts1.
data_.at(key).x_values;
164 auto& xcurrent = ts2.
data_.at(key).x_values;
165 if (xref.size() != xcurrent.size()) {
167 "The time series objects for entry (", key,
168 ") have different x_values. Operation aborted.");
169 return std::numeric_limits<real_t>::infinity();
171 for (uint64_t j = 0; j < xref.size(); ++j) {
172 if (std::abs(xref[j] - xcurrent[j]) > 1e-5) {
174 "The time series objects for entry (", key,
175 ") have different x_values. Operation aborted.");
176 return std::numeric_limits<real_t>::infinity();
183 for (
auto& pair : ts1.
data_) {
184 auto& key = pair.first;
185 auto& yref = ts1.
data_.at(key).y_values;
186 auto& ycurrent = ts2.
data_.at(key).y_values;
199 TimeSeries* merged,
const std::vector<TimeSeries>& time_series,
200 const std::function<
void(
const std::vector<real_t>&,
real_t*,
real_t*,
204 "Parameter 'merged' is a nullptr. Operation aborted.");
209 if (merged->
data_.size() != 0) {
211 "Parameter 'merged' is not empty. Operation aborted.");
215 if (time_series.size() == 0) {
217 "The given time series vector is empty. Operation aborted.");
219 }
else if (time_series.size() == 1) {
220 *merged = time_series[0];
225 auto& ref = time_series[0];
226 for (uint64_t i = 1; i < time_series.size(); ++i) {
227 auto& current = time_series[i];
228 if (ref.data_.size() != current.data_.size()) {
230 "The time series objects that should be merged do not "
231 "contain the same entries. Operation aborted.");
234 for (
auto& p : ref.data_) {
235 if (current.data_.find(p.first) == current.data_.end()) {
237 "The time series objects that should be merged do not "
238 "contain the same entries. Operation aborted");
244 for (
auto& pair : ref.data_) {
245 auto& key = pair.first;
247 auto& xref = ref.data_.at(key).x_values;
248 for (uint64_t i = 1; i < time_series.size(); ++i) {
249 auto& xcurrent = time_series[i].data_.at(key).x_values;
250 if (xref.size() != xcurrent.size()) {
251 Log::Warning(
"TimeSeries::Merge",
"The time series objects for entry (",
252 key,
") have different x_values. Operation aborted.");
255 for (uint64_t j = 0; j < xref.size(); ++j) {
256 if (std::abs(xref[j] - xcurrent[j]) > 1e-5) {
258 "The time series objects for entry (", key,
259 ") have different x_values. Operation aborted.");
269 auto& mdata = merged->
data_[key];
270 mdata.x_values.resize(xref.size());
271 mdata.y_values.resize(xref.size());
272 mdata.y_error_low.resize(xref.size());
273 mdata.y_error_high.resize(xref.size());
275 #pragma omp parallel for
276 for (uint64_t i = 0; i < xref.size(); ++i) {
277 mdata.x_values[i] = xref[i];
278 std::vector<real_t> all_y_values(time_series.size());
279 for (uint64_t j = 0; j < time_series.size(); ++j) {
280 all_y_values[j] = time_series[j].data_.at(key).y_values[i];
281 merger(all_y_values, &mdata.y_values[i], &mdata.y_error_low[i],
282 &mdata.y_error_high[i]);
296 : data_(std::move(other.data_)) {}
300 data_ = std::move(other.data_);
314 auto it =
data_.find(
id);
315 if (it !=
data_.end()) {
316 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
317 ") exists already. Operation aborted.");
319 data_.emplace(
id,
Data(ycollector, xcollector));
326 auto it =
data_.find(
id);
327 if (it !=
data_.end()) {
328 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
329 ") exists already. Operation aborted.");
331 data_.emplace(
id,
Data(y_reducer_collector, xcollector));
336 const std::string& transformed_id,
339 auto previous_data =
data_.find(old_id);
340 if (previous_data ==
data_.end()) {
341 Log::Warning(
"TimeSeries::AddTransformed",
"TimeSeries with id (", old_id,
342 ") does not exist. Operation aborted.");
346 auto transformed_data =
data_.find(transformed_id);
347 if (transformed_data !=
data_.end()) {
348 Log::Warning(
"TimeSeries::AddTransformed",
"TimeSeries with id (",
349 transformed_id,
") exists already. Operation aborted.");
357 const auto& previous = previous_data->second;
364 data_.emplace(transformed_id, data);
369 if (!
data_.empty()) {
371 auto* scheduler = sim->GetScheduler();
372 auto* param = sim->GetParam();
375 std::vector<std::pair<Reducer<real_t>*,
const std::string>> reducers;
376 for (
auto& entry :
data_) {
377 auto& result_data = entry.second;
378 if (result_data.y_reducer_collector ==
nullptr) {
381 result_data.y_reducer_collector->Reset();
383 std::make_pair(result_data.y_reducer_collector, entry.first));
384 if (result_data.xcollector ==
nullptr) {
385 result_data.x_values.push_back(scheduler->GetSimulatedSteps() *
386 param->simulation_time_step);
388 result_data.x_values.push_back(result_data.xcollector(sim));
393 auto execute_reducers =
L2F([&](
Agent* agent) {
394 for (
auto& el : reducers) {
398 sim->GetResourceManager()->ForEachAgentParallel(execute_reducers);
399 for (
auto& el : reducers) {
400 data_[el.second].y_values.push_back(el.first->GetResult());
405 for (
auto& entry :
data_) {
406 auto& result_data = entry.second;
407 if (result_data.ycollector ==
nullptr) {
410 result_data.y_values.push_back(result_data.ycollector(sim));
411 if (result_data.xcollector ==
nullptr) {
412 result_data.x_values.push_back(scheduler->GetSimulatedSteps() *
413 param->simulation_time_step);
415 result_data.x_values.push_back(result_data.xcollector(sim));
426 "Adding a TimeSeries to itself is not supported. Operation aborted.");
429 for (
auto& p : ts.
data_) {
431 auto id =
Concat(p.first,
"-", suffix);
433 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
434 ") exists already. Consider changing the suffix parameter "
435 "to make it unique. Operation aborted.");
439 data_.emplace(
id, p.second);
445 const std::vector<real_t>& y_values) {
447 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
448 ") exists already. Consider changing the suffix parameter to "
449 "make it unique. Operation aborted.");
456 data_.emplace(
id, data);
461 const std::vector<real_t>& y_values,
462 const std::vector<real_t>& y_error_low,
463 const std::vector<real_t>& y_error_high) {
465 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
466 ") exists already. Consider changing the suffix parameter to "
467 "make it unique. Operation aborted.");
476 data_.emplace(
id, data);
481 const std::vector<real_t>& y_values,
482 const std::vector<real_t>& y_error) {
484 Log::Warning(
"TimeSeries::Add",
"TimeSeries with id (",
id,
485 ") exists already. Consider changing the suffix parameter to "
486 "make it unique. Operation aborted.");
494 data_.emplace(
id, data);
507 return data_.at(
id).x_values;
512 return data_.at(
id).y_values;
517 const std::string&
id)
const {
518 return data_.at(
id).y_error_low;
523 const std::string&
id)
const {
524 return data_.at(
id).y_error_high;
529 for (
auto& p :
data_) {
530 std::cout << p.first << std::endl;
541 TBufferJSON::ExportToFile(full_filepath.c_str(),
this, Class());
Contains code required by all agents.
static void Warning(const std::string &location, const Args &... parts)
Prints warning message.
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
TimeSeries & operator=(TimeSeries &&other) noexcept
const std::vector< real_t > & GetYValues(const std::string &id) const
static void Merge(TimeSeries *merged, const std::vector< TimeSeries > &time_series, const std::function< void(const std::vector< real_t > &, real_t *, real_t *, real_t *)> &merger)
void AddTransformedData(const std::string &old_id, const std::string &transformed_id, const DataTransformer &transformer)
void SaveJson(const std::string &full_filepath) const
Saves a json representation to disk.
void AddCollector(const std::string &id, real_t(*ycollector)(Simulation *), real_t(*xcollector)(Simulation *)=nullptr)
const std::vector< real_t > & GetYErrorHigh(const std::string &id) const
static void Load(const std::string &full_filepath, TimeSeries **restored)
std::unordered_map< std::string, Data > data_
void Save(const std::string &full_filepath) const
Saves a root file to disk.
void Add(const std::string &id, const std::vector< real_t > &x_values, const std::vector< real_t > &y_values)
bool Contains(const std::string &id) const
Returns whether a times series with given id exists in this object.
void ListEntries() const
Print all time series entry names to stdout.
void Update()
Adds a new data point to all time series with a collector.
static real_t ComputeError(const TimeSeries &ts1, const TimeSeries &ts2)
Computes the mean squared error between ts1 and ts2
const std::vector< real_t > & GetYErrorLow(const std::string &id) const
const std::vector< real_t > & GetXValues(const std::string &id) const
LambdaFunctor< decltype(&TLambda::operator())> L2F(const TLambda &l)
std::string Concat(const Args &... parts)
Concatenates all arguments into a string. Equivalent to streaming all arguments into a stringstream a...
void WritePersistentObject(const char *root_file, const char *obj_name, const T &pst_object, const char *mode="new")
Writes a persistent object to the specified ROOT file.
bool GetPersistentObject(const char *root_file, const char *obj_name, T *&empty_obj)
Gets the persistent object from the specified ROOT file.
static real_t MSE(const std::vector< real_t > &v1, const std::vector< real_t > &v2)
Returns the mean squared error between two vectors.
virtual Reducer * NewCopy() const =0
std::vector< real_t > y_error_high
Data & operator=(const Data &other)
Reducer< real_t > * y_reducer_collector
real_t(* xcollector)(Simulation *)
std::vector< real_t > x_values
std::vector< real_t > y_values
std::vector< real_t > y_error_low
real_t(* ycollector)(Simulation *)