climate_ref_core.cmip6_to_cmip7
#
CMIP6 to CMIP7 format converter.
This module provides utilities to convert CMIP6 xarray datasets to CMIP7 format, following the CMIP7 Global Attributes V1.0 specification (DOI: 10.5281/zenodo.17250297).
Variable branding mappings are sourced from the CMIP7 Data Request (DReq v1.2.2.3) via a bundled JSON subset. Regenerate with:
python scripts/extract-data-request-mappings.py
The variable_id and table_id attributes are used to map the CMIP6 variable to its CMIP7 equivalent, and to determine the appropriate branding suffix and realm for the CMIP7 format. Grid information is not converted so the grid_labels may not be valid for CMIP7.
BrandingSuffix
dataclass
#
CMIP7 branding suffix components.
Format:
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
CMIP7Metadata
dataclass
#
CMIP7 metadata attributes for conversion.
This captures the additional/modified attributes needed for CMIP7 format. Based on CMIP7 Global Attributes V1.0 (DOI: 10.5281/zenodo.17250297).
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
DReqVariableMapping
#
A single CMIP6-to-CMIP7 variable mapping from the Data Request.
Each instance represents one row in the DReq Variables JSON file, capturing the CMIP6 compound name, its CMIP7 equivalent, and the branding/realm metadata needed for format conversion.
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
from_dict(data)
classmethod
#
Deserialise from a plain dict (e.g. loaded from JSON).
convert_cmip6_dataset(ds, inplace=False)
#
Convert a CMIP6 xarray Dataset to CMIP7 format in-memory.
This uses the cmip6 compound name (table_id.variable_id) to look up the appropriate CMIP7 branding suffix and realm from the Data Request mappings. It then updates the global attributes according to the CMIP7 Global Attributes.
This doesn't modify the values or coordinates, but it does add a "cmip6_compound_name" attribute for reference. This may not be a fully valid CMIP7 dataset due to the grid names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
The CMIP6 xarray Dataset to convert |
required |
inplace
|
bool
|
If True, modify the dataset in place; otherwise return a copy |
False
|
Returns:
| Type | Description |
|---|---|
Dataset
|
The converted CMIP7-style dataset |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
convert_cmip6_to_cmip7_attrs(cmip6_attrs)
#
Convert CMIP6 global attributes to CMIP7 format.
Based on CMIP7 Global Attributes V1.0 (DOI: 10.5281/zenodo.17250297).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cmip6_attrs
|
dict[str, Any]
|
Dictionary of CMIP6 global attributes. Must contain |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary of CMIP7 global attributes |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | |
convert_variant_index(value, prefix)
#
Convert CMIP6 numeric variant index to CMIP7 string format.
In CMIP6, indices like realization_index were integers (e.g., 1). In CMIP7, they are strings with a prefix (e.g., "r1").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
int | str
|
The index value (int, numpy integer, or str) |
required |
prefix
|
str
|
The prefix to use ("r", "i", "p", or "f") |
required |
Returns:
| Type | Description |
|---|---|
str
|
The CMIP7 format index (e.g., "r1", "i1", "p1", "f1") |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
create_cmip7_filename(attrs, time_range=None)
#
Create a CMIP7 filename from attributes.
The CMIP7 filename follows the MIP-DRS7 specification (V1.0):
Note that variable_id in CMIP7 may differ from CMIP6. For example,
the CMIP6 "tasmax" variable maps to "tas" in CMIP7 because the "max" part
is now captured in the branding suffix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attrs
|
dict[str, Any]
|
Dictionary containing CMIP7 attributes |
required |
time_range
|
str | None
|
Optional time range string (e.g., "190001-190912"). Format depends on frequency: "YYYY" for yearly, "YYYYMM" for monthly, "YYYYMMDD" for daily. Omit for fixed/time-independent variables. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The CMIP7 filename |
Examples:
>>> attrs = {
... "variable_id": "tas",
... "branding_suffix": "tavg-h2m-hxy-u",
... "frequency": "mon",
... "region": "glb",
... "grid_label": "g13s",
... "source_id": "CanESM6-MR",
... "experiment_id": "historical",
... "variant_label": "r2i1p1f1",
... }
>>> create_cmip7_filename(attrs, "190001-190912")
'tas_tavg-h2m-hxy-u_mon_glb_g13s_CanESM6-MR_historical_r2i1p1f1_190001-190912.nc'
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
create_cmip7_path(attrs, version=None)
#
Create a CMIP7 directory path from attributes.
The CMIP7 path follows the MIP-DRS7 specification (V1.0):
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attrs
|
dict[str, Any]
|
Dictionary containing CMIP7 attributes |
required |
version
|
str | None
|
Optional version string (e.g., "v20250622"). If not provided, uses attrs["version"] or defaults to "v1". |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The CMIP7 directory path |
Examples:
>>> attrs = {
... "drs_specs": "MIP-DRS7",
... "mip_era": "CMIP7",
... "activity_id": "CMIP",
... "institution_id": "CCCma",
... "source_id": "CanESM6-MR",
... "experiment_id": "historical",
... "variant_label": "r2i1p1f1",
... "region": "glb",
... "frequency": "mon",
... "variable_id": "tas",
... "branding_suffix": "tavg-h2m-hxy-u",
... "grid_label": "g13s",
... }
>>> create_cmip7_path(attrs, "v20250622")
'MIP-DRS7/CMIP7/CMIP/CCCma/CanESM6-MR/historical/r2i1p1f1/glb/mon/tas/tavg-h2m-hxy-u/g13s/v20250622'
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
format_cmip7_time_range(ds, frequency)
#
Format a CMIP7 time range string from a dataset's time coordinate.
Per the MIP-DRS7 spec, monthly data uses YYYYMM-YYYYMM format.
Fixed-frequency ("fx") data has no time range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
xarray Dataset with a |
required |
frequency
|
str
|
Frequency string (e.g., |
required |
Returns:
| Type | Description |
|---|---|
str or None
|
Formatted time range string, or |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
get_branding_suffix(table_id, variable_id)
#
Determine the CMIP7 branding suffix for a variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_id
|
str
|
CMIP6 table ID (e.g., "Amon", "Omon") |
required |
variable_id
|
str
|
CMIP6 variable ID (e.g., "tas", "pr") |
required |
Returns:
| Type | Description |
|---|---|
BrandingSuffix
|
The branding suffix components |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the variable is not found in the Data Request mappings. |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
get_cmip7_compound_name(table_id, variable_id)
#
Get the full CMIP7 compound name for a CMIP6 variable.
The CMIP7 compound name has the format:
<realm>.<variable_id>.<branding_suffix>.<frequency>.<region>
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_id
|
str
|
CMIP6 table identifier (e.g., "Amon") |
required |
variable_id
|
str
|
CMIP6 variable ID (e.g., "tas") |
required |
Returns:
| Type | Description |
|---|---|
str
|
The CMIP7 compound name. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the variable is not found in the Data Request mappings. |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
get_dreq_entry(table_id, variable_id)
#
Look up a variable in the Data Request by compound name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_id
|
str
|
CMIP6 table identifier (e.g., "Amon") |
required |
variable_id
|
str
|
CMIP6 variable ID (e.g., "tas") |
required |
Returns:
| Type | Description |
|---|---|
DReqVariableMapping
|
The DReq variable entry. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the compound name is not found in the Data Request mappings. |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
get_frequency_from_table(table_id)
#
Extract frequency from CMIP6 table_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_id
|
str
|
CMIP6 table identifier (e.g., "Amon", "Oday", "3hr") |
required |
Returns:
| Type | Description |
|---|---|
str
|
Frequency string (e.g., "mon", "day", "3hr") |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
get_realm(table_id, variable_id)
#
Get the CMIP7 realm for a CMIP6 variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_id
|
str
|
CMIP6 table identifier (e.g., "Amon", "Omon") |
required |
variable_id
|
str
|
CMIP6 variable ID (e.g., "tas", "tos") |
required |
Returns:
| Type | Description |
|---|---|
str
|
CMIP7 realm (e.g., "atmos", "ocean", "land") |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the variable is not found in the Data Request mappings. |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
parse_variant_label(variant_label)
#
Parse a CMIP6 variant label into its component indexes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variant_label
|
str
|
Variant label string (e.g., "r1i1p1f1", "r3i2p4f5") |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary with keys |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the variant label does not match the expected pattern. |
Source code in packages/climate-ref-core/src/climate_ref_core/cmip6_to_cmip7.py
suppress_bounds_coordinates(ds)
#
Prevent xarray from adding spurious coordinates attributes to bounds variables.
When a dataset contains scalar coordinates (e.g. height),
xarray's CF encoder adds a coordinates attribute to every variable,
including bounds variables like time_bnds.
Call this on a dataset before :meth:xarray.Dataset.to_netcdf.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
The dataset about to be written. Modified in place. |
required |
Returns:
| Type | Description |
|---|---|
Dataset
|
The same dataset, for chaining. |