Skip to content

Commit

Permalink
Change all freqs for newest syntax possible - fix were appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
aulemahal committed Nov 28, 2023
1 parent e6d3fc3 commit 0746d44
Show file tree
Hide file tree
Showing 31 changed files with 245 additions and 172 deletions.
2 changes: 1 addition & 1 deletion docs/notebooks/example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
"Almost all `xclim` indicators convert daily data to lower time frequencies, such as seasonal or annual values. This is done using `xarray.DataArray.resample` method. Resampling creates a grouped object over which you apply a reduction operation (e.g. mean, min, max). The list of available frequency is given in the link below, but the most often used are:\n",
"\n",
"- `YS`: annual starting in January\n",
"- `YS-JUL`: annual starting in July\n",
"- `AS-JUL`: annual starting in July\n",
"- `MS`: monthly\n",
"- `QS-DEC`: seasonal starting in December\n",
"\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@
"All `xclim` indicators convert daily data to lower time frequencies, such as monthly or annual values. This is done using `xarray.DataArray.resample` method. Resampling creates a grouped object over which you apply a reduction operation (e.g. mean, min, max). The list of available frequency is given in the link below, but the most often used are: \n",
"\n",
"- YS: annual starting in January\n",
"- YS-JUL: annual starting in July\n",
"- AS-JUL: annual starting in July\n",
"- MS: monthly\n",
"- QS-DEC: seasonal starting in December\n",
"- 7D: 7 day (weekly)\n",
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ dependencies = [
"lmoments3>=1.0.5",
"numba",
"numpy>=1.16",
"pandas>=0.23,<2.0; python_version == '3.8'",
"pandas>=0.23; python_version >= '3.9'",
"pandas>=1.0,<2.0; python_version == '3.8'",
"pandas>=1.0; python_version >= '3.9'",
"pint>=0.10",
"pyyaml",
"scikit-learn>=0.21.3",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_atmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ def test_wind_power_potential_from_3h_series():
from xclim.testing.helpers import test_timeseries

w = test_timeseries(
np.ones(96) * 15, variable="sfcWind", start="7/1/2000", units="m s-1", freq="3H"
np.ones(96) * 15, variable="sfcWind", start="7/1/2000", units="m s-1", freq="3h"
)
out = atmos.wind_power_potential(wind_speed=w)

Expand Down
31 changes: 17 additions & 14 deletions tests/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def da(index):
)


@pytest.mark.parametrize("freq", ["6480H", "302431T", "23144781S"])
@pytest.mark.parametrize("freq", ["6480h", "302431min", "23144781s"])
def test_time_bnds(freq, datetime_index, cftime_index):
da_datetime = da(datetime_index).resample(time=freq)
da_cftime = da(cftime_index).resample(time=freq)
Expand Down Expand Up @@ -146,7 +146,7 @@ def test_percentile_doy_invalid():
tas = xr.DataArray(
[0, 1],
dims=("time",),
coords={"time": pd.date_range("2000-01-01", periods=2, freq="H")},
coords={"time": pd.date_range("2000-01-01", periods=2, freq="h")},
)
with pytest.raises(ValueError):
percentile_doy(tas)
Expand All @@ -155,10 +155,10 @@ def test_percentile_doy_invalid():
@pytest.mark.parametrize(
"freqA,op,freqB,exp",
[
("D", ">", "H", True),
("D", ">", "h", True),
("2YS", "<=", "QS-DEC", False),
("4W", "==", "3W", False),
("24H", "==", "D", True),
("24h", "==", "D", True),
],
)
def test_compare_offsets(freqA, op, freqB, exp):
Expand Down Expand Up @@ -275,8 +275,8 @@ def test_get_calendar_errors(obj):
("standard", "noleap", True, "D"),
("noleap", "default", True, "D"),
("noleap", "all_leap", False, "D"),
("proleptic_gregorian", "noleap", False, "4H"),
("default", "noleap", True, "4H"),
("proleptic_gregorian", "noleap", False, "4h"),
("default", "noleap", True, "4h"),
],
)
def test_convert_calendar(source, target, target_as_str, freq):
Expand Down Expand Up @@ -311,7 +311,7 @@ def test_convert_calendar(source, target, target_as_str, freq):
[
("standard", "360_day", "D"),
("360_day", "default", "D"),
("proleptic_gregorian", "360_day", "4H"),
("proleptic_gregorian", "360_day", "4h"),
],
)
@pytest.mark.parametrize("align_on", ["date", "year"])
Expand Down Expand Up @@ -356,7 +356,7 @@ def test_convert_calendar_360_days_random():
dims=("time",),
coords={
"time": date_range(
"2004-01-01", "2004-12-31T23:59:59", freq="12H", calendar="default"
"2004-01-01", "2004-12-31T23:59:59", freq="12h", calendar="default"
)
},
)
Expand All @@ -365,7 +365,7 @@ def test_convert_calendar_360_days_random():
dims=("time",),
coords={
"time": date_range(
"2004-01-01", "2004-12-30T23:59:59", freq="12H", calendar="360_day"
"2004-01-01", "2004-12-30T23:59:59", freq="12h", calendar="360_day"
)
},
)
Expand Down Expand Up @@ -394,7 +394,7 @@ def test_convert_calendar_360_days_random():
"source,target,freq",
[
("standard", "noleap", "D"),
("noleap", "default", "4H"),
("noleap", "default", "4h"),
("noleap", "all_leap", "M"),
("360_day", "noleap", "D"),
("noleap", "360_day", "D"),
Expand All @@ -415,7 +415,7 @@ def test_convert_calendar_missing(source, target, freq):
np.linspace(0, 1, src.size), dims=("time",), coords={"time": src}
)
out = convert_calendar(da_src, target, missing=np.nan, align_on="date")
assert xr.infer_freq(out.time) == freq
assert fix_freq(xr.infer_freq(out.time), warn=False) == freq
if source == "360_day":
assert out.time[-1].dt.day == 31

