Auto recipe store example¶
Shows the read-only auto store. It exposes registered fixes as one-step recipes.
In [1]:
Copied!
import numpy as np
import woodpecker
from woodpecker.stores import AutoRecipeStore
from woodpecker.testing import make_cmip6
import numpy as np
import woodpecker
from woodpecker.stores import AutoRecipeStore
from woodpecker.testing import make_cmip6
Create a CMIP6-like dataset where tas uses Celsius units.
In [2]:
Copied!
dataset = make_cmip6(overrides={"units": "degC"}, seed=7)
original_values = dataset["tas"].values.copy()
dataset
dataset = make_cmip6(overrides={"units": "degC"}, seed=7)
original_values = dataset["tas"].values.copy()
dataset
Out[2]:
<xarray.Dataset> Size: 32kB
Dimensions: (time: 12, lat: 18, lon: 36)
Coordinates:
* time (time) datetime64[s] 96B 2000-01-01 2000-02-01 ... 2000-12-01
* lat (lat) float64 144B -85.0 -75.0 -65.0 -55.0 ... 55.0 65.0 75.0 85.0
* lon (lon) float64 288B 0.0 10.0 20.0 30.0 ... 320.0 330.0 340.0 350.0
Data variables:
tas (time, lat, lon) float32 31kB 251.3 251.4 251.5 ... 249.7 249.8
Attributes: (12/15)
project_id: CMIP6
dataset_id: CMIP6.CMIP.MOHC.HadGEM3-GC31-LL.historical.r1i1p1f3....
source_file: CMIP6.CMIP.MOHC.HadGEM3-GC31-LL.historical.r1i1p1f3....
source_id: HadGEM3-GC31-LL
source_name: HadGEM3-GC31-LL
mip_era: CMIP6
... ...
variable_id: tas
table_id: Amon
units: degC
frequency: mon
grid_label: gn
nominal_resolution: 250 kmThe auto store lists registered fixes as generated recipe ids.
In [3]:
Copied!
store = AutoRecipeStore()
[recipe.id for recipe in store.list_recipes() if recipe.id.startswith("woodpecker.")]
store = AutoRecipeStore()
[recipe.id for recipe in store.list_recipes() if recipe.id.startswith("woodpecker.")]
Out[3]:
['woodpecker.normalize_tas_units_to_kelvin', 'woodpecker.merge_equivalent_dimensions', 'woodpecker.ensure_latitude_is_increasing', 'woodpecker.rename_variables', 'woodpecker.promote_missing_dimension_coords', 'woodpecker.remove_coordinate_fill_value_encodings', 'woodpecker.set_coordinate_variables', 'woodpecker.convert_units', 'woodpecker.normalize_longitude_convention', 'woodpecker.drop_variables']
Lookup returns generated recipes whose fix matches() method applies to the dataset.
In [4]:
Copied!
matched_plans = store.lookup(dataset)
[recipe.id for recipe in matched_plans]
matched_plans = store.lookup(dataset)
[recipe.id for recipe in matched_plans]
Out[4]:
['woodpecker.normalize_tas_units_to_kelvin', 'xmip.broadcast_lon_lat', 'xmip.rename_cmip6_axes']
Use the generated recipe through the public recipe API.
In [5]:
Copied!
recipe_id = "woodpecker.normalize_tas_units_to_kelvin"
findings = woodpecker.recipe.check(dataset, woodpecker.recipe.auto(recipe_id))
findings.fix_ids
recipe_id = "woodpecker.normalize_tas_units_to_kelvin"
findings = woodpecker.recipe.check(dataset, woodpecker.recipe.auto(recipe_id))
findings.fix_ids
Out[5]:
('woodpecker.normalize_tas_units_to_kelvin',)
In [6]:
Copied!
write = woodpecker.recipe.apply(dataset, woodpecker.recipe.auto(recipe_id), dry_run=False)
(
write.stats,
dataset["tas"].attrs["units"],
np.allclose(dataset["tas"].values, original_values + 273.15),
)
write = woodpecker.recipe.apply(dataset, woodpecker.recipe.auto(recipe_id), dry_run=False)
(
write.stats,
dataset["tas"].attrs["units"],
np.allclose(dataset["tas"].values, original_values + 273.15),
)
Out[6]:
({'attempted': 1,
'changed': 1,
'persist_attempted': 1,
'persisted': 1,
'persist_failed': 0,
'preview': [{'path': 'HadGEM3-GC31-LL',
'fix_id': 'woodpecker.normalize_tas_units_to_kelvin',
'name': 'Normalize tas-like units to Kelvin',
'labels': ['risk.value_transformation'],
'label_titles': ['careful: value transformation'],
'label_metadata': [{'id': 'risk.value_transformation',
'title': 'careful: value transformation',
'description': 'Transforms data or coordinate values.',
'category': 'risk-medium'}],
'changed': True}]},
'K',
True)