Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove anomaly and climatology #416

Merged
merged 3 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docs/internal_api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@ Internal Functionality Helpers

geocat.comp.climatologies._calculate_center_of_time_bounds

geocat.comp.climatologies._find_time_invariant_vars

geocat.comp.climatologies._get_time_coordinate_info

geocat.comp.climatologies._infer_calendar_name

geocat.comp.climatologies._setup_clim_anom_input

geocat.comp.climatologies._validate_freq

geocat.comp.gradient._arc_lat_wgs84
Expand Down
8 changes: 8 additions & 0 deletions docs/release-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
Release Notes
=============

v2023.05.0 (June 8, 2023)
-------------------------

Breaking Changes
^^^^^^^^^^^^^^^^
* Removed deprecated functions `climatology` and `anomaly` by `Anissa Zacharias`_ in (:pr:`416`)
* Removed internal functions `_find_time_invariant_vars` and `_setup_clim_anom_input` by `Anissa Zacharias`_ in (:pr:`416`)

v2023.05.0 (4 May 2023)
-----------------------
In this release, we've added support for numpy input and other improvements to the gradient function
Expand Down
13 changes: 0 additions & 13 deletions docs/user_api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,3 @@ NCL Function Name Wrappers
:toctree: ./generated/

meteorology.dpres_plev


Deprecated Functions
--------------------
Climatologies
^^^^^^^^^^^^^
.. currentmodule:: geocat.comp.climatologies
.. autosummary::
:nosignatures:
:toctree: ./generated/

anomaly
climatology
2 changes: 1 addition & 1 deletion src/geocat/comp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# move functions into geocat.comp namespace
from .climatologies import anomaly, climatology, month_to_season, calendar_average, climatology_average, climate_anomaly
from .climatologies import month_to_season, calendar_average, climatology_average, climate_anomaly
from .fourier_filters import (fourier_band_block, fourier_band_pass,
fourier_filter, fourier_high_pass,
fourier_low_pass)
Expand Down
237 changes: 0 additions & 237 deletions src/geocat/comp/climatologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@
_FREQUENCIES = {"day", "month", "year", "season"}


def _find_time_invariant_vars(dset, time_coord_name):
if isinstance(dset, xr.Dataset):
return [
v for v in dset.variables if time_coord_name not in dset[v].dims
]
return


def _contains_datetime_like_objects(d_arr):
"""Check if a variable contains datetime like objects (either
np.datetime64, or cftime.datetime)"""
Expand Down Expand Up @@ -45,20 +37,6 @@ def _get_time_coordinate_info(dset, time_coord_name):
return time_coord_name


def _setup_clim_anom_input(dset, freq, time_coord_name):
_validate_freq(freq)

time_coord_name = _get_time_coordinate_info(dset, time_coord_name)
time_invariant_vars = _find_time_invariant_vars(dset, time_coord_name)
if time_invariant_vars:
data = dset.drop_vars(time_invariant_vars)
else:
data = dset
time_dot_freq = ".".join([time_coord_name, freq])

return data, time_invariant_vars, time_coord_name, time_dot_freq


