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

updated domain table fetch #140

Merged
merged 4 commits into from
Jul 2, 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
36 changes: 20 additions & 16 deletions cordex/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@
from .utils import get_tempfile


def _locate_domain_id(domain_id, tables):
"""Locate domain_id in domain table trying different indexes."""
indexes = ["short_name", "domain_id", "CORDEX_domain"]

for i in indexes:
if domain_id in tables.reset_index()[i].values:
return (
tables.reset_index().replace(np.nan, None).set_index(i).loc[domain_id]
)

return tables.replace(np.nan, None).loc[domain_id]


def domain_names(table_name=None):
"""Returns a list of short names of all availabe Cordex domains

Expand Down Expand Up @@ -112,11 +125,12 @@ def cordex_domain(
tables = domains.table
if isinstance(tables, list):
tables = pd.concat(tables)
config = tables.replace(np.nan, None).loc[domain_id]

config = _locate_domain_id(domain_id, tables)

return create_dataset(
**config,
domain_id=domain_id,
# domain_id=domain_id,
dummy=dummy,
add_vertices=False,
attrs=attrs,
Expand Down Expand Up @@ -214,11 +228,15 @@ def create_dataset(
attrs = cv["default_global_attrs"]
elif attrs is None:
attrs = {}

if name:
attrs[cv["domain_id"]] = name
# remove inconsistencies in keyword names
if domain_id:
attrs[cv["domain_id"]] = domain_id
if cv["domain_id"] in kwargs:
attrs[cv["domain_id"]] = kwargs[cv["domain_id"]]

if pollon is None or pollat is None:
rotated = False
try:
Expand Down Expand Up @@ -424,20 +442,6 @@ def _bounds(coord, include="left"):
return xr.merge([left, right])


def bounds_coordinates(ds, coords):
"""Adds coordinate bounds as coordinates to the dataset."""
if isinstance(coords, str):
coords = (coords,)
bounds = []
for coord in coords:
lr = _bounds(ds.coords[coord])
name = ds.coords[coord].name + "_b"
bounds.append(
xr.DataArray(np.append(lr.left, lr.right[-1]), dims=name, name=name)
)
return ds.assign_coords({b.name: b for b in bounds})


def bounds(coords):
if isinstance(coords, xr.DataArray):
coords = (coords,)
Expand Down
37 changes: 8 additions & 29 deletions cordex/preprocessing/preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"""


from warnings import warn

import numpy as np
import xarray as xr

Expand Down Expand Up @@ -447,6 +449,12 @@ def get_grid_mapping(ds):
Dataarray containing the grid mapping meta data.

"""
message = (
"get_grid_mapping is deprecated, please use cf_xarray "
'accessor ds.cf["grid_mapping"] instead.'
)
warn(message, DeprecationWarning, stacklevel=2)

return ds[get_grid_mapping_varname(ds)]


Expand Down Expand Up @@ -553,35 +561,6 @@ def member_id_to_dset_id(ds_dict):
return ds_split


# def dset_ids_to_coord(ds_dict):
# """Creates a DataArray from dataset ids"""
# dset_ids = list(ds_dict.keys())
# dim = xr.DataArray(
# dset_ids, dims="dset_id", name="dset_id", coords={"dset_id": dset_ids}
# )
# return dim


# def align_time_axis(ds_dict):
# from datetime import datetime as dt

# for ds in ds_dict.values():
# # ds = ds.copy()
# ds.coords["time"] = [dt(date.year, date.month, 15) for date in ds.time.values]
# return ds_dict


# def concat_along_dset_id(ds_dict, coords="minimal", compat="override", **kwargs):
# dset_coord = dset_ids_to_coord(ds_dict)
# ds_dict = align_time_axis(ds_dict)
# ds_list = []
# for ds in ds_dict.values():
# ds = replace_rlon_rlat(ds)
# ds = replace_lon_lat(ds)
# ds_list.append(ds)
# return xr.concat(ds_list, dim=dset_coord, coords=coords, compat=compat, **kwargs)


def sort_ds_dict_by_attr(ds_dict, attr):
"""Sorts the dataset dict by a certain attribute.

Expand Down
63 changes: 31 additions & 32 deletions cordex/tables/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
from warnings import warn

import pandas as pd