Expand Down Expand Up @@ -624,7 +624,7 @@ def test_doy_to_days_since():
[
("4AS-JUL", 4, "A", True, "JUL"),
("M", 1, "M", False, None),
("YS", 1, "A", True, "JAN"),
("YS", 1, "Y", True, "JAN"),
("3A", 3, "A", False, "DEC"),
("D", 1, "D", True, None),
("3W", 21, "D", True, None),
Expand Down Expand Up @@ -710,11 +710,14 @@ def test_convert_doy():
"freq,exp,to,warn",
[
("Y", "YE-DEC", "new", "end-anchored"),
("YS", "YS-JAN", "new", "Pandas changed"),
("AS", "YS-JAN", "new", "Pandas changed"),
("T", "min", "new", "T should now be written min"),
("56S", "56s", "new", "S should now be written s"),
("MS", "MS", "new", None),
("AS-MAR", "YS-MAR", "old", None),
("Y", "A-DEC", "inter", None),
("AS", "AS-JAN", "inter", None),
("T", "min", "inter", "T should now be written min"),
("AS-MAR", "AS-MAR", "old", None),
("min", "T", "old", None),
("4Q-DEC", "4Q-DEC", "old", None),
],
Expand Down
26 changes: 13 additions & 13 deletions tests/test_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,25 +149,25 @@ def test_check_hourly(self, date_range, random):
}

n = 100
time = date_range("2000-01-01", freq="H", periods=n)
time = date_range("2000-01-01", freq="h", periods=n)
da = xr.DataArray(random.random(n), [("time", time)], attrs=tas_attrs)
datachecks.check_freq(da, "H")
datachecks.check_freq(da, "h")

time = date_range("2000-01-01", freq="3H", periods=n)
time = date_range("2000-01-01", freq="3h", periods=n)
da = xr.DataArray(random.random(n), [("time", time)], attrs=tas_attrs)
with pytest.raises(ValidationError):
datachecks.check_freq(da, "H")
datachecks.check_freq(da, "h")

with pytest.raises(ValidationError):
datachecks.check_freq(da, ["H", "D"])
datachecks.check_freq(da, ["h", "D"])

datachecks.check_freq(da, "H", strict=False)
datachecks.check_freq(da, ["H", "D"], strict=False)
datachecks.check_freq(da, "3H")
datachecks.check_freq(da, ["H", "3H"])
datachecks.check_freq(da, "h", strict=False)
datachecks.check_freq(da, ["h", "D"], strict=False)
datachecks.check_freq(da, "3h")
datachecks.check_freq(da, ["h", "3h"])

with pytest.raises(ValidationError, match="Unable to infer the frequency of"):
datachecks.check_freq(da.where(da.time.dt.dayofyear != 5, drop=True), "3H")
datachecks.check_freq(da.where(da.time.dt.dayofyear != 5, drop=True), "3h")

