probabilist.hpp 5.32 KiB
#ifndef EVALHYD_PROBABILIST_HPP
#define EVALHYD_PROBABILIST_HPP
#include <utility>
#include <unordered_map>
#include <vector>
#include <xtensor/xtensor.hpp>
#include <xtensor/xview.hpp>
#include "utils.hpp"
#include "probabilist/evaluator.h"
namespace eh = evalhyd;
namespace evalhyd
    namespace probabilist
        /// Function allowing the evaluation of streamflow forecasts using a
        /// range of relevant metrics.
        ///
        /// \param [in] metrics:
        ///     Vector of strings for the metric(s) to be computed.
        /// \param [in] q_obs:
        ///     2D array of streamflow observations.
        ///     shape: (1, time)
        /// \param [in] q_frc:
        ///     2D array of streamflow forecasts.
        ///     shape: (members, time)
        /// \param [in] q_thr:
        ///     1D array of streamflow exceedance threshold(s).
        ///     shape: (thresholds,)
        /// \return
        ///     Vector of 2D array of metrics for each threshold.
        std::vector<xt::xtensor<double, 2>> evaluate(
                const std::vector<std::string>& metrics,
                const xt::xtensor<double, 2>& q_obs,
                const xt::xtensor<double, 2>& q_frc,
                const xt::xtensor<double, 1>& q_thr
            // check that the metrics to be computed are valid
            utils::check_metrics(
                    metrics,
                    {"BS", "BSS", "BS_CRD", "BS_LBD", "QS", "CRPS"}
            // instantiate probabilist evaluator
            eh::probabilist::Evaluator evaluator(q_obs, q_frc, q_thr);
            // 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 elements across metrics
            elt["BS"] = {"o_k", "y_k"};
            elt["BSS"] = {"o_k", "bar_o"};
            elt["BS_CRD"] = {"o_k", "bar_o", "y_k"};
            elt["BS_LBD"] = {"o_k", "y_k"};
            elt["QS"] = {"q_qnt"};
            // register nested metrics (i.e. metric dependent on another metric)
            dep["BSS"] = {"BS"};
            dep["QS"] = {"qs"};
            dep["CRPS"] = {"qs", "crps"};
            // determine required elt/dep to be pre-computed
            std::vector<std::string> req_elt;
            std::vector<std::string> req_dep;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
eh::utils::find_requirements(metrics, elt, dep, req_elt, req_dep); // pre-compute required elt for (const auto& element : req_elt) { if ( element == "o_k" ) evaluator.calc_o_k(); else if ( element == "bar_o" ) evaluator.calc_bar_o(); else if ( element == "y_k" ) evaluator.calc_y_k(); else if ( element == "q_qnt" ) evaluator.calc_q_qnt(); } // pre-compute required dep for (const auto& dependency : req_dep) { if ( dependency == "BS" ) evaluator.calc_BS(); else if ( dependency == "qs" ) evaluator.calc_qs(); else if ( dependency == "crps" ) evaluator.calc_crps(); } // retrieve or compute requested metrics std::vector<xt::xtensor<double, 2>> r; for (const auto& metric : metrics) { if ( metric == "BS" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end()) evaluator.calc_BS(); r.emplace_back(evaluator.BS); } else if ( metric == "BSS" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end()) evaluator.calc_BSS(); r.emplace_back(evaluator.BSS); } else if ( metric == "BS_CRD" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end()) evaluator.calc_BS_CRD(); r.emplace_back(evaluator.BS_CRD); } else if ( metric == "BS_LBD" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end()) evaluator.calc_BS_LBD(); r.emplace_back(evaluator.BS_LBD); } else if ( metric == "QS" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end()) evaluator.calc_QS(); r.emplace_back(evaluator.QS); } else if ( metric == "CRPS" ) { if (std::find(req_dep.begin(), req_dep.end(), metric) == req_dep.end())
141142143144145146147148149150151152
evaluator.calc_CRPS(); r.emplace_back(evaluator.CRPS); } } return r; } } } #endif //EVALHYD_PROBABILIST_HPP