Repository: Ouranosinc/xclim

Issue:
Some indices are defined with (tasmin, tasmax) while others use (tasmax, tasmin)
* xclim version: master

### Description
<!--Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.-->

I think we should stick to one ordering. It creates problems when writing cf compliance checks and will potentially trip users. 


Discussion:

Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 85dd5f6d..1df4f827 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -14,9 +14,9 @@ History
 * Renamed `areacella` to `areacello` in sea ice tests.
 * Sea ice extent and area outputs now have units of m2 to comply with CF-Convention.
 * Split `checks.py` into `cfchecks.py`, `datachecks.py` and `missing.py`. This change will only affect users creating custom indices using utilities previously located in `checks.py`.
+* Changed signature of `daily_freeze_thaw_cycles`, `daily_temperature_range`, `daily_temperature_range_variability` and `extreme_temperature_range` to take (tasmin, tasmax) instead of (tasmax, tasmin) and match signature of other similar multivariate indices.
 * Added `FromContext` subclass of `MissingBase` to have a uniform API for missing value operations.
 
-
 0.17.0 (2020-05-15)
 -------------------
 * Added support for operations on dimensionless variables (`units = '1'`).
diff --git a/xclim/indices/_multivariate.py b/xclim/indices/_multivariate.py
index 82516188..2a6cda42 100644
--- a/xclim/indices/_multivariate.py
+++ b/xclim/indices/_multivariate.py
@@ -163,8 +163,8 @@ def cold_and_dry_days(
     thresh_tasmin="[temperature]",
 )
 def daily_freezethaw_cycles(
-    tasmax: xarray.DataArray,
     tasmin: xarray.DataArray,
+    tasmax: xarray.DataArray,
     thresh_tasmax: str = "UNSET 0 degC",
     thresh_tasmin: str = "UNSET 0 degC",
     freq: str = "YS",
@@ -175,10 +175,10 @@ def daily_freezethaw_cycles(
 
     Parameters
     ----------
-    tasmax : xarray.DataArray
-      Maximum daily temperature [℃] or [K]
     tasmin : xarray.DataArray
       Minimum daily temperature values [℃] or [K]
+    tasmax : xarray.DataArray
+      Maximum daily temperature [℃] or [K
     thresh_tasmax : str
       The temperature threshold needed to trigger a thaw event [℃] or [K]. Default : '0 degC'
     thresh_tasmin : str
@@ -219,17 +219,19 @@ def daily_freezethaw_cycles(
 
 
 @declare_units("K", tasmax="[temperature]", tasmin="[temperature]")
-def daily_temperature_range(tasmax, tasmin, freq: str = "YS") -> xarray.DataArray:
+def daily_temperature_range(
+    tasmin: xarray.DataArray, tasmax: xarray.DataArray, freq: str = "YS"
+) -> xarray.DataArray:
     r"""Mean of daily temperature range.
 
     The mean difference between the daily maximum temperature and the daily minimum temperature.
 
     Parameters
     ----------
-    tasmax : xarray.DataArray
-      Maximum daily temperature values [℃] or [K]
     tasmin : xarray.DataArray
       Minimum daily temperature values [℃] or [K]
+    tasmax : xarray.DataArray
+      Maximum daily temperature values [℃] or [K]
     freq : str
       Resampling frequency; Defaults to "YS".
 
@@ -256,7 +258,7 @@ def daily_temperature_range(tasmax, tasmin, freq: str = "YS") -> xarray.DataArra
 
 @declare_units("K", tasmax="[temperature]", tasmin="[temperature]")
 def daily_temperature_range_variability(
-    tasmax: xarray.DataArray, tasmin: xarray.DataArray, freq: str = "YS"
+    tasmin: xarray.DataArray, tasmax: xarray.DataArray, freq: str = "YS"
 ) -> xarray.DataArray:
     r"""Mean absolute day-to-day variation in daily temperature range.
 
@@ -264,10 +266,10 @@ def daily_temperature_range_variability(
 
     Parameters
     ----------
-    tasmax : xarray.DataArray
-      Maximum daily temperature values [℃] or [K]
     tasmin : xarray.DataArray
       Minimum daily temperature values [℃] or [K]
+    tasmax : xarray.DataArray
+      Maximum daily temperature values [℃] or [K]
     freq : str
       Resampling frequency; Defaults to "YS".
 
@@ -295,7 +297,7 @@ def daily_temperature_range_variability(
 
 @declare_units("K", tasmax="[temperature]", tasmin="[temperature]")
 def extreme_temperature_range(
-    tasmax: xarray.DataArray, tasmin: xarray.DataArray, freq: str = "YS"
+    tasmin: xarray.DataArray, tasmax: xarray.DataArray, freq: str = "YS"
 ) -> xarray.DataArray:
     r"""Extreme intra-period temperature range.
 
@@ -303,10 +305,10 @@ def extreme_temperature_range(
 
     Parameters
     ----------
-    tasmax : xarray.DataArray
-      Maximum daily temperature values [℃] or [K]
     tasmin : xarray.DataArray
       Minimum daily temperature values [℃] or [K]
+    tasmax : xarray.DataArray
+      Maximum daily temperature values [℃] or [K]
     freq : Optional[str[
       Resampling frequency; Defaults to "YS".
 


Test patch:
diff --git a/tests/test_indices.py b/tests/test_indices.py
index 4b2387b6..12a6ddb6 100644
--- a/tests/test_indices.py
+++ b/tests/test_indices.py
@@ -208,7 +208,7 @@ class TestDailyFreezeThawCycles:
 
         mn = tasmin_series(mn + K2C)
         mx = tasmax_series(mx + K2C)
-        out = xci.daily_freezethaw_cycles(mx, mn, freq="M")
+        out = xci.daily_freezethaw_cycles(mn, mx, freq="M")
         np.testing.assert_array_equal(out[:2], [5, 1])
         np.testing.assert_array_equal(out[2:], 0)
 
@@ -227,7 +227,7 @@ class TestDailyFreezeThawCycles:
         mn = tasmin_series(mn + K2C)
         mx = tasmax_series(mx + K2C)
         out = xci.daily_freezethaw_cycles(
-            mx, mn, thresh_tasmax="0 degC", thresh_tasmin="0 degC", freq="M"
+            mn, mx, thresh_tasmax="0 degC", thresh_tasmin="0 degC", freq="M"
         )
         np.testing.assert_array_equal(out[:2], [5, 1])
         np.testing.assert_array_equal(out[2:], 0)
@@ -866,75 +866,75 @@ class TestTxMax:
 
 class TestTgMaxTgMinIndices:
     @staticmethod
-    def random_tmax_tmin_setup(length, tasmax_series, tasmin_series):
+    def random_tmin_tmax_setup(length, tasmax_series, tasmin_series):
         max_values = np.random.uniform(-20, 40, length)
         min_values = []
         for i in range(length):
             min_values.append(np.random.uniform(-40, max_values[i]))
         tasmax = tasmax_series(np.add(max_values, K2C))
         tasmin = tasmin_series(np.add(min_values, K2C))
-        return tasmax, tasmin
+        return tasmin, tasmax
 
     @staticmethod
-    def static_tmax_tmin_setup(tasmax_series, tasmin_series):
+    def static_tmin_tmax_setup(tasmin_series, tasmax_series):
         max_values = np.add([22, 10, 35.2, 25.1, 18.9, 12, 16], K2C)
         min_values = np.add([17, 3.5, 22.7, 16, 12.4, 7, 12], K2C)
         tasmax = tasmax_series(max_values)
         tasmin = tasmin_series(min_values)
-        return tasmax, tasmin
+        return tasmin, tasmax
 
     # def test_random_daily_temperature_range(self, tasmax_series, tasmin_series):
     #     days = 365
-    #     tasmax, tasmin = self.random_tmax_tmin_setup(days, tasmax_series, tasmin_series)
-    #     dtr = xci.daily_temperature_range(tasmax, tasmin, freq="YS")
+    #     tasmin, tasmax = self.random_tmin_tmax_setup(days, tasmin_series, tasmax_series)
+    #     dtr = xci.daily_temperature_range(tasmin, tasmax, freq="YS")
     #
     #     np.testing.assert_array_less(-dtr, [0, 0])
     #     np.testing.assert_allclose([dtr.mean()], [20], atol=10)
 
-    def test_static_daily_temperature_range(self, tasmax_series, tasmin_series):
-        tasmax, tasmin = self.static_tmax_tmin_setup(tasmax_series, tasmin_series)
-        dtr = xci.daily_temperature_range(tasmax, tasmin, freq="YS")
+    def test_static_daily_temperature_range(self, tasmin_series, tasmax_series):
+        tasmin, tasmax = self.static_tmin_tmax_setup(tasmin_series, tasmax_series)
+        dtr = xci.daily_temperature_range(tasmin, tasmax, freq="YS")
         assert dtr.units == "K"
         output = np.mean(tasmax - tasmin)
 
         np.testing.assert_equal(dtr, output)
 
-    # def test_random_variable_daily_temperature_range(self, tasmax_series, tasmin_series):
+    # def test_random_variable_daily_temperature_range(self, tasmin_series, tasmax_series):
     #     days = 1095
-    #     tasmax, tasmin = self.random_tmax_tmin_setup(days, tasmax_series, tasmin_series)
-    #     vdtr = xci.daily_temperature_range_variability(tasmax, tasmin, freq="YS")
+    #     tasmin, tasmax = self.random_tmin_tmax_setup(days, tasmin_series, tasmax_series)
+    #     vdtr = xci.daily_temperature_range_variability(tasmin, tasmax, freq="YS")
     #
     #     np.testing.assert_allclose(vdtr.mean(), 20, atol=10)
     #     np.testing.assert_array_less(-vdtr, [0, 0, 0, 0])
 
     def test_static_variable_daily_temperature_range(
-        self, tasmax_series, tasmin_series
+        self, tasmin_series, tasmax_series
     ):
-        tasmax, tasmin = self.static_tmax_tmin_setup(tasmax_series, tasmin_series)
-        dtr = xci.daily_temperature_range_variability(tasmax, tasmin, freq="YS")
+        tasmin, tasmax = self.static_tmin_tmax_setup(tasmin_series, tasmax_series)
+        dtr = xci.daily_temperature_range_variability(tasmin, tasmax, freq="YS")
 
         np.testing.assert_almost_equal(dtr, 2.667, decimal=3)
 
-    def test_static_extreme_temperature_range(self, tasmax_series, tasmin_series):
-        tasmax, tasmin = self.static_tmax_tmin_setup(tasmax_series, tasmin_series)
-        etr = xci.extreme_temperature_range(tasmax, tasmin)
+    def test_static_extreme_temperature_range(self, tasmin_series, tasmax_series):
+        tasmin, tasmax = self.static_tmin_tmax_setup(tasmin_series, tasmax_series)
+        etr = xci.extreme_temperature_range(tasmin, tasmax)
 
         np.testing.assert_array_almost_equal(etr, 31.7)
 
-    def test_uniform_freeze_thaw_cycles(self, tasmax_series, tasmin_series):
+    def test_uniform_freeze_thaw_cycles(self, tasmin_series, tasmax_series):
         temp_values = np.zeros(365)
         tasmax, tasmin = (
             tasmax_series(temp_values + 5 + K2C),
             tasmin_series(temp_values - 5 + K2C),
         )
-        ft = xci.daily_freezethaw_cycles(tasmax, tasmin, freq="YS")
+        ft = xci.daily_freezethaw_cycles(tasmin, tasmax, freq="YS")
 
         np.testing.assert_array_equal([np.sum(ft)], [365])
 
-    def test_static_freeze_thaw_cycles(self, tasmax_series, tasmin_series):
-        tasmax, tasmin = self.static_tmax_tmin_setup(tasmax_series, tasmin_series)
+    def test_static_freeze_thaw_cycles(self, tasmin_series, tasmax_series):
+        tasmin, tasmax = self.static_tmin_tmax_setup(tasmin_series, tasmax_series)
         tasmin -= 15
-        ft = xci.daily_freezethaw_cycles(tasmax, tasmin, freq="YS")
+        ft = xci.daily_freezethaw_cycles(tasmin, tasmax, freq="YS")
 
         np.testing.assert_array_equal([np.sum(ft)], [4])
 
@@ -943,8 +943,8 @@ class TestTgMaxTgMinIndices:
     #     runs = np.array([])
     #     for i in range(10):
     #         temp_values = np.random.uniform(-30, 30, 365)
-    #         tasmax, tasmin = self.tmax_tmin_time_series(temp_values + K2C)
-    #         ft = xci.daily_freezethaw_cycles(tasmax, tasmin, freq="YS")
+    #         tasmin, tasmax = self.tmin_tmax_time_series(temp_values + K2C)
+    #         ft = xci.daily_freezethaw_cycles(tasmin, tasmax, freq="YS")
     #         runs = np.append(runs, ft)
     #
     #     np.testing.assert_allclose(np.mean(runs), 120, atol=20)
@@ -1264,7 +1264,7 @@ class TestIsothermality:
         tasmax = tasmax_series(values.squeeze(), start="2001-01-01").sel(
             time=slice("2001", "2002")
         )
-        return tasmax, tasmin
+        return tasmin, tasmax
 
     @pytest.mark.parametrize(
         "freq,expected",
@@ -1275,7 +1275,7 @@ class TestIsothermality:
         ],
     )
     def test_simple(self, tasmax_series, tasmin_series, freq, expected):
-        tasmax, tasmin = self.get_data(tasmin_series, tasmax_series)
+        tasmin, tasmax = self.get_data(tasmin_series, tasmax_series)
 
         # weekly
         tmin = tasmin.resample(time=freq).mean(dim="time", keep_attrs=True)
diff --git a/tests/test_temperature.py b/tests/test_temperature.py
index 077fa2dc..77dfaac9 100644
--- a/tests/test_temperature.py
+++ b/tests/test_temperature.py
@@ -83,8 +83,8 @@ class TestDTR:
         # put a nan somewhere
         tasmin.values[32, 1, 0] = np.nan
         tasmin_C.values[32, 1, 0] = np.nan
-        dtr = atmos.daily_temperature_range(tasmax, tasmin, freq="MS")
-        dtrC = atmos.daily_temperature_range(tasmax_C, tasmin_C, freq="MS")
+        dtr = atmos.daily_temperature_range(tasmin, tasmax, freq="MS")
+        dtrC = atmos.daily_temperature_range(tasmin_C, tasmax_C, freq="MS")
         min1 = tasmin.values[:, 0, 0]
         max1 = tasmax.values[:, 0, 0]
 
@@ -119,8 +119,8 @@ class TestDTRVar:
         # put a nan somewhere
         tasmin.values[32, 1, 0] = np.nan
         tasmin_C.values[32, 1, 0] = np.nan
-        dtr = atmos.daily_temperature_range_variability(tasmax, tasmin, freq="MS")
-        dtrC = atmos.daily_temperature_range_variability(tasmax_C, tasmin_C, freq="MS")
+        dtr = atmos.daily_temperature_range_variability(tasmin, tasmax, freq="MS")
+        dtrC = atmos.daily_temperature_range_variability(tasmin_C, tasmax_C, freq="MS")
         min1 = tasmin.values[:, 0, 0]
         max1 = tasmax.values[:, 0, 0]
         assert dtr.attrs["units"] == "K"
@@ -157,8 +157,8 @@ class TestETR:
         tasmin.values[32, 1, 0] = np.nan
         tasmin_C.values[32, 1, 0] = np.nan
 
-        etr = atmos.extreme_temperature_range(tasmax, tasmin, freq="MS")
-        etrC = atmos.extreme_temperature_range(tasmax_C, tasmin_C, freq="MS")
+        etr = atmos.extreme_temperature_range(tasmin, tasmax, freq="MS")
+        etrC = atmos.extreme_temperature_range(tasmin_C, tasmax_C, freq="MS")
         min1 = tasmin.values[:, 0, 0]
         max1 = tasmax.values[:, 0, 0]
 
@@ -752,7 +752,7 @@ class TestDailyFreezeThaw:
         tasmin.values[180, 1, 0] = np.nan
 
         with pytest.warns(FutureWarning) as record:
-            frzthw = atmos.daily_freezethaw_cycles(tasmax, tasmin, freq="YS")
+            frzthw = atmos.daily_freezethaw_cycles(tasmin, tasmax, freq="YS")
 
         min1 = tasmin.values[:, 0, 0]
         max1 = tasmax.values[:, 0, 0]
@@ -782,8 +782,8 @@ class TestDailyFreezeThaw:
 
         with pytest.warns(None) as record:
             frzthw = atmos.daily_freezethaw_cycles(
-                tasmax,
                 tasmin,
+                tasmax,
                 thresh_tasmax="0 degC",
                 thresh_tasmin="0 degC",
                 freq="YS",