Skip to content

Commit

Permalink
Add dataset and data variable wrappers for common operations
Browse files Browse the repository at this point in the history
- Add dataset.py and variable.py which stores wrappers
- Update .gitignore
  • Loading branch information
tomvothecoder committed Jul 23, 2021
1 parent 6b811fa commit 0f5744c
Show file tree
Hide file tree
Showing 12 changed files with 856 additions and 91 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,14 @@ Local Development
plugins: anyio-2.2.0, cov-2.11.1
collected 3 items

tests/test_utils.py ..
tests/test_dataset.py ..
tests/test_xcdat.py .

---------- coverage: platform darwin, python 3.8.8-final-0 -----------
Name Stmts Miss Cover
---------------------------------------
xcdat/__init__.py 3 0 100%
xcdat/utils.py 18 0 100%
xcdat/dataset.py 18 0 100%
xcdat/xcdat.py 0 0 100%
---------------------------------------
TOTAL 21 0 100%
Expand Down
3 changes: 1 addition & 2 deletions conda-env/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ dependencies:
- python=3.8.8
- pip=21.0.1
- typing_extensions=3.7.4 # Required to make use of Python >=3.8 backported types
- cartopy=0.18.0
- matplotlib=3.3.4
- netcdf4=1.5.6
- xarray=0.17.0
- cf_xarray=0.6.0
- dask=2021.7.0
# Additional
# ==================
- bump2version==1.0.1
Expand Down
1 change: 1 addition & 0 deletions conda-env/readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies:
- matplotlib=3.3.4
- netcdf4=1.5.6
- xarray=0.17.0
- dask=2021.7.0
# Documentation
# ==================
- sphinx=3.5.1
Expand Down
4 changes: 1 addition & 3 deletions conda-recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ requirements:
run:
- python
- typing_extensions
- cartopy
- matplotlib
- netcdf4
- xarray
- typing_extensions
- dask
- cf_xarray

test:
Expand Down
3 changes: 2 additions & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ API Reference
:toctree: generated/

xcdat.coord
xcdat.dataset
xcdat.log
xcdat.utils
xcdat.variable
165 changes: 165 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"""This module stores reusable test fixtures."""
from datetime import datetime

import numpy as np
import xarray as xr

# If the fixture is an xarray object, make sure to use .copy() to create a
# shallow copy of the object. Otherwise, you might run into unintentional
# side-effects caused by reference assignment.
# https://xarray.pydata.org/en/stable/generated/xarray.DataArray.copy.html

# Dataset coordinates
time = xr.DataArray(
data=[
datetime(2000, 1, 1),
datetime(2000, 2, 1),
datetime(2000, 3, 1),
datetime(2000, 4, 1),
datetime(2000, 5, 1),
datetime(2000, 6, 1),
datetime(2000, 7, 1),
datetime(2000, 8, 1),
datetime(2000, 9, 1),
datetime(2000, 10, 1),
datetime(2000, 11, 1),
datetime(2000, 12, 1),
],
dims=["time"],
)
time_non_cf_compliant = xr.DataArray(
data=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
dims=["time"],
attrs={"units": "months since 2000-01-01"},
)

lat = xr.DataArray(
data=np.array([-90, -88.75, 88.75, 90]),
dims=["lat"],
attrs={"units": "degrees_north", "axis": "Y"},
)
lon = xr.DataArray(
data=np.array([0, 1.875, 356.25, 358.125]),
dims=["lon"],
attrs={"units": "degrees_east", "axis": "X"},
)

