From fb5f2f8f6009f260ac2826da95d8bcf8668d7549 Mon Sep 17 00:00:00 2001
From: Thibault Hallouin <thibault.hallouin@inrae.fr>
Date: Mon, 30 Jan 2023 10:59:51 +0100
Subject: [PATCH] add "series" dimension to m_cdt to be consistent with t_msk

related to e453205d5741f6f059b8dc04a4304ac51a0f089d
---
 include/evalhyd/evald.hpp  | 25 ++++++++++++++++++-------
 include/evalhyd/evalp.hpp  |  3 +--
 tests/test_determinist.cpp | 30 +++++++++++++++++++++---------
 3 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/include/evalhyd/evald.hpp b/include/evalhyd/evald.hpp
index a9f250b..5fb72f9 100644
--- a/include/evalhyd/evald.hpp
+++ b/include/evalhyd/evald.hpp
@@ -84,15 +84,14 @@ namespace evalhyd
     ///
     ///       .. seealso:: :doc:`../../functionalities/temporal-masking`
     ///
-    ///    m_cdt: ``xt::xtensor<std::array<char, 32>, 1>``, optional
+    ///    m_cdt: ``xt::xtensor<std::array<char, 32>, 2>``, optional
     ///       Masking conditions to use to generate temporal subsets. Each
     ///       condition consists in a string and can be specified on observed
     ///       streamflow values/statistics (mean, median, quantile), or on time
     ///       indices. If provided in combination with *t_msk*, the latter takes
     ///       precedence. If not provided and neither is *t_msk*, no subset is
-    ///       performed. If provided, there must be as many conditions as there
-    ///       are time series of observations.
-    ///       shape: (subsets,)
+    ///       performed.
+    ///       shape: (series, subsets)
     ///
     ///       .. seealso:: :doc:`../../functionalities/conditional-masking`
     ///
@@ -171,7 +170,7 @@ namespace evalhyd
             xtl::xoptional<double, bool> epsilon =
                     xtl::missing<double>(),
             const xt::xexpression<XB3>& t_msk = XB3({}),
-            const xt::xtensor<std::array<char, 32>, 1>& m_cdt = {},
+            const xt::xtensor<std::array<char, 32>, 2>& m_cdt = {},
             xtl::xoptional<const std::unordered_map<std::string, int>, bool> bootstrap =
                     xtl::missing<const std::unordered_map<std::string, int>>(),
             const std::vector<std::string>& dts = {},
@@ -251,6 +250,7 @@ namespace evalhyd
                     "observations contain more than one time series"
             );
         }
+
         if (t_msk_.size() > 0)
         {
             if (q_prd_.shape(0) != t_msk_.shape(0))
@@ -262,6 +262,17 @@ namespace evalhyd
             }
         }
 
+        if (m_cdt.size() > 0)
+        {
+            if (q_prd_.shape(0) != m_cdt.shape(0))
+            {
+                throw std::runtime_error(
+                        "predictions and masking conditions feature different "
+                        "numbers of series"
+                );
+            }
+        }
+
         // retrieve dimensions
         std::size_t n_tim = q_prd_.shape(1);
 