from ._resources import (
from ._resources import ( # fetch_cmip6_cmor_table,
cmor_tables_inpath,
ecmwf_tables,
fetch_cmip6_cmor_table,
fetch_cordex_cmor_table,
read_cordex_domain_tables,
read_domain_table,
)

# __cmor_table_version__ = cmor_table_version
__all__ = [
"cmor_tables_inpath",
"ecmwf_tables",
"fetch_cmpi6_cmor_table",
# "fetch_cmpi6_cmor_table",
"fetch_cordex_cmor_table",
"read_cordex_domain_tables",
"read_cordex_domain_table",
"cmor_tables_inpath",
]

Expand All @@ -31,13 +28,15 @@ def tables(self):

@property
def table(self):
return pd.concat(self.tables.values())
if isinstance(self.tables, dict):
return pd.concat(self.tables.values())
return self.tables

# def __getattr__(self, table):
# return self.tables[table]


domains = read_cls(read_cordex_domain_tables)
domains = read_cls(read_domain_table)

ecmwf = read_cls(ecmwf_tables)

Expand Down Expand Up @@ -69,26 +68,26 @@ def cordex_cmor_table(table, table_dir=None):
return fetch_cordex_cmor_table(table)


def cmip6_cmor_table(table):
"""fetch a cmip6 cmor table

If required, the table will be download from github.
The tables are experimental right now and only used
for development purposes.

Parameters
----------
table: str
Name of the cmip6 table.

Returns
-------
filename : str
Filepath to the cmip6 cmor table.
"""
warn(
"CMIP6 cmor table fetching is deprecated and will be removed in the future. Please use cordex_cmor_table instead.",
DeprecationWarning,
stacklevel=2,
)
return fetch_cmip6_cmor_table(table)
# def cmip6_cmor_table(table):
# """fetch a cmip6 cmor table
#
# If required, the table will be download from github.
# The tables are experimental right now and only used
# for development purposes.
#
# Parameters
# ----------
# table: str
# Name of the cmip6 table.
#
# Returns
# -------
# filename : str
# Filepath to the cmip6 cmor table.
# """
# warn(
# "CMIP6 cmor table fetching is deprecated and will be removed in the future. Please use cordex_cmor_table instead.",
# DeprecationWarning,
# stacklevel=2,
# )
# return fetch_cmip6_cmor_table(table)
25 changes: 10 additions & 15 deletions cordex/tables/_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ def _construct_cache_dir(path):
# Use the default cache folder for the OS
path=cache_url, # pooch.os_cache("cordex"),
# The remote data is on Github
base_url=base_url + "domains/",
base_url="https://raw.githubusercontent.com/WCRP-CORDEX/domain-tables/main/",
registry={
"cordex.csv": None,
"cordex-high-res.csv": None,
"cordex-fps.csv": None,
"cordex-core.csv": None,
"cordex-regular.csv": None,
"rotated-latitude-longitude.csv": None,
},
)

Expand Down Expand Up @@ -70,10 +66,10 @@ def fetch_cordex_cmor_table(table):
)


def fetch_cmip6_cmor_table(table):
return retrieve_cmor_table(
table, url="https://github.com/PCMDI/cmip6-cmor-tables/raw/master/Tables"
)
# def fetch_cmip6_cmor_table(table):
# return retrieve_cmor_table(
# table, url="https://github.com/PCMDI/cmip6-cmor-tables/raw/master/Tables"
# )


def retrieve_cmor_table(table, url):
Expand Down Expand Up @@ -106,12 +102,11 @@ def read_region_table(name):
return read_remote_table(name, resource=REGION_RESOURCE, index_col="area")


def read_cordex_domain_tables():
def read_domain_table():
resource = DOMAIN_RESOURCE
return {
table.split(".")[0]: read_remote_table(table, resource, index_col="short_name")
for table in resource.registry.keys()
}
return read_remote_table(
"rotated-latitude-longitude.csv", resource, index_col="short_name"
)


def region_tables():
Expand Down
8 changes: 4 additions & 4 deletions docs/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ What's New
v0.6.0 (Unreleased)
-------------------

New Features
~~~~~~~~~~~~
Internal Changes
~~~~~~~~~~~~~~~~

- Support for upcoming CORDEX-CMIP6 vocabulary. This includes the new keyword `mip_era` in :py:meth:`cmor.cordex_domain` and
:py:meth:`cmor.create_dataset` (:pull:`129`).
- Support for upcoming CORDEX-CMIP6 vocabulary. This includes the new keyword `mip_era` in :py:meth:`cmor.cordex_domain` and :py:meth:`cmor.create_dataset` (:pull:`129`).
- Updated domain table fetching. There is now only one table that contains all domain definitions which is now located in the `WCRP CORDEX github table repository <https://github.com/WCRP-CORDEX/domain-tables/blob/main/rotated-latitude-longitude.csv>`_ (:pull:`140`). This table allows for selection by different naming conventions for the domain identifier, e.g., ``EUR-12`` is equivilant to ``EUR-11``, etc.

Breaking Changes
~~~~~~~~~~~~~~~~
Expand Down
29 changes: 14 additions & 15 deletions tests/test_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@

import cordex as cx


@pytest.mark.parametrize(
"table",
[
"CMIP6_Amon",
"CMIP6_day",
"CMIP6_E1hr",
"CMIP6_E3hr",
"CMIP6_coordinate",
"CMIP6_fx",
"CMIP6_grids",
],
)
def test_download_cmip6_cmor_tables(table):
cx.tables.cmip6_cmor_table(table)
# @pytest.mark.parametrize(
# "table",
# [
# "CMIP6_Amon",
# "CMIP6_day",
# "CMIP6_E1hr",
# "CMIP6_E3hr",
# "CMIP6_coordinate",
# "CMIP6_fx",
# "CMIP6_grids",
# ],
# )
# def test_download_cmip6_cmor_tables(table):
# cx.tables.cmip6_cmor_table(table)


@pytest.mark.parametrize("table", ["CORDEX_CV", "CORDEX_remo_example"])
Expand Down
Loading