diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ab913f99a660bfbd6cc26b07c37b595b9e7e98e..27df2280a43567e4bbbe2893bf6630b313f4fd81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ project( find_package(xtl 0.7.5 REQUIRED) message(STATUS "Found xtl: ${xtl_INCLUDE_DIRS}/xtl") -find_package(xtensor 0.24.4 REQUIRED) +find_package(xtensor 0.24.6 REQUIRED) message(STATUS "Found xtensor: ${xtensor_INCLUDE_DIRS}/xtensor") # ------------------------------------------------------------------------------ diff --git a/include/evalhyd/detail/determinist/efficiencies.hpp b/include/evalhyd/detail/determinist/efficiencies.hpp index af83745fa530c1e8f349348a6742c1ed7c4c1a3c..6ae18ff67ee925025ec18d90aa5252252def1757 100644 --- a/include/evalhyd/detail/determinist/efficiencies.hpp +++ b/include/evalhyd/detail/determinist/efficiencies.hpp @@ -9,6 +9,9 @@ #include <xtensor/xview.hpp> #include <xtensor/xoperation.hpp> +#include "../maths.hpp" + + namespace evalhyd { namespace determinist diff --git a/include/evalhyd/detail/maths.hpp b/include/evalhyd/detail/maths.hpp index f8b44d55fc1ee539d3c33c3c8e5f8e58dce874df..49786ad67145a847f5b5faaf5b94b5d94ac80630 100644 --- a/include/evalhyd/detail/maths.hpp +++ b/include/evalhyd/detail/maths.hpp @@ -17,8 +17,8 @@ namespace evalhyd { namespace maths { - // TODO: substitute with `xt::stddev` when fixed for `xt::rtensor` - // (see https://gitlab.irstea.fr/HYCAR-Hydro/evalhyd/evalhyd-r/-/issues/1) + // TODO: substitute with `xt::stddev` when performance fixed + // (see https://github.com/xtensor-stack/xtensor/pull/2656) // function to calculate standard deviation on last axis of n-dim expressions template <class A1, class A2> inline auto nanstd(A1&& arr, A2&& mean_arr) @@ -27,56 +27,6 @@ namespace evalhyd xt::nanmean(xt::square(xt::abs(arr - mean_arr)), -1) ); } - - // TODO: drop in favour of xt::quantile when xtensor issue fixed - // https://github.com/xtensor-stack/xtensor/issues/2651 - // function to calculate quantile on 1-dim expressions - inline double quantile(const xt::xtensor<double, 1>& t, double p) - { - std::size_t n = t.size(); - - // compute virtual index - auto virtual_idx = (double(n) - 1) * p; - - if (std::fmod(virtual_idx, 1) == 0) - // virtual index is an integer - { - std::size_t i = {static_cast<unsigned long long>(virtual_idx)}; - std::array<std::size_t, 1> kth = {i}; - auto values = xt::partition(t, kth); - return xt::mean(xt::view(values, xt::range(i, i + 1)))(); - } - else - // virtual index is not an integer - { - // determine indices before and after virtual index - std::size_t prv_idx = std::floor(virtual_idx); - std::size_t nxt_idx = prv_idx + 1; - - // deal with edge cases - if (virtual_idx > double(n) - 1) - { - prv_idx = n - 1; - nxt_idx = n - 1; - } - if (virtual_idx < 0) - { - prv_idx = 0; - nxt_idx = 0; - } - - std::array<std::size_t, 2> kth = {prv_idx, nxt_idx}; - auto values = xt::partition(t, kth); - auto vw = xt::view(values, xt::range(prv_idx, nxt_idx + 1)); - - // perform linear interpolation to determine quantile - auto gamma = virtual_idx - double(prv_idx); - auto prv = xt::amin(vw); - auto nxt = xt::amax(vw); - - return (prv + (nxt - prv) * gamma)(); - } - } } } diff --git a/include/evalhyd/detail/probabilist/intervals.hpp b/include/evalhyd/detail/probabilist/intervals.hpp index ceca4a2531c961f57f18bcbc884e6529c125c8d2..0a2f4c2a2e3df0fe2fbc802be8c0fdcd4d0af515 100644 --- a/include/evalhyd/detail/probabilist/intervals.hpp +++ b/include/evalhyd/detail/probabilist/intervals.hpp @@ -11,9 +11,6 @@ #include <xtensor/xview.hpp> #include <xtensor/xindex_view.hpp> #include <xtensor/xsort.hpp> -#include <xtensor/xio.hpp> - -#include "../maths.hpp" namespace evalhyd @@ -64,34 +61,16 @@ namespace evalhyd xt::col(quantiles, 1) = 0.5 + c_lvl / 200.; // compute predictive interval bounds from quantiles - - // TODO: replace with xt::quantile when xtensor issue fixed - // https://github.com/xtensor-stack/xtensor/issues/2651 - for (std::size_t s = 0; s < n_sit; s++) + for (std::size_t i = 0; i < n_itv; i++) { - for (std::size_t l = 0; l < n_ldt; l++) - { - for (std::size_t i = 0; i < n_itv; i++) - { - for (std::size_t t = 0; t < n_tim; t++) - { - // lower bound - xt::view(itv_bnds, s, l, i, 0, t) = - evalhyd::maths::quantile( - xt::view(q_prd, s, l, xt::all(), t), - quantiles(i, 0) - ); - // upper bound - xt::view(itv_bnds, s, l, i, 1, t) = - evalhyd::maths::quantile( - xt::view(q_prd, s, l, xt::all(), t), - quantiles(i, 1) - ); - } - } - } + auto q = xt::quantile(q_prd, xt::view(quantiles, i), 2); + + xt::view(itv_bnds, xt::all(), xt::all(), i, 0, xt::all()) = + xt::view(q, 0); + xt::view(itv_bnds, xt::all(), xt::all(), i, 1, xt::all()) = + xt::view(q, 1); } - + return itv_bnds; } @@ -217,8 +196,6 @@ namespace evalhyd xt::view(q_obs_masked, xt::all(), xt::all(), b_exp[e]); // compute "climatology" interval - - // TODO: replace with `xt::nanquantile` when available for (std::size_t s = 0; s < n_sit; s++) { for (std::size_t l = 0; l < n_ldt; l++) @@ -234,15 +211,16 @@ namespace evalhyd { // lower bound xt::view(clim_bnds, s, l, m, e, i, 0) = - evalhyd::maths::quantile( - obs_filtered, quantiles(i, 0) - ); - + xt::quantile( + obs_filtered, + {quantiles(i, 0)} + )(); // upper bound xt::view(clim_bnds, s, l, m, e, i, 1) = - evalhyd::maths::quantile( - obs_filtered, quantiles(i, 1) - ); + xt::quantile( + obs_filtered, + {quantiles(i, 1)} + )(); } else { diff --git a/include/evalhyd/detail/uncertainty.hpp b/include/evalhyd/detail/uncertainty.hpp index 36b459ea100830b62f75a74cfa82f00c3725d450..25b13af0957e7552f52fe648564f2abc67be0054 100644 --- a/include/evalhyd/detail/uncertainty.hpp +++ b/include/evalhyd/detail/uncertainty.hpp @@ -16,8 +16,8 @@ #include <xtensor/xtensor.hpp> #include <xtensor/xadapt.hpp> #include <xtensor/xrandom.hpp> +#include <xtensor/xsort.hpp> -#include "maths.hpp" typedef std::chrono::time_point< std::chrono::system_clock, std::chrono::minutes diff --git a/include/evalhyd/evald.hpp b/include/evalhyd/evald.hpp index 834583319a7852ecb503214fd2bcebfd4e07f226..f56db11eed76781139529369e982a5744a82e07c 100644 --- a/include/evalhyd/evald.hpp +++ b/include/evalhyd/evald.hpp @@ -15,7 +15,6 @@ #include "detail/utils.hpp" #include "detail/masks.hpp" -#include "detail/maths.hpp" #include "detail/uncertainty.hpp" #include "detail/determinist/evaluator.hpp" diff --git a/include/evalhyd/evalp.hpp b/include/evalhyd/evalp.hpp index fa5e7e752ac59d0fd1f58e156a54e291003c164e..5dfe36984077f92cff08fe908e7755721d5eab49 100644 --- a/include/evalhyd/evalp.hpp +++ b/include/evalhyd/evalp.hpp @@ -16,7 +16,6 @@ #include "detail/utils.hpp" #include "detail/masks.hpp" -#include "detail/maths.hpp" #include "detail/uncertainty.hpp" #include "detail/probabilist/evaluator.hpp"