def test_common_time(self, tas_series, date_range, random):
tas_attrs = {
Expand All @@ -176,7 +176,7 @@ def test_common_time(self, tas_series, date_range, random):
}

n = 100
time = date_range("2000-01-01", freq="H", periods=n)
time = date_range("2000-01-01", freq="h", periods=n)
da = xr.DataArray(random.random(n), [("time", time)], attrs=tas_attrs)

# No freq
Expand All @@ -187,7 +187,7 @@ def test_common_time(self, tas_series, date_range, random):
datachecks.check_common_time([db, da])

# Not same freq
time = date_range("2000-01-01", freq="6H", periods=n)
time = date_range("2000-01-01", freq="6h", periods=n)
db = xr.DataArray(random.random(n), [("time", time)], attrs=tas_attrs)
with pytest.raises(ValidationError, match="Inputs have different frequencies"):
datachecks.check_common_time([db, da])
Expand All @@ -197,6 +197,6 @@ def test_common_time(self, tas_series, date_range, random):
db["time"] = db.time + pd.Timedelta(30, "min")
with pytest.raises(
ValidationError,
match=r"All inputs have the same frequency \(H\), but they are not anchored on the same minutes",
match=r"All inputs have the same frequency \(h\), but they are not anchored on the same minutes",
):
datachecks.check_common_time([db, da])
2 changes: 1 addition & 1 deletion tests/test_generic_indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_missing(self, ndq_series):
np.testing.assert_array_equal(out.sel(time="1902").isnull(), True)

def test_3hourly(self, pr_hr_series, random):
pr = pr_hr_series(random.random(366 * 24)).resample(time="3H").mean()
pr = pr_hr_series(random.random(366 * 24)).resample(time="3h").mean()
out = generic.stats(pr, freq="MS", op="var")
assert out.units == "kg^2 m-4 s-2"
assert out.long_name == "Variance of variable"
2 changes: 1 addition & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_day_lengths(method):


