diff --git a/doc/source/references/release_notes.rst b/doc/source/references/release_notes.rst index c35ebcaa..c17a1043 100644 --- a/doc/source/references/release_notes.rst +++ b/doc/source/references/release_notes.rst @@ -6,6 +6,12 @@ Release history [maint] Made Frequency part of SliceMode union. [fix] slice_mode seasonal samplings was giving wrong results for quite a few indices. This has been fixed and the performances should also be improved by the fix. However, now seasonal slice_mode does not allow to use xclim missing values mechanisms. +[fix] user_index ExtremeMode config was not properly parsed when a string was used. +[fix] user_index Anomaly operator was not properly using the `ref_time_range` to setup a reference period as it should. +[fix] user_index Sum and Mean operators were broken due to a previous refactoring and a lack of unit tests, it is now fixed and tested. +[maint] Changed how `rechunker` dependency is pinned to add flexibility. We want a version above '0.3' but not the '0.4'. +[maint] For the newly generate API, on `custom_index` function, the parameter `user_index` is now mandatory. + 5.2.0 ----- diff --git a/icclim/main.py b/icclim/main.py index 4c74b9a8..22128df0 100644 --- a/icclim/main.py +++ b/icclim/main.py @@ -107,9 +107,6 @@ def indice(*args, **kwargs): return index(*args, **kwargs) -# TODO extract the custom index doc in a different doc than icclim.index - - def index( in_files: str | list[str] | Dataset | DataArray, index_name: str | None = None, # optional when computing user_indices @@ -260,12 +257,6 @@ def index( chunk_it=chunk_it, ) if user_index is not None: - if (rtr := user_index.get("ref_time_range", None)) is not None: - # setup anomaly todo: put that elsewhere - rtr = [x.strftime("%Y-%m-%d") for x in rtr] - config._cf_variables[0].reference_da = ds[var_name].sel( - time=slice(rtr[0], rtr[1]) - ) result_ds = _compute_user_index_dataset(config=config, user_index=user_index) else: result_ds = _compute_ecad_index_dataset( diff --git a/icclim/models/constants.py b/icclim/models/constants.py index 8c8b1104..a8808eca 100644 --- a/icclim/models/constants.py +++ b/icclim/models/constants.py @@ -27,6 +27,13 @@ MODIFIABLE_THRESHOLD = "MODIFIABLE_THRESHOLD" # fields: threshold MODIFIABLE_QUANTILE_WINDOW = "MODIFIABLE_QUANTILE_WINDOW" # fields: window_width - # Map of months index to their short name, used to get a pandas frequency anchor MONTHS_MAP = {1:"JAN", 2:"FEB", 3:"MAR", 4:"APR", 5:"MAY", 6:"JUN", 7:"JUL", 8:"AUG", 9:"SEP", 10:"OCT", 11:"NOV", 12:"DEC" } + +# Season defined by their month numbers +AMJJAS_MONTHS = [*range(4, 9)] +ONDJFM_MONTHS = [10, 11, 12, 1, 2, 3] +DJF_MONTHS = [12, 1, 2] +MAM_MONTHS = [*range(3, 6)] +JJA_MONTHS = [*range(6, 9)] +SON_MONTHS = [*range(9, 12)] diff --git a/icclim/models/frequency.py b/icclim/models/frequency.py index 62d85f9e..6be3331d 100644 --- a/icclim/models/frequency.py +++ b/icclim/models/frequency.py @@ -16,19 +16,15 @@ from xarray.core.dataarray import DataArray from icclim.icclim_exceptions import InvalidIcclimArgumentError -from icclim.models.constants import MONTHS_MAP - -AMJJAS_MONTHS = [*range(4, 9)] -ONDJFM_MONTHS = [10, 11, 12, 1, 2, 3] -DJF_MONTHS = [12, 1, 2] -MAM_MONTHS = [*range(3, 6)] -JJA_MONTHS = [*range(6, 9)] -SON_MONTHS = [*range(9, 12)] - - -def get_season_sampling_freq(month_list: list[int]) -> str: - # Must be used with month_filter to properly create a season - return f"{len(month_list)}MS" +from icclim.models.constants import ( + AMJJAS_MONTHS, + DJF_MONTHS, + JJA_MONTHS, + MAM_MONTHS, + MONTHS_MAP, + ONDJFM_MONTHS, + SON_MONTHS, +) def get_month_filter(month_list: list[int]) -> Callable: diff --git a/icclim/models/user_index_config.py b/icclim/models/user_index_config.py index fa8fc8c9..97961e13 100644 --- a/icclim/models/user_index_config.py +++ b/icclim/models/user_index_config.py @@ -157,6 +157,10 @@ def __init__( ) self.save_percentile = save_percentile self.ref_time_range = ref_time_range + if (rtr := ref_time_range) is not None: + rtr = [x.strftime("%Y-%m-%d") for x in rtr] + for cf_var in cf_vars: + cf_var.reference_da = cf_var.study_da.sel(time=slice(rtr[0], rtr[1])) def get_nb_event_conf( diff --git a/icclim/tests/test_frequency.py b/icclim/tests/test_frequency.py index b023e43a..d1458335 100644 --- a/icclim/tests/test_frequency.py +++ b/icclim/tests/test_frequency.py @@ -64,13 +64,6 @@ def test_winter(self): assert freq.accepted_values == [] assert freq.post_processing is not None - # def test_between_dates(self): - # freq = Frequency.lookup(["dates", ["15-06", "28 aout"] ]) - # assert freq == Frequency.CUSTOM - # assert freq.panda_freq == "75D" - # assert freq.accepted_values == [] - # assert freq.post_processing is not None - class Test_filter_months: def test_simple(self): @@ -113,14 +106,3 @@ def test_winter(self): time_bds_res[1].data[1] == pd.to_datetime("2043-02") - pd.tseries.offsets.Day() ) - - # def test_season_date_to_date(self): - # # WHEN - # da_res, time_bds_res = get_seasonal_time_updater(1, 4)(stub_tas()) - # # THEN - # np.testing.assert_array_equal(1, da_res) - # assert time_bds_res[0].data[0] == pd.to_datetime("2042-01") - # assert ( - # time_bds_res[0].data[1] - # == pd.to_datetime("2042-05") - pd.tseries.offsets.Day() - # )