def _calculate_center_of_time_bounds(
dset: typing.Union[xr.Dataset, xr.DataArray],
time_dim: str,
Expand Down Expand Up @@ -131,221 +109,6 @@ def _infer_calendar_name(dates):
return np.asarray(dates).ravel()[0].calendar


def climatology(
dset: typing.Union[xr.DataArray, xr.Dataset],
freq: str,
time_coord_name: str = None,
keep_attrs: bool = None) -> typing.Union[xr.DataArray, xr.Dataset]:
r""".. deprecated:: 2023.02.0 The ``climatology`` function is deprecated due to
inaccuracies in monthly climatology calculations and when using monthly
data to calculate seasonal or yearly climatologies. Use
`climatology_average <https://geocat-comp.readthedocs.io/en/stable/user_api/generated/geocat.comp.climatologies.climatology_average.html>`__
instead.

Compute climatologies for a specified time frequency.

Parameters
----------
dset : :class:`xarray.Dataset`, :class:`xarray.DataArray`
The data on which to operate

freq : str
Climatology frequency alias. Accepted alias:

- `day`: for daily climatologies
- `month`: for monthly climatologies
- `year`: for annual climatologies
- `season': for seasonal climatologies

time_coord_name : str, optional
Name for time coordinate to use. Defaults to ``None`` and infers the name
from the data.

keep_attrs : bool, optional
If True, attrs will be copied from the original object to the new one.
If False, the new object will be returned without attributes.
Defaults to None which means the attrs will only be kept in unambiguous circumstances.

Returns
-------
computed_dset : :class:`xarray.Dataset`, :class:`xarray.DataArray`
The computed climatology data

Examples
--------
>>> import xarray as xr
>>> import pandas as pd
>>> import numpy as np
>>> import geocat.comp
>>> # Create toy data set
>>> dates = pd.date_range(start="2000/01/01",
... freq="M",
... periods=24)
>>> ts = xr.DataArray(np.arange(24).reshape(24, 1, 1),
... dims=["time", "lat", "lon"],
... coords={"time": dates})
>>> ts
<xarray.DataArray (time: 24, lat: 1, lon: 1)>
array([[[ 0]],
[[ 1]],
[[ 2]],
<BLANKLINE>
[[21]],
[[22]],
[[23]]])
Coordinates:
* time (time) datetime64[ns] 2000-01-31 2000-02-29 ... 2001-12-31
Dimensions without coordinates: lat, lon

>>> # Calculate yearly climate averages
>>> geocat.comp.climatology(ts, 'year')
<xarray.DataArray (year: 2, lat: 1, lon: 1)>
array([[[ 5.5]],
[[17.5]]])
Coordinates:
* year (year) int64 2000 2001
Dimensions without coordinates: lat, lon

>>> # Calculate seasonal climate averages
>>> geocat.comp.climatology(ts, 'season')
<xarray.DataArray (season: 4, lat: 1, lon: 1)>
array([[[10.]],
[[12.]],
[[ 9.]],
[[15.]]])
Coordinates:
* season (season) object 'DJF' 'JJA' 'MAM' 'SON'
Dimensions without coordinates: lat, lon

See Also
--------
Related GeoCAT Functions:
:func:`climatology_average`

Related NCL Functions:
`clmDayTLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmDayTLL.shtml>`__,
`clmDayTLLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmDayTLLL.shtml>`__,
`clmMonLLLT <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmMonLLLT.shtml>`__,
`clmMonLLT <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmMonLLT.shtml>`__,
`clmMonTLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmMonTLL.shtml>`__,
`clmMonTLLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/clmMonTLLL.shtml>`__,
`month_to_season <https://www.ncl.ucar.edu/Document/Functions/Contributed/month_to_season.shtml>`__
"""
data, time_invariant_vars, time_coord_name, time_dot_freq = _setup_clim_anom_input(
dset, freq, time_coord_name)

grouped = data.groupby(time_dot_freq)
# TODO: Compute weighted climatologies when `time_bounds` are available
clim = grouped.mean(time_coord_name, keep_attrs=keep_attrs)
if time_invariant_vars:
if keep_attrs == False:
return xr.concat([dset[time_invariant_vars], clim],
combine_attrs='drop',
dim=time_coord_name)
else:
return xr.concat([dset[time_invariant_vars], clim],
dim=time_coord_name)
else:
return clim


def anomaly(
dset: typing.Union[xr.DataArray, xr.Dataset],
freq: str,
time_coord_name: str = None) -> typing.Union[xr.DataArray, xr.Dataset]:
r""".. deprecated:: 2023.02.0 The ``anomaly`` function is deprecated due to
inaccuracies in monthly anomaly calculations and when using monthly
data to calculate seasonal or yearly anomalies. Use `climate_anomaly <https://geocat-comp.readthedocs.io/en/stable/user_api/generated/geocat.comp.climatologies.climate_anomaly.html>`__
instead.

Parameters
----------
dset : :class:`xarray.Dataset`, :class:`xarray.DataArray`
The data on which to operate

freq : str
Anomaly frequency alias. Accepted alias:

- `day`: for daily anomalies
- `month`: for monthly anomalies
- `year`: for annual anomalies
- `season`: for seasonal anomalies

time_coord_name : str, optional
Name for time coordinate to use. Defaults to ``None`` and infers the name
from the data.

Returns
-------
computed_dset : :class:`xarray.Dataset`, :class:`xarray.DataArray`
The computed anomaly data

Examples
--------
>>> import xarray as xr
>>> import pandas as pd
>>> import numpy as np
>>> import geocat.comp
>>> # Create toy data
>>> dates = pd.date_range(start="2000/01/01",
... freq="M",
... dates=24)
>>> ts = xr.DataArray(np.arange(24).reshape(24, 1, 1),
... dims=["time", "lat", "lon"],
... coords={"time": dates})
>>> ts
<xarray.DataArray (time: 24, lat: 1, lon: 1)>
array([[[ 0]],
[[ 1]],
[[ 2]],
<BLANKLINE>
[[21]],
[[22]],
[[23]]])
Coordinates:
* time (time) datetime64[ns] 2000-01-31 2000-02-29 ... 2001-12-31
Dimensions without coordinates: lat, lon

>>> # Compute seasonal anomalies
>>> geocat.comp.anomaly(ts, 'season')
<xarray.DataArray (time: 24, lat: 1, lon: 1)>
array([[[-10.]],
[[ -9.]],
[[ -7.]],
<BLANKLINE>
[[ 6.]],
[[ 7.]],
[[ 13.]]])
Coordinates:
* time (time) datetime64[ns] 2000-01-31 2000-02-29 ... 2001-12-31
season (time) <U3 'DJF' 'DJF' 'MAM' 'MAM' ... 'SON' 'SON' 'SON' 'DJF'
Dimensions without coordinates: lat, lon

See Also
--------
Related GeoCAT Functions:
:func:`climate_anomaly`

Related NCL Functions:
`clmDayAnomTLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcDayAnomTLL.shtml>`__,
`clmDayAnomTLLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcMonAnomTLLL.shtml>`__,
`clmMonAnomLLLT <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcMonAnomLLLT.shtml>`__,
`clmMonAnomLLT <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcMonAnomLLT.shtml>`__,
`clmMonAnomTLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcMonAnomTLL.shtml>`__,
`clmMonAnomTLLL <https://www.ncl.ucar.edu/Document/Functions/Contributed/calcMonAnomTLLL.shtml>`__
"""

data, time_invariant_vars, time_coord_name, time_dot_freq = _setup_clim_anom_input(
dset, freq, time_coord_name)

clim = climatology(data, freq, time_coord_name)
anom = data.groupby(time_dot_freq) - clim
if time_invariant_vars:
return xr.merge([dset[time_invariant_vars], anom])
else:
return anom


def climate_anomaly(
dset: typing.Union[xr.DataArray, xr.Dataset],
freq: str,
Expand Down
Loading