def test_cosine_of_solar_zenith_angle():
time = xr.date_range("1900-01-01T00:30", "1900-01-03", freq="H")
time = xr.date_range("1900-01-01T00:30", "1900-01-03", freq="h")
time = xr.DataArray(time, dims=("time",), coords={"time": time}, name="time")
lat = xr.DataArray(
[0, 45, 70], dims=("site",), name="lat", attrs={"units": "degree_north"}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ def test_southhemisphere(self, tas_series):
tas = tas_series(np.zeros(2 * 365), start="2000/1/1")
warm_period = tas.sel(time=slice("2000-11-01", "2001-03-01"))
tas = tas.where(~tas.time.isin(warm_period.time), 280)
gsl = xci.growing_season_length(tas, mid_date="01-01", freq="AS-Jul")
gsl = xci.growing_season_length(tas, mid_date="01-01", freq="AS-JUL")
np.testing.assert_array_equal(gsl.sel(time="2000-07-01"), 121)


Expand Down
16 changes: 8 additions & 8 deletions tests/test_missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ class TestMissingBase:
def test_3hourly_input(self, random):
"""Creating array with 21 days of 3h"""
n = 21 * 8
time = xr.cftime_range(start="2002-01-01", periods=n, freq="3H")
time = xr.cftime_range(start="2002-01-01", periods=n, freq="3h")
ts = xr.DataArray(random.random(n), dims="time", coords={"time": time})
mb = missing.MissingBase(ts, freq="MS", src_timestep="3H")
mb = missing.MissingBase(ts, freq="MS", src_timestep="3h")
# Make sure count is 31 * 8, because we're requesting a MS freq.
assert mb.count == 31 * 8

Expand All @@ -35,7 +35,7 @@ def test_monthly_input(self, random):
n = 5
time = xr.cftime_range(start="2002-06-01", periods=n, freq="MS")
ts = xr.DataArray(random.random(n), dims="time", coords={"time": time})
mb = missing.MissingBase(ts, freq="AS", src_timestep="M", season="JJA")
mb = missing.MissingBase(ts, freq="YS", src_timestep="M", season="JJA")
assert mb.count == 3

def test_seasonal_input(self, random):
Expand Down Expand Up @@ -139,14 +139,14 @@ def test_no_freq(self, tasmin_series):
t = list(range(31))
t.pop(5)
ts2 = ts.isel(time=t)
miss = missing.missing_any(ts2, freq=None, src_timestep="H")
miss = missing.missing_any(ts2, freq=None, src_timestep="h")
np.testing.assert_array_equal(miss, True)

# With indexer
miss = missing.missing_any(ts, freq=None, month=[7])
np.testing.assert_array_equal(miss, False)

miss = missing.missing_any(ts2, freq=None, month=[7], src_timestep="H")
miss = missing.missing_any(ts2, freq=None, month=[7], src_timestep="h")
np.testing.assert_array_equal(miss, True)

def test_hydro(self, open_dataset):
Expand Down Expand Up @@ -264,23 +264,23 @@ def pr(self, pr_hr_series):

def test_any(self, pr_hr_series):
pr = self.pr(pr_hr_series)
out = missing.missing_any(pr, "D", src_timestep="H")
out = missing.missing_any(pr, "D", src_timestep="h")
np.testing.assert_array_equal(
out,
[True] + 8 * [False] + [True],
)

def test_pct(self, pr_hr_series):
pr = self.pr(pr_hr_series)
out = missing.missing_pct(pr, "D", src_timestep="H", tolerance=0.1)
out = missing.missing_pct(pr, "D", src_timestep="h", tolerance=0.1)
np.testing.assert_array_equal(
out,
9 * [False] + [True],
)

def test_at_least_n_valid(self, pr_hr_series):
pr = self.pr(pr_hr_series)
out = missing.at_least_n_valid(pr, "D", src_timestep="H", n=20)
out = missing.at_least_n_valid(pr, "D", src_timestep="h", n=20)
np.testing.assert_array_equal(
out,
9 * [False] + [True],
Expand Down
2 changes: 1 addition & 1 deletion tests/test_precip.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def test_days_over_precip_thresh__seasonal_indexer(open_dataset):
per = pr.quantile(0.8, "time", keep_attrs=True)
# WHEN
out = atmos.days_over_precip_thresh(
pr, per, freq="AS", date_bounds=("01-10", "12-31")
pr, per, freq="YS", date_bounds=("01-10", "12-31")
)
# THEN
np.testing.assert_almost_equal(out[0], np.array([81.0, 66.0, 66.0, 75.0]))
Expand Down
8 changes: 4 additions & 4 deletions tests/test_temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ def test_tx90p__seasonal_indexer(self, tasmax_series):
# create cold spell in june
tas[175:180] = 1
# WHEN
out = atmos.tx90p(tas, t90, freq="AS", season="JJA")
out = atmos.tx90p(tas, t90, freq="YS", season="JJA")
# THEN
assert out[0] == 87 # non regression test

Expand Down Expand Up @@ -1489,7 +1489,7 @@ def test_simple(self, tas_series):

tg = tas_series(a + K2C, start="1/1/2000")

out = atmos.cold_spell_frequency(tg, freq="AS")
out = atmos.cold_spell_frequency(tg, freq="YS")
np.testing.assert_array_equal(out, 1)


Expand All @@ -1500,7 +1500,7 @@ def test_simple(self, tas_series):

tg = tas_series(a + K2C, start="1/1/2000")

out = atmos.cold_spell_max_length(tg, freq="AS")
out = atmos.cold_spell_max_length(tg, freq="YS")
np.testing.assert_array_equal(out, 5)


Expand All @@ -1511,5 +1511,5 @@ def test_simple(self, tas_series):

tg = tas_series(a + K2C, start="1/1/2000")

out = atmos.cold_spell_total_length(tg, freq="AS")
out = atmos.cold_spell_total_length(tg, freq="YS")
np.testing.assert_array_equal(out, 8)
9 changes: 2 additions & 7 deletions xclim/core/bootstrapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import xclim.core.utils

from .calendar import convert_calendar, parse_offset, percentile_doy
from .calendar import construct_offset, convert_calendar, parse_offset, percentile_doy

BOOTSTRAP_DIM = "_bootstrap"

Expand Down Expand Up @@ -202,12 +202,7 @@ def bootstrap_func(compute_index_func: Callable, **kwargs) -> xarray.DataArray:

def _get_bootstrap_freq(freq):
_, base, start_anchor, anchor = parse_offset(freq) # noqa
bfreq = "A"
if start_anchor:
bfreq += "S"
if base in ["A", "Q"] and anchor is not None:
bfreq = f"{bfreq}-{anchor}"
return bfreq
return construct_offset(1, "Y", start_anchor, anchor)


def _get_year_label(year_dt) -> str:
Expand Down
Loading

0 comments on commit 0746d44

Please sign in to comment.