%load_ext autoreload
%autoreload 2
Examples of CORDEX-CMIP6 cmorization#
Introduction#
This notebook demonstrates how climate model output can be reformatted and standardized using CMOR (Climate Model Output Rewriter) for the CORDEX-CMIP6 framework.
What is CMORization?
CMORization is the process of converting raw model output into standardized netCDF files
It ensures compliance with CF (Climate and Forecast) conventions
It automatically handles unit conversions, time resampling, and metadata standardization
In this notebook, we’ll show examples of how to cmorize different types of climate data (fixed fields, monthly, and sub-daily data).
!ls ../Tables
CORDEX-CMIP6_1hr.json CORDEX-CMIP6_formula_terms.json
CORDEX-CMIP6_3hr.json CORDEX-CMIP6_fx.json
CORDEX-CMIP6_6hr.json CORDEX-CMIP6_grids.json
CORDEX-CMIP6_CV.json CORDEX-CMIP6_mon.json
CORDEX-CMIP6_coordinate.json CORDEX-CMIP6_remo_example.json
CORDEX-CMIP6_day.json
Controlled Vocabulary (CV)#
The CORDEX-CMIP6_CV.json file defines the controlled vocabulary and required global attributes that the CMOR3 library uses for rewriting and validating the model output. This ensures all CORDEX-CMIP6 datasets follow the same conventions and contain consistent metadata.
Below we show the required global attributes that must be present in every CORDEX-CMIP6 dataset:
import json
import pprint
from IPython.display import JSON
# Opening JSON file
with open("../Tables/CORDEX-CMIP6_CV.json") as json_file:
CV = json.load(json_file)["CV"]
# JSON(CV['required_global_attributes'])
pprint.pprint(CV["required_global_attributes"])
['activity_id',
'contact',
'Conventions',
'creation_date',
'domain_id',
'domain',
'driving_experiment_id',
'driving_experiment',
'driving_institution_id',
'driving_source_id',
'driving_variant_label',
'frequency',
'grid',
'institution',
'institution_id',
'license',
'mip_era',
'product',
'project_id',
'source',
'source_id',
'source_type',
'tracking_id',
'variable_id',
'version_realization']
CMORization Examples#
We use the cordex.cmor module to create examples of CORDEX-CMIP6 compliant datasets. The following section defines three functions that demonstrate how to cmorize different types of climate data:
Fixed fields (fx): Time-independent data like topography (orog)
Monthly data (mon): Variables averaged over monthly timescales (e.g., temperature)
Sub-daily data: Hourly, 3-hourly, and 6-hourly data that can be automatically resampled
Each function shows how to:
Specify the input variable mapping
Define the CMOR table for the output format
Handle coordinate systems and domain information
Convert units as needed
Example 1: Fixed Fields (fx) - Topography#
This example demonstrates CMORization of fixed fields, using topography (orog) as an example. Fixed fields are time-independent variables that describe static properties of the domain, such as terrain height or land-sea masks.
We’ll create the file, then inspect it using xarray and various validation tools:
f = test_cmorizer_fx()
Generated Filename#
The filename follows the CORDEX-CMIP6 naming convention, encoding information about the domain, driving model, and version:
f
'CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/fx/orog/v20261020/orog_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_fx.nc'
# Display the netCDF header showing all metadata and attributes
!ncdump -h $f
netcdf orog_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_fx {
dimensions:
rlat = 412 ;
rlon = 424 ;
bnds = 2 ;
vertices = 4 ;
variables:
double rlat(rlat) ;
rlat:units = "degrees" ;
rlat:axis = "Y" ;
rlat:long_name = "latitude in rotated pole grid" ;
rlat:standard_name = "grid_latitude" ;
double rlon(rlon) ;
rlon:units = "degrees" ;
rlon:axis = "X" ;
rlon:long_name = "longitude in rotated pole grid" ;
rlon:standard_name = "grid_longitude" ;
int rotated_latitude_longitude ;
rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ;
rotated_latitude_longitude:grid_north_pole_latitude = 39.25 ;
rotated_latitude_longitude:grid_north_pole_longitude = -162. ;
rotated_latitude_longitude:north_pole_grid_longitude = 0. ;
rotated_latitude_longitude:earth_radius = 6371229. ;
double lat(rlat, rlon) ;
lat:standard_name = "latitude" ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:missing_value = 1.e+20 ;
lat:_FillValue = 1.e+20 ;
lat:bounds = "vertices_lat" ;
double lon(rlat, rlon) ;
lon:standard_name = "longitude" ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:missing_value = 1.e+20 ;
lon:_FillValue = 1.e+20 ;
lon:bounds = "vertices_lon" ;
double vertices_lat(rlat, rlon, vertices) ;
vertices_lat:units = "degrees_north" ;
vertices_lat:missing_value = 1.e+20 ;
vertices_lat:_FillValue = 1.e+20 ;
double vertices_lon(rlat, rlon, vertices) ;
vertices_lon:units = "degrees_east" ;
vertices_lon:missing_value = 1.e+20 ;
vertices_lon:_FillValue = 1.e+20 ;
float orog(rlat, rlon) ;
orog:standard_name = "surface_altitude" ;
orog:long_name = "Surface Altitude" ;
orog:comment = "The surface called \'surface\' means the lower boundary of the atmosphere. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level." ;
orog:units = "m" ;
orog:cell_methods = "area: mean" ;
orog:cell_measures = "area: areacella" ;
orog:missing_value = 1.e+20f ;
orog:_FillValue = 1.e+20f ;
orog:grid_mapping = "rotated_latitude_longitude" ;
orog:coordinates = "lat lon" ;
// global attributes:
:Conventions = "CF-1.11" ;
:activity_id = "DD" ;
:contact = "gerics-cordex@hereon.de" ;
:creation_date = "2026-10-20T12:56:02Z" ;
:domain = "Europe" ;
:domain_id = "EUR-12" ;
:driving_experiment = "reanalysis simulation of the recent past" ;
:driving_experiment_id = "evaluation" ;
:driving_institution_id = "ECMWF" ;
:driving_source = "ECMWF Reanalysis v5" ;
:driving_source_id = "ERA5" ;
:driving_variant_label = "r1i1p1f1" ;
:experiment_id = "evaluation" ;
:external_variables = "areacella" ;
:frequency = "fx" ;
:grid = "Rotated-pole latitude-longitude with 0.11 degree grid spacing" ;
:history = "2026-10-20T12:56:02Z ;rewrote data to be consistent with CORDEX-CMIP6 for variable orog found in table fx." ;
:institution = "Climate Service Center Germany, Helmholtz Centre hereon GmbH, Hamburg, Germany" ;
:institution_id = "GERICS" ;
:label = "REMO2020 v2.2" ;
:mip_era = "CMIP6" ;
:product = "model-output" ;
:project_id = "CORDEX-CMIP6" ;
:references = "https://www.remo-rcm.de" ;
:run_variant = "1st realization" ;
:source = "Regional Climate Model REMO, version 2.2, hydrostatic configuration with MACv2 aerosol forcing and Fresh-water Lake model (FLake) (2023)" ;
:source_id = "REMO2020-2-2" ;
:source_type = "ARCM" ;
:table_id = "fx" ;
:table_info = "Name: CORDEX-CMIP6_fx.json; Creation Date:(07 September 2026) MD5:7d8c68a16e22b8a61989906b159c0196" ;
:title = "GERICS REMO2020-2-2 downscaling of ERA5 evaluation for CORDEX-CMIP6 EUR-12" ;
:tracking_id = "hdl:21.14103/844d0a4d-606d-47f1-8b8c-7d30e542739b" ;
:variable_id = "orog" ;
:version_realization = "v1-r1" ;
:license = "https://cordex.org/data-access/cordex-cmip6-data/cordex-cmip6-terms-of-use" ;
:cmor_version = "3.16.0" ;
}
Interactive Dataset Exploration with xarray#
The xarray dataset representation provides an interactive way to explore the dataset structure, dimensions, variables, and attributes:
ds = xr.open_dataset(f)
ds
<xarray.Dataset> Size: 15MB
Dimensions: (rlat: 412, rlon: 424, vertices: 4)
Coordinates:
* rlat (rlat) float64 3kB -23.38 -23.27 ... 21.73 21.84
* rlon (rlon) float64 3kB -28.38 -28.27 ... 18.05 18.16
lat (rlat, rlon) float64 1MB ...
lon (rlat, rlon) float64 1MB ...
Dimensions without coordinates: vertices
Data variables:
rotated_latitude_longitude int32 4B ...
vertices_lat (rlat, rlon, vertices) float64 6MB ...
vertices_lon (rlat, rlon, vertices) float64 6MB ...
orog (rlat, rlon) float32 699kB ...
Attributes: (12/36)
Conventions: CF-1.11
activity_id: DD
contact: gerics-cordex@hereon.de
creation_date: 2026-10-20T12:56:02Z
domain: Europe
domain_id: EUR-12
... ...
title: GERICS REMO2020-2-2 downscaling of ERA5 evaluati...
tracking_id: hdl:21.14103/844d0a4d-606d-47f1-8b8c-7d30e542739b
variable_id: orog
version_realization: v1-r1
license: https://cordex.org/data-access/cordex-cmip6-data...
cmor_version: 3.16.0ds.orog.plot()
<matplotlib.collections.QuadMesh at 0x7f34037eb020>
In the following cell, we will demonstrate how to check the cmorized datasets using three different tools: cdo verifygrid, cf-checker, and the IOOS compliance-checker including the WCRP plugin:
!cdo verifygrid $f
cdo verifygrid: Grid consists of 174688 (424x412) cells (type: curvilinear), of which
cdo verifygrid: 174688 cells have 4 vertices
cdo verifygrid: lon : -44.59386 to 64.96438 degrees
cdo verifygrid: lat : 21.98783 to 72.585 degrees
cdo verifygrid: Processed 1 variable [0.11s 602M]
!cfchecks $f
CHECKING NetCDF FILE: CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/fx/orog/v20261020/orog_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_fx.nc
=====================
Using CF Checker Version 4.1.0
Checking against CF Version CF-1.8
Using Standard Name Table Version 95 (2026-09-16T04:56:46Z)
Using Area Type Table Version 13 (20 March 2025)
Using Standardized Region Name Table Version 5 (12 November 2024)
ERROR: (2.6.1): This netCDF file does not appear to contain CF Convention data.
WARN: (7.1): Boundary var vertices_lat should not have attribute units
WARN: (7.1): Boundary var vertices_lon should not have attribute units
------------------
Checking variable: rlat
------------------
------------------
Checking variable: rlon
------------------
------------------
Checking variable: rotated_latitude_longitude
------------------
------------------
Checking variable: lat
------------------
------------------
Checking variable: lon
------------------
------------------
Checking variable: vertices_lat
------------------
WARN: (7.1): Boundary Variable vertices_lat should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lat should not have missing_value attribute
------------------
Checking variable: vertices_lon
------------------
WARN: (7.1): Boundary Variable vertices_lon should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lon should not have missing_value attribute
------------------
Checking variable: orog
------------------
ERRORS detected: 1
WARNINGS given: 6
INFORMATION messages: 0
The compliance checker can be used to validate the cmorized file against the CORDEX-CMIP6 standard. Note that these tests should return no high priority issues. The following command runs the compliance checker with the appropriate tests:
!compliance-checker --test=cf:1.11 --test=wcrp_cordex_cmip6 $f
Running Compliance Checker on the datasets from: ['CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/fx/orog/v20261020/orog_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_fx.nc']
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_coordinate.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_coordinate.json'.
SHA256 hash of downloaded file: ebdc7e928412179be6db384f3b3955383248a0d9581712ad91eed1730319bf4a
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_grids.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_grids.json'.
SHA256 hash of downloaded file: 6d9b6f6b4678be242c70b23620748aaa67e509fc624c060231d92108e409dd8f
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_formula_terms.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_formula_terms.json'.
SHA256 hash of downloaded file: 3d6ae4d188ad95dbea93fa4ca19f81e2d7c6cecf3707acd768549a8201e36819
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_CV.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_CV.json'.
SHA256 hash of downloaded file: a73c6a78843632cc1f816b6b778e54a166ac97311b9959b000ca176a5307881c
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_1hr.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_1hr.json'.
SHA256 hash of downloaded file: 6ca30fec98917f29fa1193f3f91f2c6a29bab75bb304003fd72e8e6f689d48f8
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_3hr.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_3hr.json'.
SHA256 hash of downloaded file: 7c9411fb89eb8e8599cba86f72d87515a83e487de7b2b37df6c1f783192b7b67
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_6hr.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_6hr.json'.
SHA256 hash of downloaded file: 13a133c9003d035eac652ef967aa89c0b746bd529e23e5e2a26861a060e31b61
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_day.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_day.json'.
SHA256 hash of downloaded file: 7b283897583cf443ebf44b9492e0e4214330927549f6e977578e7686a76e6370
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_mon.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_mon.json'.
SHA256 hash of downloaded file: ad3b9822376c3637aa63609f3d2851ebf703a17ba443fc7e6f2d2f2919e13b57
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Downloading data from 'https://raw.githubusercontent.com/WCRP-CORDEX/cordex-cmip6-cmor-tables/main/Tables/CORDEX-CMIP6_fx.json' to file '/home/runner/.wcrp_metadata/cordex-cmip6-cmor-tables/CORDEX-CMIP6_fx.json'.
SHA256 hash of downloaded file: 82c82a16a8258a901144f484ecd13893ef39480acfdf1967e0737a0c93dba48b
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:08Z
cf:1.11
http://cfconventions.org/Data/cf-conventions/cf-conventions-1.11/cf-conventions.html
--------------------------------------------------------------------------------
Corrective Actions
orog_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_fx.nc has 1 potential issue
Warnings
--------------------------------------------------------------------------------
§7.1 Cell Boundaries
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* The Boundary variables 'vertices_lat' should not have the attributes: '['units', 'missing_value', '_FillValue']'
* The Boundary variables 'vertices_lon' should not have the attributes: '['units', 'missing_value', '_FillValue']'
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:08Z
wcrp_cordex_cmip6:1.0
--------------------------------------------------------------------------------
All tests passed!
Example 2: Monthly Aggregated Data (mon) - Temperature#
This example demonstrates CMORization of monthly averaged data. We use 2-meter temperature (tas), a standard meteorological variable that’s typically provided as monthly means in climate archives. The CMORization process ensures proper scaling, dimension ordering, and CF convention compliance:
f = test_cmorizer_mon()
f
/tmp/ipykernel_3516/2886418336.py:54: DeprecationWarning: 'CORDEX_domain' keyword is deprecated, please use the 'domain_id' keyword instead
filename = cmor.cmorize_variable(
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1035: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
unused_keys = set(attribute.keys()) - set(inverted)
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1036: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
for key, value in attribute.items():
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1044: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
newmap.update({key: attribute[key] for key in unused_keys})
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:635: UserWarning: adding time bounds
warn("adding time bounds")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:426: UserWarning: time units are set to default: days since 1950-01-01T00:00:00
warn(f"time units are set to default: {u}")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/utils.py:339: UserWarning: writing temporary table to /tmp/tmp5nbmlcr1
warn(f"writing temporary table to {filename}")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1035: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
unused_keys = set(attribute.keys()) - set(inverted)
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1036: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
for key, value in attribute.items():
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1044: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
newmap.update({key: attribute[key] for key in unused_keys})
C Traceback:
In function: cmor_values_from_bounds
! called from: cmor_axis
!
!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Warning: The values you provided for axis time are different from those computed from the bounds, which are used for the axis values instead of the user-provided values.
!
! The first value found is at index 0: 18276.000000 will be replaced with 18277.500000 between bounds 18262.000000 and 18293.000000
!
!!!!!!!!!!!!!!!!!!!!!!!!!
'CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/mon/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_mon_200001-200012.nc'
ds = xr.open_dataset(f)
ds
<xarray.Dataset> Size: 22MB
Dimensions: (time: 12, bnds: 2, rlat: 412, rlon: 424,
vertices: 4)
Coordinates:
* time (time) datetime64[ns] 96B 2000-01-16T12:00:00...
* rlat (rlat) float64 3kB -23.38 -23.27 ... 21.73 21.84
* rlon (rlon) float64 3kB -28.38 -28.27 ... 18.05 18.16
lat (rlat, rlon) float64 1MB ...
lon (rlat, rlon) float64 1MB ...
height float64 8B ...
Dimensions without coordinates: bnds, vertices
Data variables:
time_bnds (time, bnds) datetime64[ns] 192B ...
rotated_latitude_longitude int32 4B ...
vertices_lat (rlat, rlon, vertices) float64 6MB ...
vertices_lon (rlat, rlon, vertices) float64 6MB ...
tas (time, rlat, rlon) float32 8MB ...
Attributes: (12/36)
Conventions: CF-1.11
activity_id: DD
contact: gerics-cordex@hereon.de
creation_date: 2026-10-20T12:56:09Z
domain: Europe
domain_id: EUR-12
... ...
title: GERICS REMO2020-2-2 downscaling of ERA5 evaluati...
tracking_id: hdl:21.14103/12d482c5-0075-461a-be17-588a0beb0a00
variable_id: tas
version_realization: v1-r1
license: https://cordex.org/data-access/cordex-cmip6-data...
cmor_version: 3.16.0ds.cf
Coordinates:
CF Axes: * X: ['rlon']
* Y: ['rlat']
Z: ['height']
* T: ['time']
CF Coordinates: longitude: ['lon']
latitude: ['lat']
vertical: ['height']
* time: ['time']
Cell Measures: area, volume: n/a
Standard Names: * grid_latitude: ['rlat']
* grid_longitude: ['rlon']
height: ['height']
latitude: ['lat']
longitude: ['lon']
* time: ['time']
Bounds: n/a
Grid Mappings: n/a
Data Variables:
Cell Measures: area, volume: n/a
Standard Names: air_temperature: ['tas']
Bounds: T: ['time_bnds']
lat: ['vertices_lat']
latitude: ['vertices_lat']
lon: ['vertices_lon']
longitude: ['vertices_lon']
time: ['time_bnds']
Grid Mappings: rotated_latitude_longitude: ['rotated_latitude_longitude']
ds.tas.plot(col="time", col_wrap=4)
<xarray.plot.facetgrid.FacetGrid at 0x7f3403287fe0>
!ncdump -h $f
netcdf tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_mon_200001-200012 {
dimensions:
time = UNLIMITED ; // (12 currently)
rlat = 412 ;
rlon = 424 ;
bnds = 2 ;
vertices = 4 ;
variables:
double time(time) ;
time:bounds = "time_bnds" ;
time:units = "days since 1950-01-01T00:00:00" ;
time:calendar = "proleptic_gregorian" ;
time:axis = "T" ;
time:long_name = "time" ;
time:standard_name = "time" ;
double time_bnds(time, bnds) ;
double rlat(rlat) ;
rlat:units = "degrees" ;
rlat:axis = "Y" ;
rlat:long_name = "latitude in rotated pole grid" ;
rlat:standard_name = "grid_latitude" ;
double rlon(rlon) ;
rlon:units = "degrees" ;
rlon:axis = "X" ;
rlon:long_name = "longitude in rotated pole grid" ;
rlon:standard_name = "grid_longitude" ;
int rotated_latitude_longitude ;
rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ;
rotated_latitude_longitude:grid_north_pole_latitude = 39.25 ;
rotated_latitude_longitude:grid_north_pole_longitude = -162. ;
rotated_latitude_longitude:north_pole_grid_longitude = 0. ;
rotated_latitude_longitude:earth_radius = 6371229. ;
double lat(rlat, rlon) ;
lat:standard_name = "latitude" ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:missing_value = 1.e+20 ;
lat:_FillValue = 1.e+20 ;
lat:bounds = "vertices_lat" ;
double lon(rlat, rlon) ;
lon:standard_name = "longitude" ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:missing_value = 1.e+20 ;
lon:_FillValue = 1.e+20 ;
lon:bounds = "vertices_lon" ;
double vertices_lat(rlat, rlon, vertices) ;
vertices_lat:units = "degrees_north" ;
vertices_lat:missing_value = 1.e+20 ;
vertices_lat:_FillValue = 1.e+20 ;
double vertices_lon(rlat, rlon, vertices) ;
vertices_lon:units = "degrees_east" ;
vertices_lon:missing_value = 1.e+20 ;
vertices_lon:_FillValue = 1.e+20 ;
double height ;
height:units = "m" ;
height:axis = "Z" ;
height:positive = "up" ;
height:long_name = "height" ;
height:standard_name = "height" ;
float tas(time, rlat, rlon) ;
tas:standard_name = "air_temperature" ;
tas:long_name = "Near-Surface Air Temperature" ;
tas:comment = "near-surface (usually, 2 meter) air temperature" ;
tas:units = "K" ;
tas:cell_methods = "area: time: mean" ;
tas:cell_measures = "area: areacella" ;
tas:history = "2026-10-20T12:56:09Z altered by CMOR: Treated scalar dimension: \'height\'." ;
tas:coordinates = "height lat lon" ;
tas:missing_value = 1.e+20f ;
tas:_FillValue = 1.e+20f ;
tas:grid_mapping = "rotated_latitude_longitude" ;
// global attributes:
:Conventions = "CF-1.11" ;
:activity_id = "DD" ;
:contact = "gerics-cordex@hereon.de" ;
:creation_date = "2026-10-20T12:56:09Z" ;
:domain = "Europe" ;
:domain_id = "EUR-12" ;
:driving_experiment = "reanalysis simulation of the recent past" ;
:driving_experiment_id = "evaluation" ;
:driving_institution_id = "ECMWF" ;
:driving_source = "ECMWF Reanalysis v5" ;
:driving_source_id = "ERA5" ;
:driving_variant_label = "r1i1p1f1" ;
:experiment_id = "evaluation" ;
:external_variables = "areacella" ;
:frequency = "mon" ;
:grid = "Rotated-pole latitude-longitude with 0.11 degree grid spacing" ;
:history = "2026-10-20T12:56:09Z ;rewrote data to be consistent with CORDEX-CMIP6 for variable tas found in table mon." ;
:institution = "Climate Service Center Germany, Helmholtz Centre hereon GmbH, Hamburg, Germany" ;
:institution_id = "GERICS" ;
:label = "REMO2020 v2.2" ;
:mip_era = "CMIP6" ;
:product = "model-output" ;
:project_id = "CORDEX-CMIP6" ;
:references = "https://www.remo-rcm.de" ;
:run_variant = "1st realization" ;
:source = "Regional Climate Model REMO, version 2.2, hydrostatic configuration with MACv2 aerosol forcing and Fresh-water Lake model (FLake) (2023)" ;
:source_id = "REMO2020-2-2" ;
:source_type = "ARCM" ;
:table_id = "mon" ;
:table_info = "Name: CORDEX-CMIP6_mon.json; Creation Date:(07 September 2026) MD5:b10b18e683ad5e012613a22c64d9001e" ;
:title = "GERICS REMO2020-2-2 downscaling of ERA5 evaluation for CORDEX-CMIP6 EUR-12" ;
:tracking_id = "hdl:21.14103/12d482c5-0075-461a-be17-588a0beb0a00" ;
:variable_id = "tas" ;
:version_realization = "v1-r1" ;
:license = "https://cordex.org/data-access/cordex-cmip6-data/cordex-cmip6-terms-of-use" ;
:cmor_version = "3.16.0" ;
}
!cfchecks $f
CHECKING NetCDF FILE: CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/mon/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_mon_200001-200012.nc
=====================
Using CF Checker Version 4.1.0
Checking against CF Version CF-1.8
Using Standard Name Table Version 95 (2026-09-16T04:56:46Z)
Using Area Type Table Version 13 (20 March 2025)
Using Standardized Region Name Table Version 5 (12 November 2024)
ERROR: (2.6.1): This netCDF file does not appear to contain CF Convention data.
WARN: (7.1): Boundary var vertices_lat should not have attribute units
WARN: (7.1): Boundary var vertices_lon should not have attribute units
------------------
Checking variable: time
------------------
------------------
Checking variable: time_bnds
------------------
------------------
Checking variable: rlat
------------------
------------------
Checking variable: rlon
------------------
------------------
Checking variable: rotated_latitude_longitude
------------------
------------------
Checking variable: lat
------------------
------------------
Checking variable: lon
------------------
------------------
Checking variable: vertices_lat
------------------
WARN: (7.1): Boundary Variable vertices_lat should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lat should not have missing_value attribute
------------------
Checking variable: vertices_lon
------------------
WARN: (7.1): Boundary Variable vertices_lon should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lon should not have missing_value attribute
------------------
Checking variable: height
------------------
------------------
Checking variable: tas
------------------
INFO: attribute history is being used in a non-standard way
ERRORS detected: 1
WARNINGS given: 6
INFORMATION messages: 1
!compliance-checker --test=cf:1.11 --test=wcrp_cordex_cmip6 $f
Running Compliance Checker on the datasets from: ['CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/mon/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_mon_200001-200012.nc']
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:15Z
cf:1.11
http://cfconventions.org/Data/cf-conventions/cf-conventions-1.11/cf-conventions.html
--------------------------------------------------------------------------------
Corrective Actions
tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_mon_200001-200012.nc has 3 potential issues
Warnings
--------------------------------------------------------------------------------
§3.1.2 Temperature units
* Variable tas has a temperature related standard_name and it is recommended that the units_metadata attribute is present and has one of the values ['temperature: difference', 'temperature: on_scale', 'temperature: unknown']
§4.4 Time Coordinate
* Variable time has a calendar attribute of proleptic_gregorian and it is recommended that the units_metadata attribute is present and has one of the values ['leap_seconds: none', 'leap_seconds: utc', 'leap_seconds: unknown']
§7.1 Cell Boundaries
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* The Boundary variables 'vertices_lat' should not have the attributes: '['units', 'missing_value', '_FillValue']'
* The Boundary variables 'vertices_lon' should not have the attributes: '['units', 'missing_value', '_FillValue']'
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:15Z
wcrp_cordex_cmip6:1.0
--------------------------------------------------------------------------------
All tests passed!
Example 3: Sub-daily Data (1hr, 3hr, 6hr, day) - Temperature#
This example demonstrates the flexibility of the CMORization process for sub-daily data. Starting with hourly temperature data, we show how it can be automatically resampled to various standard time frequencies:
1 hour (1hr): Raw hourly output
3 hours (3hr): Averaged over 3-hour intervals
6 hours (6hr): Averaged over 6-hour intervals
Daily (day): Daily averaged values
The allow_resample=True parameter enables automatic temporal aggregation to match the target CMOR table frequency:
f = test_cmorizer_subdaily("1hr")
f
/tmp/ipykernel_3516/2886418336.py:87: DeprecationWarning: 'CORDEX_domain' keyword is deprecated, please use the 'domain_id' keyword instead
filename = cmor.cmorize_variable(
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1035: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
unused_keys = set(attribute.keys()) - set(inverted)
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1036: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
for key, value in attribute.items():
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1044: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
newmap.update({key: attribute[key] for key in unused_keys})
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:517: UserWarning: resampling input data from H to h
warn(f"resampling input data from {input_freq} to {pd_freq}")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:426: UserWarning: time units are set to default: days since 1950-01-01T00:00:00
warn(f"time units are set to default: {u}")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/utils.py:339: UserWarning: writing temporary table to /tmp/tmpcfduaji9
warn(f"writing temporary table to {filename}")
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1035: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
unused_keys = set(attribute.keys()) - set(inverted)
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1036: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
for key, value in attribute.items():
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1044: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
newmap.update({key: attribute[key] for key in unused_keys})
'CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/1hr/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000.nc'
ds = xr.open_dataset(f)
ds
<xarray.Dataset> Size: 48MB
Dimensions: (rlat: 412, rlon: 424, vertices: 4, time: 49)
Coordinates:
* rlat (rlat) float64 3kB -23.38 -23.27 ... 21.73 21.84
* rlon (rlon) float64 3kB -28.38 -28.27 ... 18.05 18.16
lat (rlat, rlon) float64 1MB ...
lon (rlat, rlon) float64 1MB ...
* time (time) datetime64[ns] 392B 2000-01-01 ... 200...
height float64 8B ...
Dimensions without coordinates: vertices
Data variables:
rotated_latitude_longitude int32 4B ...
vertices_lat (rlat, rlon, vertices) float64 6MB ...
vertices_lon (rlat, rlon, vertices) float64 6MB ...
tas (time, rlat, rlon) float32 34MB ...
Attributes: (12/36)
Conventions: CF-1.11
activity_id: DD
contact: gerics-cordex@hereon.de
creation_date: 2026-10-20T12:56:17Z
domain: Europe
domain_id: EUR-12
... ...
title: GERICS REMO2020-2-2 downscaling of ERA5 evaluati...
tracking_id: hdl:21.14103/dd8e870f-055b-4aa4-b8a2-6a943ca8ef9b
variable_id: tas
version_realization: v1-r1
license: https://cordex.org/data-access/cordex-cmip6-data...
cmor_version: 3.16.0!ncdump -h $f
netcdf tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000 {
dimensions:
time = UNLIMITED ; // (49 currently)
rlat = 412 ;
rlon = 424 ;
bnds = 2 ;
vertices = 4 ;
variables:
double time(time) ;
time:units = "days since 1950-01-01T00:00:00" ;
time:calendar = "proleptic_gregorian" ;
time:axis = "T" ;
time:long_name = "time" ;
time:standard_name = "time" ;
double rlat(rlat) ;
rlat:units = "degrees" ;
rlat:axis = "Y" ;
rlat:long_name = "latitude in rotated pole grid" ;
rlat:standard_name = "grid_latitude" ;
double rlon(rlon) ;
rlon:units = "degrees" ;
rlon:axis = "X" ;
rlon:long_name = "longitude in rotated pole grid" ;
rlon:standard_name = "grid_longitude" ;
int rotated_latitude_longitude ;
rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ;
rotated_latitude_longitude:grid_north_pole_latitude = 39.25 ;
rotated_latitude_longitude:grid_north_pole_longitude = -162. ;
rotated_latitude_longitude:north_pole_grid_longitude = 0. ;
rotated_latitude_longitude:earth_radius = 6371229. ;
double lat(rlat, rlon) ;
lat:standard_name = "latitude" ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:missing_value = 1.e+20 ;
lat:_FillValue = 1.e+20 ;
lat:bounds = "vertices_lat" ;
double lon(rlat, rlon) ;
lon:standard_name = "longitude" ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:missing_value = 1.e+20 ;
lon:_FillValue = 1.e+20 ;
lon:bounds = "vertices_lon" ;
double vertices_lat(rlat, rlon, vertices) ;
vertices_lat:units = "degrees_north" ;
vertices_lat:missing_value = 1.e+20 ;
vertices_lat:_FillValue = 1.e+20 ;
double vertices_lon(rlat, rlon, vertices) ;
vertices_lon:units = "degrees_east" ;
vertices_lon:missing_value = 1.e+20 ;
vertices_lon:_FillValue = 1.e+20 ;
double height ;
height:units = "m" ;
height:axis = "Z" ;
height:positive = "up" ;
height:long_name = "height" ;
height:standard_name = "height" ;
float tas(time, rlat, rlon) ;
tas:standard_name = "air_temperature" ;
tas:long_name = "Near-Surface Air Temperature" ;
tas:comment = "near-surface (usually, 2 meter) air temperature" ;
tas:units = "K" ;
tas:cell_methods = "area: mean time: point" ;
tas:cell_measures = "area: areacella" ;
tas:history = "2026-10-20T12:56:17Z altered by CMOR: Treated scalar dimension: \'height\'." ;
tas:coordinates = "height lat lon" ;
tas:missing_value = 1.e+20f ;
tas:_FillValue = 1.e+20f ;
tas:grid_mapping = "rotated_latitude_longitude" ;
// global attributes:
:Conventions = "CF-1.11" ;
:activity_id = "DD" ;
:contact = "gerics-cordex@hereon.de" ;
:creation_date = "2026-10-20T12:56:17Z" ;
:domain = "Europe" ;
:domain_id = "EUR-12" ;
:driving_experiment = "reanalysis simulation of the recent past" ;
:driving_experiment_id = "evaluation" ;
:driving_institution_id = "ECMWF" ;
:driving_source = "ECMWF Reanalysis v5" ;
:driving_source_id = "ERA5" ;
:driving_variant_label = "r1i1p1f1" ;
:experiment_id = "evaluation" ;
:external_variables = "areacella" ;
:frequency = "1hr" ;
:grid = "Rotated-pole latitude-longitude with 0.11 degree grid spacing" ;
:history = "2026-10-20T12:56:17Z ;rewrote data to be consistent with CORDEX-CMIP6 for variable tas found in table 1hr." ;
:institution = "Climate Service Center Germany, Helmholtz Centre hereon GmbH, Hamburg, Germany" ;
:institution_id = "GERICS" ;
:label = "REMO2020 v2.2" ;
:mip_era = "CMIP6" ;
:product = "model-output" ;
:project_id = "CORDEX-CMIP6" ;
:references = "https://www.remo-rcm.de" ;
:run_variant = "1st realization" ;
:source = "Regional Climate Model REMO, version 2.2, hydrostatic configuration with MACv2 aerosol forcing and Fresh-water Lake model (FLake) (2023)" ;
:source_id = "REMO2020-2-2" ;
:source_type = "ARCM" ;
:table_id = "1hr" ;
:table_info = "Name: CORDEX-CMIP6_1hr.json; Creation Date:(07 September 2026) MD5:beebe3fa80cf01dc01cb22103d724c2a" ;
:title = "GERICS REMO2020-2-2 downscaling of ERA5 evaluation for CORDEX-CMIP6 EUR-12" ;
:tracking_id = "hdl:21.14103/dd8e870f-055b-4aa4-b8a2-6a943ca8ef9b" ;
:variable_id = "tas" ;
:version_realization = "v1-r1" ;
:license = "https://cordex.org/data-access/cordex-cmip6-data/cordex-cmip6-terms-of-use" ;
:cmor_version = "3.16.0" ;
}
!cfchecks $f
CHECKING NetCDF FILE: CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/1hr/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000.nc
=====================
Using CF Checker Version 4.1.0
Checking against CF Version CF-1.8
Using Standard Name Table Version 95 (2026-09-16T04:56:46Z)
Using Area Type Table Version 13 (20 March 2025)
Using Standardized Region Name Table Version 5 (12 November 2024)
ERROR: (2.6.1): This netCDF file does not appear to contain CF Convention data.
WARN: (7.1): Boundary var vertices_lat should not have attribute units
WARN: (7.1): Boundary var vertices_lon should not have attribute units
------------------
Checking variable: time
------------------
------------------
Checking variable: rlat
------------------
------------------
Checking variable: rlon
------------------
------------------
Checking variable: rotated_latitude_longitude
------------------
------------------
Checking variable: lat
------------------
------------------
Checking variable: lon
------------------
------------------
Checking variable: vertices_lat
------------------
WARN: (7.1): Boundary Variable vertices_lat should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lat should not have missing_value attribute
------------------
Checking variable: vertices_lon
------------------
WARN: (7.1): Boundary Variable vertices_lon should not have _FillValue attribute
WARN: (7.1): Boundary Variable vertices_lon should not have missing_value attribute
------------------
Checking variable: height
------------------
------------------
Checking variable: tas
------------------
INFO: attribute history is being used in a non-standard way
ERRORS detected: 1
WARNINGS given: 6
INFORMATION messages: 1
!compliance-checker --test=cf:1.11 --test=wcrp_cordex_cmip6 $f
Running Compliance Checker on the datasets from: ['CORDEX/CORDEX-CMIP6/DD/EUR-12/GERICS/ERA5/evaluation/r1i1p1f1/REMO2020-2-2/v1-r1/1hr/tas/v20261020/tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000.nc']
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:20Z
cf:1.11
http://cfconventions.org/Data/cf-conventions/cf-conventions-1.11/cf-conventions.html
--------------------------------------------------------------------------------
Corrective Actions
tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000.nc has 3 potential issues
Warnings
--------------------------------------------------------------------------------
§3.1.2 Temperature units
* Variable tas has a temperature related standard_name and it is recommended that the units_metadata attribute is present and has one of the values ['temperature: difference', 'temperature: on_scale', 'temperature: unknown']
§4.4 Time Coordinate
* Variable time has a calendar attribute of proleptic_gregorian and it is recommended that the units_metadata attribute is present and has one of the values ['leap_seconds: none', 'leap_seconds: utc', 'leap_seconds: unknown']
§7.1 Cell Boundaries
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lat and parent variable lat have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* Bounds variable vertices_lon and parent variable lon have the following matching attributes ['units']. It is recommended that only the parent variable of the bounds variable contains these attributes
* The Boundary variables 'vertices_lat' should not have the attributes: '['units', 'missing_value', '_FillValue']'
* The Boundary variables 'vertices_lon' should not have the attributes: '['units', 'missing_value', '_FillValue']'
--------------------------------------------------------------------------------
IOOS Compliance Checker Report
Version 6.1.0
Report generated 2026-10-20T12:56:20Z
wcrp_cordex_cmip6:1.0
--------------------------------------------------------------------------------
Corrective Actions
tas_EUR-12_ERA5_evaluation_r1i1p1f1_GERICS_REMO2020-2-2_v1-r1_1hr_200001010000-200001030000.nc has 1 potential issue
Recommended
--------------------------------------------------------------------------------
[CDXT001] Time Chunking
* File chunking recommendations: '1' full simulation year is expected in the data file for frequency '1hr'. The last timestep conflicts with this recommendation ('2000-12-31 23:00:00'): '2000-01-03 00:00:00'.
# Demonstration of automatic resampling: Starting from hourly data,
# the CMORization process automatically aggregates to daily frequency
# based on the CMOR table definition
f = test_cmorizer_subdaily("day")
f
/tmp/ipykernel_3516/2886418336.py:87: DeprecationWarning: 'CORDEX_domain' keyword is deprecated, please use the 'domain_id' keyword instead
filename = cmor.cmorize_variable(
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1035: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
unused_keys = set(attribute.keys()) - set(inverted)
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1036: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
for key, value in attribute.items():
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cf_xarray/accessor.py:1044: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
newmap.update({key: attribute[key] for key in unused_keys})
/home/runner/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:517: UserWarning: resampling input data from H to D
warn(f"resampling input data from {input_freq} to {pd_freq}")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[25], line 4
1 # Demonstration of automatic resampling: Starting from hourly data,
2 # the CMORization process automatically aggregates to daily frequency
3 # based on the CMOR table definition
----> 4 f = test_cmorizer_subdaily("day")
5 f
Cell In[4], line 87, in test_cmorizer_subdaily(table)
83 str
84 Path to the cmorized netCDF file
85 """
86 ds = cx.tutorial.open_dataset("remo_EUR-11_TEMP2_1hr")
---> 87 filename = cmor.cmorize_variable(
88 ds,
89 "tas",
90 mapping_table={"tas": {"varname": "TEMP2"}},
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:813, in cmorize_variable(ds, out_name, cmor_table, dataset_table, mapping_table, grids_table, inpath, replace_coords, allow_units_convert, allow_resample, input_freq, domain_id, crop, time_units, rewrite_time_axis, outpath, **kwargs)
810 if outpath:
811 dataset_table["outpath"] = outpath
--> 813 ds_prep = prepare_variable(
814 ds,
815 out_name,
816 cmor_table,
817 domain_id=domain_id,
818 mapping_table=mapping_table,
819 replace_coords=replace_coords,
820 input_freq=input_freq,
821 rewrite_time_axis=rewrite_time_axis,
822 time_units=time_units,
823 allow_resample=allow_resample,
824 allow_units_convert=allow_units_convert,
825 crop=crop,
826 **kwargs,
827 )
829 return cmorize_cmor(
830 ds_prep, out_name, cmor_table, dataset_table, grids_table, inpath
831 )
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:631, in prepare_variable(ds, out_name, cmor_table, mapping_table, replace_coords, allow_units_convert, allow_resample, input_freq, domain_id, time_units, rewrite_time_axis, use_cftime, squeeze, crop, guess_coord_axis)
629 var_ds = var_ds.convert_calendar(ds.time.dt.calendar, use_cftime=True)
630 if allow_resample is True:
--> 631 var_ds = _adjust_frequency(var_ds, cf_freq, input_freq, time_cell_method)
632 if rewrite_time_axis is True:
633 var_ds = _rewrite_time_axis(var_ds, cf_freq)
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:518, in _adjust_frequency(ds, cf_freq, input_freq, time_cell_method)
516 if pd_freq != input_freq:
517 warn(f"resampling input data from {input_freq} to {pd_freq}")
--> 518 resample = _resample(
519 ds, pd_freq, time_cell_method=time_cell_method, **options["resample_kwargs"]
520 )
521 return resample
522 return ds
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/cordex/cmor/cmor.py:97, in _resample(ds, time, time_cell_method, label, time_offset, **kwargs)
95 mean_kwargs["engine"] = "flox"
96 mean_kwargs["method"] = default_flox_method
---> 97 return ds.resample(time=time, label=label, offset=loffset, **kwargs).mean(
98 **mean_kwargs
99 )
100 else:
101 raise Exception(f"unknown time_cell_method: {time_cell_method}")
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/_aggregations.py:5935, in DatasetResampleAggregations.mean(self, dim, skipna, keep_attrs, **kwargs)
5925 return self._flox_reduce(
5926 func="mean",
5927 dim=dim,
(...) 5932 **kwargs,
5933 )
5934 else:
-> 5935 out = self.reduce(
5936 duck_array_ops.mean,
5937 dim=dim,
5938 skipna=skipna,
5939 numeric_only=True,
5940 keep_attrs=keep_attrs,
5941 **kwargs,
5942 )
5943 return out
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/resample.py:499, in DatasetResample.reduce(self, func, dim, axis, keep_attrs, shortcut, **kwargs)
465 def reduce(
466 self,
467 func: Callable[..., Any],
(...) 473 **kwargs: Any,
474 ) -> Dataset:
475 """Reduce the items in this group by applying `func` along the
476 pre-defined resampling dimension.
477
(...) 497 removed.
498 """
--> 499 return super().reduce(
500 func=func,
501 dim=dim,
502 axis=axis,
503 keep_attrs=keep_attrs,
504 shortcut=shortcut,
505 **kwargs,
506 )
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/groupby.py:1966, in DatasetGroupByBase.reduce(self, func, dim, axis, keep_attrs, shortcut, **kwargs)
1955 return ds.reduce(
1956 func=func,
1957 dim=dim,
(...) 1961 **kwargs,
1962 )
1964 check_reduce_dims(dim, self.dims)
-> 1966 return self.map(reduce_dataset)
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/resample.py:436, in DatasetResample.map(self, func, args, shortcut, **kwargs)
434 # ignore shortcut if set (for now)
435 applied = (func(ds, *args, **kwargs) for ds in self._iter_grouped())
--> 436 combined = self._combine(applied)
438 # If the aggregation function didn't drop the original resampling
439 # dimension, then we need to do so before we can rename the proxy
440 # dimension we used.
441 if self._dim in combined.coords:
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/groupby.py:1873, in DatasetGroupByBase._combine(self, applied)
1871 def _combine(self, applied):
1872 """Recombine the applied objects like the original."""
-> 1873 applied_example, applied = peek_at(applied)
1874 dim, positions = self._infer_concat_args(applied_example)
1875 combined = concat(
1876 applied,
1877 dim,
(...) 1881 join="outer",
1882 )
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/utils.py:287, in peek_at(iterable)
283 """Returns the first value from iterable, as well as a new iterator with
284 the same content as the original iterable
285 """
286 gen = iter(iterable)
--> 287 peek = next(gen)
288 return peek, itertools.chain([peek], gen)
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/resample.py:435, in <genexpr>(.0)
405 """Apply a function over each Dataset in the groups generated for
406 resampling and concatenate them together into a new Dataset.
407
(...) 432 The result of splitting, applying and combining this dataset.
433 """
434 # ignore shortcut if set (for now)
--> 435 applied = (func(ds, *args, **kwargs) for ds in self._iter_grouped())
436 combined = self._combine(applied)
438 # If the aggregation function didn't drop the original resampling
439 # dimension, then we need to do so before we can rename the proxy
440 # dimension we used.
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/groupby.py:1955, in DatasetGroupByBase.reduce.<locals>.reduce_dataset(ds)
1954 def reduce_dataset(ds: Dataset) -> Dataset:
-> 1955 return ds.reduce(
1956 func=func,
1957 dim=dim,
1958 axis=axis,
1959 keep_attrs=keep_attrs,
1960 keepdims=False,
1961 **kwargs,
1962 )
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/dataset.py:6975, in Dataset.reduce(self, func, dim, keep_attrs, keepdims, numeric_only, **kwargs)
6971 None
6972 if len(reduce_dims) == var.ndim and var.ndim != 1
6973 else reduce_dims
6974 )
-> 6975 variables[name] = var.reduce(
6976 func,
6977 dim=reduce_maybe_single,
6978 keep_attrs=keep_attrs,
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/variable.py:1792, in Variable.reduce(self, func, dim, axis, keep_attrs, keepdims, **kwargs)
1785 keep_attrs_ = (
1786 _get_keep_attrs(default=True) if keep_attrs is None else keep_attrs
1787 )
1789 # Note that the call order for Variable.mean is
1790 # Variable.mean -> NamedArray.mean -> Variable.reduce
1791 # -> NamedArray.reduce
-> 1792 result = super().reduce(
1793 func=func, dim=dim, axis=axis, keepdims=keepdims, **kwargs
1794 )
1796 # return Variable always to support IndexVariable
1797 return Variable(
1798 result.dims, result._data, attrs=result._attrs if keep_attrs_ else None
1799 )
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/namedarray/core.py:930, in NamedArray.reduce(self, func, dim, axis, keepdims, **kwargs)
928 data = func(self.data, axis=axis, **kwargs)
929 else:
--> 930 data = func(self.data, **kwargs)
932 if getattr(data, "shape", ()) == self.shape:
933 dims = self.dims
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/duck_array_ops.py:811, in mean(array, axis, skipna, **kwargs)
809 return _to_pytimedelta(mean_timedeltas, unit="us") + offset
810 else:
--> 811 return _mean(array, axis=axis, skipna=skipna, **kwargs)
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/xarray/core/duck_array_ops.py:563, in _create_nan_agg_method.<locals>.f(values, axis, skipna, **kwargs)
561 with warnings.catch_warnings():
562 warnings.filterwarnings("ignore", "All-NaN slice encountered")
--> 563 return func(values, axis=axis, **kwargs)
564 except AttributeError:
565 if not is_duck_dask_array(values):
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/numpy/_core/fromnumeric.py:3862, in mean(a, axis, dtype, out, keepdims, where)
3859 else:
3860 return mean(axis=axis, dtype=dtype, out=out, **kwargs)
-> 3862 return _methods._mean(a, axis=axis, dtype=dtype,
3863 out=out, **kwargs)
File ~/micromamba/envs/cmor-examples/lib/python3.12/site-packages/numpy/_core/_methods.py:132, in _mean(a, axis, dtype, out, keepdims, where)
129 dtype = mu.dtype('f4')
130 is_float16_result = True
--> 132 ret = umr_sum(arr, axis, dtype, out, keepdims, where=where)
133 if isinstance(ret, mu.ndarray):
134 ret = um.true_divide(
135 ret, rcount, out=ret, casting='unsafe', subok=False)
TypeError: the resolved dtypes are not compatible with add.reduce. Resolved (dtype('S1'), dtype('S1'), dtype('S2'))
ds = xr.open_dataset(f)
ds
ds.tas.plot(col="time")
!ncdump -h $f
!cfchecks $f
!compliance-checker --test=cf:1.11 --test=wcrp_cordex_cmip6 $f