# Dataset data variables (bounds)
time_bnds = xr.DataArray(
name="time_bnds",
data=[
[datetime(2000, 1, 1), datetime(2000, 2, 1)],
[datetime(2000, 2, 1), datetime(2000, 3, 1)],
[datetime(2000, 3, 1), datetime(2000, 4, 1)],
[datetime(2000, 4, 1), datetime(2000, 5, 1)],
[datetime(2000, 5, 1), datetime(2000, 6, 1)],
[datetime(2000, 6, 1), datetime(2000, 7, 1)],
[datetime(2000, 7, 1), datetime(2000, 8, 1)],
[datetime(2000, 8, 1), datetime(2000, 9, 1)],
[datetime(2000, 9, 1), datetime(2000, 10, 1)],
[datetime(2000, 10, 1), datetime(2000, 11, 1)],
[datetime(2000, 11, 1), datetime(2000, 12, 1)],
[datetime(2000, 12, 1), datetime(2001, 1, 1)],
],
coords={"time": time},
dims=["time", "bnds"],
)
time_bnds_non_cf_compliant = xr.DataArray(
name="time_bnds",
data=[
[datetime(2000, 1, 1), datetime(2000, 2, 1)],
[datetime(2000, 2, 1), datetime(2000, 3, 1)],
[datetime(2000, 3, 1), datetime(2000, 4, 1)],
[datetime(2000, 4, 1), datetime(2000, 5, 1)],
[datetime(2000, 5, 1), datetime(2000, 6, 1)],
[datetime(2000, 6, 1), datetime(2000, 7, 1)],
[datetime(2000, 7, 1), datetime(2000, 8, 1)],
[datetime(2000, 8, 1), datetime(2000, 9, 1)],
[datetime(2000, 9, 1), datetime(2000, 10, 1)],
[datetime(2000, 10, 1), datetime(2000, 11, 1)],
[datetime(2000, 11, 1), datetime(2000, 12, 1)],
[datetime(2000, 12, 1), datetime(2001, 1, 1)],
],
coords={"time": time.data},
dims=["time", "bnds"],
)
lat_bnds = xr.DataArray(
name="lat_bnds",
data=np.array([[-90, -89.375], [-89.375, 0.0], [0.0, 89.375], [89.375, 90]]),
coords={"lat": lat.data},
dims=["lat", "bnds"],
attrs={"units": "degrees_north", "axis": "Y", "is_generated": "True"},
)
lon_bnds = xr.DataArray(
name="lon_bnds",
data=np.array(
[
[-0.9375, 0.9375],
[0.9375, 179.0625],
[179.0625, 357.1875],
[357.1875, 359.0625],
]
),
coords={"lon": lon.data},
dims=["lon", "bnds"],
attrs={"units": "degrees_east", "axis": "X", "is_generated": "True"},
)

# Dataset data variables (variables)
ts = xr.DataArray(
name="ts",
data=np.ones((12, 4, 4)),
coords={"time": time, "lat": lat, "lon": lon},
dims=["time", "lat", "lon"],
)
ts_non_cf_compliant = xr.DataArray(
name="ts",
data=np.ones((12, 4, 4)),
coords={"time": time_non_cf_compliant, "lat": lat, "lon": lon},
dims=["time", "lat", "lon"],
)


def generate_dataset(cf_compliant=True, has_bounds: bool = True) -> xr.Dataset:
"""Generates a dataset using coordinate and data variable fixtures.
NOTE: Using ``.assign()`` to add data variables to an existing dataset will
remove attributes from existing coordinates. The workaround is to update a
data_vars dict then create the dataset. https://github.com/pydata/xarray/issues/2245
Parameters
----------
cf_compliant : bool, optional
CF compliant time units, by default True
has_bounds : bool, optional
Include bounds for coordinates, by default True
Returns
-------
xr.Dataset
Test dataset.
"""
data_vars = {}
coords = {
"lat": lat.copy(),
"lon": lon.copy(),
}

if cf_compliant:
coords.update({"time": time.copy()})
data_vars.update({"ts": ts.copy()})
else:
coords.update({"time": time_non_cf_compliant.copy()})
data_vars.update({"ts": ts_non_cf_compliant.copy()})

if has_bounds:
data_vars.update(
{
"time_bnds": time_bnds.copy(),
"lat_bnds": lat_bnds.copy(),
"lon_bnds": lon_bnds.copy(),
}
)

ds = xr.Dataset(data_vars=data_vars, coords=coords)
return ds
Loading

0 comments on commit 0f5744c

Please sign in to comment.