diff --git a/cordex/domain.py b/cordex/domain.py index fff0fac..69abd51 100644 --- a/cordex/domain.py +++ b/cordex/domain.py @@ -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 @@ -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, @@ -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: @@ -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,) diff --git a/cordex/preprocessing/preprocessing.py b/cordex/preprocessing/preprocessing.py index 1d4d1ae..8e7f65e 100644 --- a/cordex/preprocessing/preprocessing.py +++ b/cordex/preprocessing/preprocessing.py @@ -5,6 +5,8 @@ """ +from warnings import warn + import numpy as np import xarray as xr @@ -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)] @@ -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. diff --git a/cordex/tables/__init__.py b/cordex/tables/__init__.py index 5034fd5..627f1b2 100644 --- a/cordex/tables/__init__.py +++ b/cordex/tables/__init__.py @@ -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", ] @@ -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) @@ -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) diff --git a/cordex/tables/_resources.py b/cordex/tables/_resources.py index b009580..e850055 100644 --- a/cordex/tables/_resources.py +++ b/cordex/tables/_resources.py @@ -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, }, ) @@ -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): @@ -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(): diff --git a/docs/whats_new.rst b/docs/whats_new.rst index 107fec2..0b85bec 100644 --- a/docs/whats_new.rst +++ b/docs/whats_new.rst @@ -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 `_ (: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 ~~~~~~~~~~~~~~~~ diff --git a/tests/test_tables.py b/tests/test_tables.py index d31b789..69d2d42 100644 --- a/tests/test_tables.py +++ b/tests/test_tables.py @@ -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"])