@@ -271,7 +282,7 @@ namespace evalhyd
             if ((t_msk_.size() < 1) && (m_cdt.size() > 0))
             {
                 std::size_t n_srs = q_prd_.shape(0);
-                std::size_t n_msk = m_cdt.shape(0);
+                std::size_t n_msk = m_cdt.shape(1);
 
                 XB3 c_msk = xt::zeros<bool>({n_srs, n_msk, n_tim});
 
@@ -281,7 +292,7 @@ namespace evalhyd
                     {
                         xt::view(c_msk, s, m) =
                                 masks::generate_mask_from_conditions(
-                                        xt::view(m_cdt, m),
+                                        xt::view(m_cdt, s, m),
                                         xt::view(q_obs_, 0),
                                         xt::view(q_prd_, s, xt::newaxis())
                                 );
diff --git a/include/evalhyd/evalp.hpp b/include/evalhyd/evalp.hpp
index 658de7f..4c49e42 100644
--- a/include/evalhyd/evalp.hpp
+++ b/include/evalhyd/evalp.hpp
@@ -95,8 +95,7 @@ namespace evalhyd
     ///       quantile), or on time indices. If provided in combination with
     ///       *t_msk*, the latter takes precedence. If not provided and neither
     ///       is *t_msk*, no subset is performed and only one set of metrics is
-    ///       returned corresponding to the whole time series. If provided, as
-    ///       many sets of metrics are returned as they are conditions provided.
+    ///       returned corresponding to the whole time series.
     ///       shape: (sites, subsets)
     ///
     ///       .. seealso:: :doc:`../../functionalities/conditional-masking`
diff --git a/tests/test_determinist.cpp b/tests/test_determinist.cpp
index be28204..560c713 100644
--- a/tests/test_determinist.cpp
+++ b/tests/test_determinist.cpp
@@ -191,9 +191,13 @@ TEST(DeterministTests, TestMaskingConditions)
     // conditions on streamflow values _________________________________________
 
     // compute scores using masking conditions on streamflow to subset whole record
-    xt::xtensor<std::array<char, 32>, 1> q_conditions = {
-            std::array<char, 32> {"q_obs{<2000,>3000}"}
-    };
+    xt::xtensor<std::array<char, 32>, 2> q_conditions = {{
+            {{std::array<char, 32>{"q_obs{<2000,>3000}"}}},
+            {{std::array<char, 32>{"q_obs{<2000,>3000}"}}},
+            {{std::array<char, 32>{"q_obs{<2000,>3000}"}}},
+            {{std::array<char, 32>{"q_obs{<2000,>3000}"}}},
+            {{std::array<char, 32>{"q_obs{<2000,>3000}"}}}
+    }};
 
     std::vector<xt::xarray<double>> metrics_q_conditioned =
             evalhyd::evald(
@@ -222,9 +226,13 @@ TEST(DeterministTests, TestMaskingConditions)
     // conditions on streamflow statistics _____________________________________
 
     // compute scores using masking conditions on streamflow to subset whole record
-    xt::xtensor<std::array<char, 32>, 1> q_conditions_ ={
-            std::array<char, 32> {"q_obs{>=mean}"}
-    };
+    xt::xtensor<std::array<char, 32>, 2> q_conditions_ = {{
+            {{std::array<char, 32>{"q_obs{>=mean}"}}},
+            {{std::array<char, 32>{"q_obs{>=mean}"}}},
+            {{std::array<char, 32>{"q_obs{>=mean}"}}},
+            {{std::array<char, 32>{"q_obs{>=mean}"}}},
+            {{std::array<char, 32>{"q_obs{>=mean}"}}}
+    }};
 
     double mean = xt::mean(observed, {1})();
 
@@ -255,9 +263,13 @@ TEST(DeterministTests, TestMaskingConditions)
     // conditions on temporal indices __________________________________________
 
     // compute scores using masking conditions on time indices to subset whole record
-    xt::xtensor<std::array<char, 32>, 1> t_conditions = {
-            std::array<char, 32> {"t{0,1,2,3,4,5:97,97,98,99}"}
-    };
+    xt::xtensor<std::array<char, 32>, 2> t_conditions = {{
+            {{std::array<char, 32>{"t{0,1,2,3,4,5:97,97,98,99}"}}},
+            {{std::array<char, 32>{"t{0,1,2,3,4,5:97,97,98,99}"}}},
+            {{std::array<char, 32>{"t{0,1,2,3,4,5:97,97,98,99}"}}},
+            {{std::array<char, 32>{"t{0,1,2,3,4,5:97,97,98,99}"}}},
+            {{std::array<char, 32>{"t{0,1,2,3,4,5:97,97,98,99}"}}}
+    }};
 
     std::vector<xt::xarray<double>> metrics_t_conditioned =
             evalhyd::evald(
-- 
GitLab