Commit b4abca9f authored by Thibault Hallouin's avatar Thibault Hallouin
Browse files

refactor determinist Evaluator

including:
- extracting the element/intermediate/metric calculations from the
  `determinist::Evaluator` class
- introducing new getter methods in `determinist::Evaluator` class
  that handle the element/intermediate/metric inter-dependencies
  internally to the object
- removing external inter-dependencies handling from `evald`
1 merge request!3release v0.1.0
Pipeline #42829 passed with stage
in 2 minutes and 4 seconds
Showing with 844 additions and 574 deletions
+844 -574
#ifndef EVALHYD_DETERMINIST_ELEMENTS_HPP
#define EVALHYD_DETERMINIST_ELEMENTS_HPP
#include <xtensor/xtensor.hpp>
#include <xtensor/xview.hpp>
#include "../maths.hpp"
namespace evalhyd
{
namespace determinist
{
namespace elements
{
// Compute the mean of the observations.
//
// \param q_obs
// Streamflow observations.
// shape: (1, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Mean observed streamflow.
// shape: (subsets, samples, series, 1)
template <class D2>
inline xt::xtensor<double, 4> calc_mean_obs(
const D2& q_obs,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 4> mean_obs =
xt::zeros<double>({n_msk, n_exp, n_srs, std::size_t {1}});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto obs_masked = xt::where(xt::view(t_msk, m), q_obs, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
// apply the bootstrap sampling
auto obs = xt::view(obs_masked, xt::all(), b_exp[e]);
xt::view(mean_obs, m, e) =
xt::nanmean(obs, -1, xt::keep_dims);
}
}
return mean_obs;
}
// Compute the mean of the predictions.
//
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Mean predicted streamflow.
// shape: (subsets, samples, series, 1)
template <class D2>
inline xt::xtensor<double, 4> calc_mean_prd(
const D2& q_prd,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 4> mean_prd =
xt::zeros<double>({n_msk, n_exp, n_srs, std::size_t {1}});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto prd_masked = xt::where(xt::view(t_msk, m), q_prd, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
// apply the bootstrap sampling
auto prd = xt::view(prd_masked, xt::all(), b_exp[e]);
xt::view(mean_prd, m, e) =
xt::nanmean(prd, -1, xt::keep_dims);
}
}
return mean_prd;
}
// Compute the quadratic error between observations and predictions.
//
// \param q_obs
// Streamflow observations.
// shape: (1, time)
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \return
// Quadratic errors between observations and predictions.
// shape: (series, time)
template <class D2>
inline xt::xtensor<double, 2> calc_quad_err(
const D2& q_obs,
const D2& q_prd
)
{
return xt::square(q_obs - q_prd);
}
// Compute the quadratic error between observations and mean observation.
//
// \param q_obs
// Streamflow observations.
// shape: (series, time)
// \param mean_obs
// Mean observed streamflow.
// shape: (subsets, samples, series, 1)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param n_srs
// Number of prediction series.
// \param n_tim
// Number of time steps.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Quadratic errors between observations and mean observation.
// shape: (subsets, samples, series, time)
template <class D2>
inline xt::xtensor<double, 4> calc_quad_obs(
const D2& q_obs,
const xt::xtensor<double, 4>& mean_obs,
const xt::xtensor<bool, 3>& t_msk,
std::size_t n_srs,
std::size_t n_tim,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 4> quad_obs =
xt::zeros<double>({n_msk, n_exp, n_srs, n_tim});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto obs_masked = xt::where(xt::view(t_msk, m), q_obs, NAN);
for (std::size_t e = 0; e < n_exp; e++)
{
xt::view(quad_obs, m, e) = xt::square(
obs_masked - xt::view(mean_obs, m, e)
);
}
}
return quad_obs;
}
// Compute the quadratic error between predictions and mean prediction.
//
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \param mean_prd
// Mean predicted streamflow.
// shape: (subsets, samples, series, 1)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param n_srs
// Number of prediction series.
// \param n_tim
// Number of time steps.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Quadratic errors between predictions and mean prediction.
// shape: (subsets, samples, series, time)
template <class D2>
inline xt::xtensor<double, 4> calc_quad_prd(
const D2& q_prd,
const xt::xtensor<double, 4>& mean_prd,
const xt::xtensor<bool, 3>& t_msk,
std::size_t n_srs,
std::size_t n_tim,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 4> quad_prd =
xt::zeros<double>({n_msk, n_exp, n_srs, n_tim});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto prd_masked = xt::where(xt::view(t_msk, m), q_prd, NAN);
for (std::size_t e = 0; e < n_exp; e++)
{
xt::view(quad_prd, m, e) = xt::square(
prd_masked - xt::view(mean_prd, m, e)
);
}
}
return quad_prd;
}
// Compute the Pearson correlation coefficient.
//
// \param q_obs
// Streamflow observations.
// shape: (series, time)
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \param mean_obs
// Mean observed streamflow.
// shape: (subsets, samples, series, 1)
// \param mean_prd
// Mean predicted streamflow.
// shape: (subsets, samples, series, 1)
// \param quad_obs
// Quadratic errors between observations and mean observation.
// shape: (subsets, samples, series, time)
// \param quad_prd
// Quadratic errors between predictions and mean prediction.
// shape: (subsets, samples, series, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Pearson correlation coefficients.
// shape: (subsets, samples, series)
template <class D2>
inline xt::xtensor<double, 3> calc_r_pearson(
const D2& q_obs,
const D2& q_prd,
const xt::xtensor<double, 4>& mean_obs,
const xt::xtensor<double, 4>& mean_prd,
const xt::xtensor<double, 4>& quad_obs,
const xt::xtensor<double, 4>& quad_prd,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
// calculate error in timing and dynamics $r_{pearson}$
// (Pearson's correlation coefficient)
xt::xtensor<double, 3> r_pearson =
xt::zeros<double>({n_msk, n_exp, n_srs});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto prd_masked = xt::where(xt::view(t_msk, m), q_prd, NAN);
auto obs_masked = xt::where(xt::view(t_msk, m), q_obs, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
auto prd = xt::view(prd_masked, xt::all(), b_exp[e]);
auto obs = xt::view(obs_masked, xt::all(), b_exp[e]);
auto r_num = xt::nansum(
(prd - xt::view(mean_prd, m, e))
* (obs - xt::view(mean_obs, m, e)),
-1
);
auto prd2 = xt::view(quad_prd, m, e, xt::all(), b_exp[e]);
auto obs2 = xt::view(quad_obs, m, e, xt::all(), b_exp[e]);
auto r_den = xt::sqrt(
xt::nansum(prd2, -1) * xt::nansum(obs2, -1)
);
xt::view(r_pearson, m, e) = r_num / r_den;
}
}
return r_pearson;
}
// Compute alpha.
//
// \param q_obs
// Streamflow observations.
// shape: (series, time)
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \param mean_obs
// Mean observed streamflow.
// shape: (subsets, samples, series, 1)
// \param mean_prd
// Mean predicted streamflow.
// shape: (subsets, samples, series, 1)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Alphas, ratios of standard deviations.
// shape: (subsets, samples, series)
template <class D2>
inline xt::xtensor<double, 3> calc_alpha(
const D2& q_obs,
const D2& q_prd,
const xt::xtensor<double, 4>& mean_obs,
const xt::xtensor<double, 4>& mean_prd,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
// calculate error in spread of flow $alpha$
xt::xtensor<double, 3> alpha =
xt::zeros<double>({n_msk, n_exp, n_srs});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto prd_masked = xt::where(xt::view(t_msk, m), q_prd, NAN);
auto obs_masked = xt::where(xt::view(t_msk, m), q_obs, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
auto prd = xt::view(prd_masked, xt::all(), b_exp[e]);
auto obs = xt::view(obs_masked, xt::all(), b_exp[e]);
xt::view(alpha, m, e) =
maths::nanstd(prd, xt::view(mean_prd, m, e))
/ maths::nanstd(obs, xt::view(mean_obs, m, e));
}
}
return alpha;
}
// Compute the bias.
//
// \param q_obs
// Streamflow observations.
// shape: (series, time)
// \param q_prd
// Streamflow predictions.
// shape: (series, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Biases.
// shape: (subsets, samples, series)
template <class D2>
inline xt::xtensor<double, 3> calc_bias(
const D2& q_obs,
const D2& q_prd,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
// calculate $bias$
xt::xtensor<double, 3> bias =
xt::zeros<double>({n_msk, n_exp, n_srs});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto prd_masked = xt::where(xt::view(t_msk, m), q_prd, NAN);
auto obs_masked = xt::where(xt::view(t_msk, m), q_obs, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
auto prd = xt::view(prd_masked, xt::all(), b_exp[e]);
auto obs = xt::view(obs_masked, xt::all(), b_exp[e]);
xt::view(bias, m, e) =
xt::nansum(prd, -1) / xt::nansum(obs, -1);
}
}
return bias;
}
}
}
}
#endif //EVALHYD_DETERMINIST_ELEMENTS_HPP
This diff is collapsed.
#ifndef EVALHYD_DETERMINIST_METRICS_HPP
#define EVALHYD_DETERMINIST_METRICS_HPP
#include <xtensor/xtensor.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/xoperation.hpp>
namespace evalhyd
{
namespace determinist
{
namespace metrics
{
// Compute the root-mean-square error (RMSE).
//
// \param quad_err
// Quadratic errors between observations and predictions.
// shape: (series, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Root-mean-square errors.
// shape: (series, subsets, samples)
inline xt::xtensor<double, 3> calc_RMSE(
const xt::xtensor<double, 2>& quad_err,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
// compute RMSE
xt::xtensor<double, 3> RMSE =
xt::zeros<double>({n_srs, n_msk, n_exp});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto quad_err_masked = xt::where(xt::view(t_msk, m), quad_err, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
auto err2 = xt::view(quad_err_masked, xt::all(), b_exp[e]);
xt::view(RMSE, xt::all(), m, e) = xt::sqrt(xt::nanmean(err2, -1));
}
}
return RMSE;
}
// Compute the Nash-Sutcliffe Efficiency (NSE).
//
// \param quad_err
// Quadratic errors between observations and predictions.
// shape: (series, time)
// \param quad_obs
// Quadratic errors between observations and mean observation.
// shape: (subsets, samples, series, time)
// \param t_msk
// Temporal subsets of the whole record.
// shape: (subsets, series, time)
// \param b_exp
// Boostrap samples.
// shape: (samples, time slice)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Nash-Sutcliffe efficiencies.
// shape: (series, subsets, samples)
inline xt::xtensor<double, 3> calc_NSE(
const xt::xtensor<double, 2>& quad_err,
const xt::xtensor<double, 4>& quad_obs,
const xt::xtensor<bool, 3>& t_msk,
const std::vector<xt::xkeep_slice<int>>& b_exp,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 3> NSE =
xt::zeros<double>({n_srs, n_msk, n_exp});
for (std::size_t m = 0; m < n_msk; m++)
{
// apply the mask
// (using NaN workaround until reducers work on masked_view)
auto quad_err_masked = xt::where(xt::view(t_msk, m), quad_err, NAN);
// compute variable one sample at a time
for (std::size_t e = 0; e < n_exp; e++)
{
// compute squared errors operands
auto err2 = xt::view(quad_err_masked, xt::all(), b_exp[e]);
xt::xtensor<double, 1> f_num =
xt::nansum(err2, -1);
auto obs2 = xt::view(quad_obs, m, e, xt::all(), b_exp[e]);
xt::xtensor<double, 1> f_den =
xt::nansum(obs2, -1);
// compute NSE
xt::view(NSE, xt::all(), m, e) = 1 - (f_num / f_den);
}
}
return NSE;
}
// Compute the Kling-Gupta Efficiency (KGE).
//
// \param r_pearson
// Pearson correlation coefficients.
// shape: (subsets, samples, series)
// \param alpha
// Alphas, ratios of standard deviations.
// shape: (subsets, samples, series)
// \param bias
// Biases.
// shape: (subsets, samples, series)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Kling-Gupta efficiencies.
// shape: (series, subsets, samples)
inline xt::xtensor<double, 3> calc_KGE(
const xt::xtensor<double, 3>& r_pearson,
const xt::xtensor<double, 3>& alpha,
const xt::xtensor<double, 3>& bias,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 3> KGE =
xt::zeros<double>({n_srs, n_msk, n_exp});
for (std::size_t m = 0; m < n_msk; m++)
{
for (std::size_t e = 0; e < n_exp; e++)
{
// compute KGE
xt::view(KGE, xt::all(), m, e) = 1 - xt::sqrt(
xt::square(xt::view(r_pearson, m, e) - 1)
+ xt::square(xt::view(alpha, m, e) - 1)
+ xt::square(xt::view(bias, m, e) - 1)
);
}
}
return KGE;
}
// Compute the modified Kling-Gupta Efficiency (KGEPRIME).
//
// \param mean_obs
// Mean observed streamflow.
// shape: (subsets, samples, series, 1)
// \param mean_prd
// Mean predicted streamflow.
// shape: (subsets, samples, series, 1)
// \param r_pearson
// Pearson correlation coefficients.
// shape: (subsets, samples, series)
// \param alpha
// Alphas, ratios of standard deviations.
// shape: (subsets, samples, series)
// \param bias
// Biases.
// shape: (subsets, samples, series)
// \param n_srs
// Number of prediction series.
// \param n_msk
// Number of temporal subsets.
// \param n_exp
// Number of bootstrap samples.
// \return
// Modified Kling-Gupta efficiencies.
// shape: (series, subsets, samples)
inline xt::xtensor<double, 3> calc_KGEPRIME(
const xt::xtensor<double, 4>& mean_obs,
const xt::xtensor<double, 4>& mean_prd,
const xt::xtensor<double, 3>& r_pearson,
const xt::xtensor<double, 3>& alpha,
const xt::xtensor<double, 3>& bias,
std::size_t n_srs,
std::size_t n_msk,
std::size_t n_exp
)
{
xt::xtensor<double, 3> KGEPRIME =
xt::zeros<double>({n_srs, n_msk, n_exp});
for (std::size_t m = 0; m < n_msk; m++)
{
for (std::size_t e = 0; e < n_exp; e++)
{
// calculate error in spread of flow $gamma$
auto gamma = xt::view(alpha, m, e)
* (xt::view(mean_obs, m, e, xt::all(), 0)
/ xt::view(mean_prd, m, e, xt::all(), 0));
// compute KGEPRIME
xt::view(KGEPRIME, xt::all(), m, e) = 1 - xt::sqrt(
xt::square(xt::view(r_pearson, m, e) - 1)
+ xt::square(gamma - 1)
+ xt::square(xt::view(bias, m, e) - 1)
);
}
}
return KGEPRIME;
}
}
}
}
#endif //EVALHYD_DETERMINIST_METRICS_HPP
...@@ -12,67 +12,6 @@ namespace evalhyd ...@@ -12,67 +12,6 @@ namespace evalhyd
{ {
namespace utils namespace utils
{ {
/// Procedure to determine based on a list of metrics which elements
/// and which metrics (and their associated elements) require to be
/// pre-computed for memoisation purposes.
///
/// \param [in] metrics:
/// Vector of strings for the metric(s) to be computed.
/// \param [in] elements:
/// Map between metrics and their required computation elements.
/// \param [in] dependencies:
/// Map between metrics and their dependencies.
/// \param [out] required_elements:
/// Set of elements identified as required to be pre-computed.
/// \param [out] required_dependencies:
/// Set of metrics identified as required to be pre-computed.
inline void find_requirements (
const std::vector<std::string>& metrics,
std::unordered_map<std::string, std::vector<std::string>>& elements,
std::unordered_map<std::string, std::vector<std::string>>& dependencies,
std::vector<std::string>& required_elements,
std::vector<std::string>& required_dependencies
)
{
std::unordered_set<std::string> found_elements;
std::unordered_set<std::string> found_dependencies;
for (const auto& metric : metrics)
{
// add elements to pre-computation set
for (const auto& element : elements[metric])
{
if (found_elements.find(element) == found_elements.end())
{
found_elements.insert(element);
required_elements.push_back(element);
}
}
// add metric dependencies to pre-computation set
if (dependencies.find(metric) != dependencies.end())
{
for (const auto& dependency : dependencies[metric])
{
if (found_dependencies.find(dependency) == found_dependencies.end())
{
found_dependencies.insert(dependency);
required_dependencies.push_back(dependency);
}
// add dependency elements to pre-computation set
for (const auto& element : elements[dependency])
{
if (found_elements.find(element) == found_elements.end())
{
found_elements.insert(element);
required_elements.push_back(element);
}
}
}
}
}
}
/// Procedure to check that all elements in the list of metrics are /// Procedure to check that all elements in the list of metrics are
/// valid metrics. /// valid metrics.
/// ///
......
...@@ -340,67 +340,6 @@ namespace evalhyd ...@@ -340,67 +340,6 @@ namespace evalhyd
// instantiate determinist evaluator // instantiate determinist evaluator
determinist::Evaluator<D2, B2> evaluator(obs, prd, msk, exp); determinist::Evaluator<D2, B2> evaluator(obs, prd, msk, exp);
// declare maps for memoisation purposes
std::unordered_map<std::string, std::vector<std::string>> elt;
std::unordered_map<std::string, std::vector<std::string>> dep;
// register potentially recurring computation elt across metrics
elt["RMSE"] = {"quad_err"};
elt["NSE"] = {"mean_obs", "quad_obs", "quad_err"};
elt["KGE"] = {"mean_obs", "mean_prd", "quad_obs", "quad_prd",
"r_pearson", "alpha", "bias"};
elt["KGEPRIME"] = {"mean_obs", "mean_prd", "quad_obs", "quad_prd",
"r_pearson", "alpha", "bias"};
// TODO: register nested metrics (i.e. metric dependent on another metric)
// dep[...] = {...};
// determine required elt/dep to be pre-computed
std::vector<std::string> req_elt;
std::vector<std::string> req_dep;
utils::find_requirements(metrics, elt, dep, req_elt, req_dep);
// pre-compute required elt
for ( const auto& element : req_elt )
{
if ( element == "mean_obs" )
{
evaluator.calc_mean_obs();
}
else if ( element == "mean_prd" )
{
evaluator.calc_mean_prd();
}
else if ( element == "quad_err" )
{
evaluator.calc_quad_err();
}
else if ( element == "quad_obs" )
{
evaluator.calc_quad_obs();
}
else if ( element == "quad_prd" )
{
evaluator.calc_quad_prd();
}
else if ( element == "r_pearson" )
{
evaluator.calc_r_pearson();
}
else if ( element == "alpha" )
{
evaluator.calc_alpha();
}
else if ( element == "bias" )
{
evaluator.calc_bias();
}
}
// TODO: pre-compute required dep
// for ( const auto& dependency : req_dep ) {...}
// retrieve or compute requested metrics // retrieve or compute requested metrics
std::vector<xt::xarray<double>> r; std::vector<xt::xarray<double>> r;
...@@ -410,39 +349,27 @@ namespace evalhyd ...@@ -410,39 +349,27 @@ namespace evalhyd
{ {
if ( metric == "RMSE" ) if ( metric == "RMSE" )
{ {
if (std::find(req_dep.begin(), req_dep.end(), metric) r.emplace_back(
== req_dep.end()) uncertainty::summarise(evaluator.get_RMSE(), summary)
{ );
evaluator.calc_RMSE();
}
r.emplace_back(uncertainty::summarise(evaluator.RMSE, summary));
} }
else if ( metric == "NSE" ) else if ( metric == "NSE" )
{ {
if (std::find(req_dep.begin(), req_dep.end(), metric) r.emplace_back(
== req_dep.end()) uncertainty::summarise(evaluator.get_NSE(), summary)
{ );
evaluator.calc_NSE();
}
r.emplace_back(uncertainty::summarise(evaluator.NSE, summary));
} }
else if ( metric == "KGE" ) else if ( metric == "KGE" )
{ {
if (std::find(req_dep.begin(), req_dep.end(), metric) r.emplace_back(
== req_dep.end()) uncertainty::summarise(evaluator.get_KGE(), summary)
{ );
evaluator.calc_KGE();
}
r.emplace_back(uncertainty::summarise(evaluator.KGE, summary));
} }
else if ( metric == "KGEPRIME" ) else if ( metric == "KGEPRIME" )
{ {
if (std::find(req_dep.begin(), req_dep.end(), metric) r.emplace_back(
== req_dep.end()) uncertainty::summarise(evaluator.get_KGEPRIME(), summary)
{ );
evaluator.calc_KGEPRIME();
}
r.emplace_back(uncertainty::summarise(evaluator.KGEPRIME, summary));
} }
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment