geoips.utils.types package#
Submodules#
geoips.utils.types.converter_registry module#
Generalised bidirectional type-converter registry.
TypeConverterRegistry stores one-way converters keyed by
(source_type, target_type) tuples and dispatches with
priority-matching (exact type, then isinstance MRO-ordered).
It is independent of DataTreeDitto so that both the tree-storage
layer and the plugin-lifecycle hooks can share the same converters.
- class geoips.utils.types.converter_registry.TypeConverterRegistry[source]#
Bases:
objectBidirectional type converter registry with priority dispatch.
Stores one-way (source → target) converters and dispatches calls using exact-type matching first, falling back to
isinstance-based matching with MRO ordering (most specific registered type wins).A module-level singleton
converter_registryis created at import time for use throughout the framework.Examples
>>> registry = TypeConverterRegistry() >>> registry.register(np.ndarray, xr.Dataset, numpy_to_dataset) >>> ds = registry.convert(np.array([1, 2, 3]), xr.Dataset) >>> isinstance(ds, xr.Dataset) True
- can_convert(obj: Any, target: type) bool[source]#
Return
Trueif a conversion path exists for obj → target.
- convert(obj: Any, target: type, **kwargs: Any) Any[source]#
Convert obj to target using a registered converter.
Matching order:
Exact
type(obj)→ target entry.isinstance-based match, ordered by the object’s Method Resolution Order (MRO) so the most specific registered base class wins. The MRO is the linearized order Python searches an object’s class hierarchy (type(obj).__mro__); see https://docs.python.org/3/howto/mro.html. For example, aMaskedArray(a subclass ofndarray) prefers a registeredMaskedArrayconverter over anndarrayone.
- Parameters:
obj (Any) – Object to convert.
target (type) – Desired target type.
kwargs – Forwarded to the converter function.
- Returns:
Converted object (guaranteed to be an instance of target when a converter is found).
- Return type:
Any
- Raises:
TypeError – If no converter is registered for the requested path.
- register(source: type, target: type, converter: Any) None[source]#
Register a one-way converter from source to target.
- Parameters:
source (type) – Source type.
target (type) – Target type.
converter (callable) –
converter(obj, **kwargs)must return an instance of target.
- register_bidirectional(type_a: type, type_b: type, a_to_b: Any, b_to_a: Any) None[source]#
Register a pair of converters for round-trip conversion.
Convenience wrapper around two
register()calls.- Parameters:
type_a (type) – First type.
type_b (type) – Second type.
a_to_b (callable) – Convert type_a → type_b.
b_to_a (callable) – Convert type_b → type_a.
- property registered_types: dict[type, set[type]]#
{target_type, …}} summary.
- Type:
Return {source_type
geoips.utils.types.converters module#
Pure type-conversion functions and FamilyConversionSpec.
Every converter here is a standalone function with no side effects,
independently testable, and reusable by DataTreeDitto, the
TypeConverterRegistry, and the plugin-lifecycle hooks.
Metadata policy#
_ditto_*keys inattrs— storage-layer metadata used byDataTreeDittofor round-trip recovery (original type, shape, dtype, …)._conv_*keys inattrs— semantic-conversion metadata used by the plugin-lifecycle hooks to record context (e.g. variable ordering, mask presence).
- class geoips.utils.types.converters.FamilyConversionSpec(input_type: type | None = None, input_converter: Callable | None = None, output_type: type | None = None, output_converter: Callable | None = None)[source]#
Bases:
objectDefines the type conversions needed for a single plugin family.
- Parameters:
input_type (type or None) – The type expected by the plugin’s
call()after the input converter has been applied.Nonemeans “no conversion”.input_converter (callable or None) –
converter(dataset) → input_type. Called by_pre_call.output_type (type or None) – The type produced by the plugin’s
call().output_converter (callable or None) –
converter(plugin_result) → xr.Dataset. Called by_post_call.Nonemeans the plugin already returns aDataset.
- input_converter: Callable | None = None#
- input_type: type | None = None#
- output_converter: Callable | None = None#
- output_type: type | None = None#
- geoips.utils.types.converters.dataarray_to_dataset(obj: DataArray, **kwargs: Any) Dataset[source]#
Convert a
DataArrayto aDatasetfor DataTreeDitto storage.- Parameters:
obj (xr.DataArray) –
kwargs (Ignored.) –
- Return type:
xr.Dataset
- geoips.utils.types.converters.dataset_dict_to_dataset(dct: dict[str, xarray.core.dataset.Dataset], **kwargs: Any) Dataset[source]#
Merge a dict of datasets into a single
xr.Dataset.Uses
xarray.mergefor alignment. The dict insertion order is preserved via a_conv_var_orderattribute.- Parameters:
dct (dict[str, xr.Dataset]) –
kwargs (Ignored.) –
- Return type:
xr.Dataset
- geoips.utils.types.converters.dataset_to_dataarray(dataset: Dataset, **kwargs: Any) DataArray[source]#
Recover an
xr.DataArrayfrom a DataArray-originxr.Dataset.- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Return type:
xr.DataArray
- geoips.utils.types.converters.dataset_to_dataset_dict(dataset: Dataset, **kwargs: Any) dict[str, xarray.core.dataset.Dataset][source]#
Split a multi-variable
Datasetinto a dict of single-variable datasets.Keys are the data-variable names; each value is a
Datasetcontaining exactly one data variable (plus shared coordinates).- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Return type:
dict[str, xr.Dataset]
- geoips.utils.types.converters.dataset_to_dict(dataset: Dataset, **kwargs: Any) dict[source]#
Recover a plain
dictfrom a dict-originxr.Dataset.Walks
_ditto_keysto preserve original insertion order.- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Return type:
dict
- geoips.utils.types.converters.dataset_to_list(dataset: Dataset, **kwargs: Any) list[source]#
Recover a list from attrs.
- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Returns:
The stored list value.
- Return type:
list
- geoips.utils.types.converters.dataset_to_masked_array(dataset: Dataset, **kwargs: Any) MaskedArray[source]#
Reconstruct a
numpy.ma.MaskedArrayfrom a dataset.Uses
_conv_mask_varand_conv_fill_valuemetadata written bymasked_array_to_dataset.- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Return type:
np.ma.MaskedArray
- geoips.utils.types.converters.dataset_to_numpy(dataset: Dataset, **kwargs: Any) ndarray[source]#
Extract a numpy array from a dataset produced by
numpy_to_dataset.Uses
_ditto_var_namemetadata to locate the correct data variable; falls back to the first data variable.- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored.) –
- Return type:
np.ndarray
- geoips.utils.types.converters.dataset_vars_to_numpy_list(dataset: Dataset, **kwargs: Any) list[numpy.ndarray][source]#
Extract every data variable as a list of arrays.
Arrays are returned in insertion order (the order they appear when iterating
dataset.data_vars). This is stable for a given dataset but callers that need a specific ordering should sort or filter the list themselves.- Parameters:
dataset (xr.Dataset) –
kwargs (Ignored — future slot for
variablessubset / ordering context.) –
- Returns:
One array per data variable, in insertion order.
- Return type:
list[np.ndarray]
- geoips.utils.types.converters.dict_to_dataset(obj: dict, **kwargs: Any) Dataset[source]#
Convert a plain
dictto anxr.Datasetfor DataTreeDitto storage.Numpy-array values become data variables (each with synthetic dim names of the form
<key>_dim_<i>); scalar values (int,float,str,bool,None) becomeattrsunder a_ditto_attr_<key>namespace; any other value type raisesTypeError. Original insertion order is preserved in_ditto_keys.- Parameters:
obj (dict Dictionary of numpy arrays and/or scalars.) –
kwargs (Ignored.) –
- Return type:
xr.Dataset
- geoips.utils.types.converters.list_to_dataset(obj: list, **kwargs: Any) Dataset[source]#
Store a plain list as attrs in a Dataset.
- Parameters:
obj (list List of any JSON-serializable values (e.g. filenames).) –
kwargs (Ignored.) –
- Returns:
Dataset with
_ditto_list_valuein attrs.- Return type:
xr.Dataset
- geoips.utils.types.converters.masked_array_to_dataset(obj: MaskedArray, name: str = 'data', dims: list[str] | None = None, **kwargs: Any) Dataset[source]#
Convert a
numpy.ma.MaskedArraytoxr.Dataset.Stores the mask as a companion data variable (
{name}_mask) and thefill_valueinattrsso thatdataset_to_masked_arraycan reconstruct the original MaskedArray faithfully.- Parameters:
obj (np.ma.MaskedArray) –
name (str Base data-variable name.) –
dims (list[str] or None) –
kwargs (Ignored.) –
- Return type:
xr.Dataset
- geoips.utils.types.converters.numpy_to_dataset(obj: ndarray, name: str = 'data', dims: list[str] | None = None, **kwargs: Any) Dataset[source]#
Convert a numpy array to an
xr.Datasetwith_ditto_*metadata.- Parameters:
obj (np.ndarray) – Input array (may be a regular ndarray or MaskedArray).
name (str) – Data-variable name in the resulting dataset.
dims (list[str] or None) – Dimension names. Auto-generated (
dim_0,dim_1, …) whenNone.kwargs (Ignored — forward-compatibility slot.) –
- Return type:
xr.Dataset
geoips.utils.types.datatree_converters module#
Converter registration for the shared type-converter registry.
Registers converters for dict, xr.DataArray, np.ndarray,
np.ma.MaskedArray, and list on the shared TypeConverterRegistry
singleton – the live dispatch path used by the plugin-lifecycle hooks and by
DataTreeDitto conversions.
This module contains only wiring – every converter function lives in the
single canonical module geoips.utils.types.converters. This module
imports those functions and registers them.
Registration is idempotent – calling this module twice (e.g. via reload) will not produce duplicate entries.
geoips.utils.types.datatree_ditto module#
DataTreeDitto: a DataTree that auto-converts non-xarray payloads.
Extends xarray.DataTree so that non-xarray objects (numpy arrays, dicts,
etc.) assigned into the tree are converted to Dataset objects on the way in
and recovered to their original type on the way out, using the shared
converter_registry.
- class geoips.utils.types.datatree_ditto.DataTreeDitto(dataset=None, children=None, name=None)[source]#
Bases:
DataTreeA DataTree subclass that automatically converts non-xarray objects to datasets.
DataTreeDitto extends xarray’s DataTree to automatically handle conversion of various data types (numpy arrays, etc.) to xarray Datasets while preserving metadata needed for round-trip conversion back to original types.
Pokemon, the world’s most valuable intellectual property, has a pokemon named “ditto” that duplicates its opponents behavior and structure with only slight difference. This class - DataTreeDitto - behaves like to xarray DataTrees with slight differences to accommodate a wider variety of data types.
Examples
>>> import numpy as np >>> arr = np.array([[1, 2], [3, 4]]) >>> dt = DataTreeDitto(arr) >>> dt.ds.data.values.tolist() [[1, 2], [3, 4]] >>> dt.get_original().tolist() [[1, 2], [3, 4]]
- filter(filterfunc: Callable[[DataTree], bool]) DataTree[source]#
Filter nodes according to a specified condition.
Returns a new tree containing only the nodes in the original tree for which fitlerfunc(node) is True. Will also contain empty nodes at intermediate positions if required to support leaves.
- Parameters:
filterfunc (function) – A function which accepts only one DataTree - the node on which filterfunc will be called.
- Return type:
DataTree
See also
match,pipe,map_over_datasets
- classmethod from_datatree(dt: DataTree) DataTreeDitto[source]#
Convert a plain DataTree to DataTreeDitto recursively.
Public API for converting standard
DataTreeinstances returned by xarray operations back toDataTreeDitto.- Parameters:
dt (DataTree) – DataTree instance to convert.
- Returns:
Converted DataTreeDitto with all children also converted.
- Return type:
- get(key, default=None)[source]#
Mapping-style
get.Dict-origin nodes return the wrapped dict’s value (or default); all other nodes delegate to
DataTree.get. This deliberately does not route through__getitem__so it stays safe for xarray’s internal tree traversal (which callsnode.get(part)).
- get_original(path: str = '.') Any[source]#
Get the original object (before conversion) at the specified path.
- Parameters:
path (str, default ".") – Path to the node. Use “.” for current node, or child names separated by “/” for nested nodes.
- Returns:
Original object if conversion metadata exists, otherwise the dataset. Returns None if the node contains no data.
- Return type:
Any
Notes
Performance and memory behavior depend on the registered converter: some converters duplicate data while others reuse the underlying array via views. The returned object shares shallow-copy semantics with the stored data — modifying mutable elements of the returned object may affect the data inside the tree.
Examples
>>> arr = np.array([1, 2, 3]) >>> dt = DataTreeDitto(arr) >>> original = dt.get_original() >>> original.tolist() [1, 2, 3] >>> dt["child"] = np.array([4, 5, 6]) >>> dt.get_original("child").tolist() [4, 5, 6]
- list_converted_nodes() dict[str, str][source]#
List all nodes that contain converted objects and their original types.
- Returns:
Mapping of node paths to original object type names. Paths use “/” as separator, with “/” representing the root node.
- Return type:
dict of str to str
Examples
>>> dt = DataTreeDitto(np.array([1, 2, 3])) >>> dt["child"] = np.array([4, 5, 6]) >>> converted = dt.list_converted_nodes() >>> "/" in converted True >>> "child" in converted True >>> converted["/"] 'numpy.ndarray'
- map_over_datasets(func: Callable[[...], Any], *args: Any, kwargs: Mapping[str, Any] | None = None) DataTree | tuple[xarray.core.datatree.DataTree, ...][source]#
Map a function over datasets, returning
DataTreeDittooutput.
- match(pattern: str) DataTree[source]#
Return nodes with paths matching pattern.
Uses unix glob-like syntax for pattern-matching.
- Parameters:
pattern (str) – A pattern to match each node path against.
- Return type:
DataTree
See also
filter,pipe,map_over_datasetsExamples
>>> dt = DataTree.from_dict( ... { ... "/a/A": None, ... "/a/B": None, ... "/b/A": None, ... "/b/B": None, ... } ... ) >>> dt.match("*/B") <xarray.DataTree> Group: / ├── Group: /a │ └── Group: /a/B └── Group: /b └── Group: /b/B
- mean(dim=None, *, skipna=None, keep_attrs=None, **kwargs)[source]#
Reduce this tree by mean, returning
DataTreeDittooutput.
- to_datatree() DataTree[source]#
Convert to a standard DataTree with all nodes as xarray objects.
- Returns:
A standard DataTree instance with all converted objects as datasets. Conversion metadata is preserved in dataset attributes.
- Return type:
DataTree
Examples
>>> arr = np.array([1, 2, 3]) >>> dt = DataTreeDitto(arr, name="test") >>> standard_dt = dt.to_datatree() >>> isinstance(standard_dt, DataTree) True >>> standard_dt.ds.data.values.tolist() [1, 2, 3]
geoips.utils.types.datatree_helpers module#
Neutral helpers for flattening xr.DataTree nodes into mutable Datasets.
These helpers previously lived as duplicated methods on plugin base classes
(BaseClassPlugin._to_mutable_dataset) and inside
geoips.utils.types.script_datatree. They have one home now so the
interface-level plugin classes (algorithms, coverage_checkers,
filename_formatters) can share a single implementation without reaching back
into the base plugin class or the scripting module.
The canonical flattener is recursive and runs
normalize_geoips_dataset_coords on the result, matching the behavior the
legacy plugin _pre_call overrides relied on before this refactor.
- geoips.utils.types.datatree_helpers.has_data_vars(node)[source]#
Return whether node or any descendant contains data variables.
- Parameters:
node (xarray.DataTree) – DataTree node to inspect.
- Returns:
Trueif node itself carries data variables, or any of its descendant nodes do.- Return type:
bool
- geoips.utils.types.datatree_helpers.to_mutable_dataset(node)[source]#
Return a mutable
xr.Datasetflattening node and its descendants.DataTree.dsreturns an immutableDatasetView. Plugins that write back into the dataset (e.g.xobj[product_name] = ...) need a mutablexr.Dataset. This helper recursively collects every descendant that carries data variables, merges them into a single mutable Dataset, propagates node attributes, and appliesnormalize_geoips_dataset_coordsso the result matches the GeoIPS coordinate convention legacycall()methods expect.- Parameters:
node (xarray.DataTree) – DataTree node to flatten. May be a reader-style multi-level tree (root attrs-only, sub-children holding each variable group) or a single-level multi-child tree.
- Returns:
A mutable, coord-normalized Dataset merging all data-bearing descendants of node.
attrsare merged with node attrs taking precedence.- Return type:
xarray.Dataset
geoips.utils.types.family_conversions module#
Family-to-converter mappings for the plugin-lifecycle hooks.
Note
These mappings exist purely for backwards compatibility. They let the
DataTree-based order-based procflow drive legacy family-based plugins by
converting the shared DataTree payload into the concrete type each legacy
family expects (and back again). They are keyed by family only and do not
describe per-plugin argument/keyword-argument signatures — those legacy
call-signature bindings live in geoips.utils.types.obp_conduits.
New plugins are expected to be DataTree-native (declare data_tree = True)
and therefore need no entry here. As legacy families are migrated, their
entries should be removed; this module is expected to shrink over time and
is a candidate for eventual deletion.
Each mapping entry is a FamilyConversionSpec that tells the
_pre_call / _post_call hooks what type the plugin’s family
expects as input, what type it returns, and which converter functions
to use for the forward and reverse transformations.
These mappings are imported by the interface-level base classes
(BaseAlgorithmPlugin, BaseOutputFormatterPlugin, …) via
their _family_conversion_map class attribute.
geoips.utils.types.obp_conduits module#
The Order-Based Procflow (OBP) conduit binding registry.
OBP_CONDUITS maps an upstream node’s plugin kind to the
keyword-argument name and extractor a downstream plugin expects. This
previously lived inside class_based_plugin (as _OBP_CONDUITS) and was
reached back into by YamlPluginCallable; it now has one home, so new plugin
kinds are wired in exactly one place.
This registry holds the bespoke, per-kind call-signature bindings for
legacy plugins — i.e. the specific keyword-argument name each legacy plugin
family expects and how to pull that value out of an upstream DataTree node.
It is the companion to geoips.utils.types.family_conversions, which
handles type conversions; this module handles argument wiring. Together
they let the DataTree-based OBP drive legacy plugins.
Like family_conversions, these bindings are a backwards-compatibility
layer: DataTree-native plugins (data_tree = True) consume the DataTree
directly and need no conduit entry, so this registry is expected to shrink as
plugins are migrated. (Originally adapted from @srikanth-kumar’s work.)
- geoips.utils.types.obp_conduits.OBP_CONDUITS: dict[str, dict] = {'algorithm': {'extract': <function _extract_ds>, 'kwarg': 'xarray_obj'}, 'colormapper': {'extract': <function <lambda>>, 'kwarg': 'mpl_colors_info'}, 'coverage_checker': {'extract': <function <lambda>>, 'kwarg': 'coverage'}, 'feature_annotator': {'extract': <function _extract_annotator_spec>, 'kwarg': 'feature_annotator'}, 'filename_formatter': {'extract': <function <lambda>>, 'kwarg': 'output_filenames'}, 'gridline_annotator': {'extract': <function _extract_annotator_spec>, 'kwarg': 'gridline_annotator'}, 'interpolator': {'extract': <function _extract_ds>, 'kwarg': 'xarray_obj'}, 'manual': {'extract': <function _extract_ds>, 'kwarg': 'xarray_obj'}, 'output_formatter': {'extract': <function <lambda>>, 'kwarg': 'output_products'}, 'product': {'extract': <function _extract_product_name>, 'kwarg': 'product_name'}, 'product_default': {'extract': <function _extract_attrs_dict>, 'kwarg': 'product_default_info'}, 'reader': {'extract': <function _extract_ds>, 'kwarg': 'xarray_obj'}, 'sector': {'extract': <function <lambda>>, 'kwarg': 'area_def'}}#
Maps an upstream node’s plugin kind to the downstream kwarg name it feeds and the extractor that pulls the value out of the node. Add a new plugin kind’s wiring here (single location).
geoips.utils.types.partial_lexeme module#
Lightweight helper for treating singular and plural spellings as equivalent.
A drop‑in str subclass that normalizes English nouns so that their singular and plural forms compare as equal, hash to the same key, and work inside Pydantic v2 models. Ignores capitalization.
Examples
>>> from partial_lexeme import Lexeme
>>> Lexeme("reader") == "readers" == Lexeme("readers")
True
>>> {Lexeme("analyses"): 1} == {"analysis": 1}
True
>>> from pydantic import BaseModel
>>> class _Plugin(BaseModel):
>>> kind: Lexeme
>>> interface: Lexeme
>>> model = _Plugin(kind="reader", interface="readers")
>>> assert model.kind == model.interface == "reader"
- class geoips.utils.types.partial_lexeme.Lexeme(value: Any)[source]#
Bases:
strA string that treats singular and plural spellings as equal.
It behaves exactly like a built‑in
strbut overrides equality and hashing to use the canonical singular form. This makes singular and plural spellings interchangeable as dict keys, set members, CLI options, etc.
geoips.utils.types.script_datatree module#
Helpers for OBP-style plugin calls from scripts.
- class geoips.utils.types.script_datatree.RetentionPolicy(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#
Bases:
StrEnum- current_only = 'current_only'#
- keep_all = 'keep_all'#
- metadata_only = 'metadata_only'#
- geoips.utils.types.script_datatree.add_data_step(tree, data, *, step_id, retention_policy=None)[source]#
Attach user-created or user-modified data as a manual script step.
- Parameters:
tree (xarray.DataTree) – Root script DataTree created by
initialize_script_tree.data (xarray.DataTree, DataTreeDitto, xarray.Dataset, xarray.DataArray, or) – convertible object Data to attach as the new manual step.
step_id (str) – Step id for the inserted data.
retention_policy (RetentionPolicy or str, optional) – Retention policy override for the inserted data step.
- Returns:
The same root script DataTree, updated in place and returned for convenient chaining.
- Return type:
xarray.DataTree
- geoips.utils.types.script_datatree.apply_script_retention(tree, current_step_id, retention_policy=None)[source]#
Apply a retention policy to an initialized script DataTree.
- Parameters:
tree (xarray.DataTree) – Root script DataTree created by
initialize_script_tree.current_step_id (str) – Step id for the current result. This step remains intact for all retention policies.
retention_policy (RetentionPolicy or str, optional) – Retention policy to apply. Defaults to the root script DataTree policy.
- Returns:
The same root script DataTree, updated in place and returned for convenient chaining.
- Return type:
xarray.DataTree
- Raises:
ValueError – If tree is not an initialized script DataTree, if current_step_id does not exist, or if the retention policy is invalid.
- geoips.utils.types.script_datatree.attach_plugin_result(tree, step_data, *, step_id=None, plugin_kind, plugin_name=None, start_time=None, end_time=None, retention_policy=None)[source]#
Attach a scripted plugin result to an initialized script DataTree.
This internal helper records one plugin result under the supplied
step_id. Ifstep_idis omitted, the plugin name is used. Duplicate step names are rejected so scripts do not accidentally clobber earlier results.- Parameters:
tree (xarray.DataTree) – Root script DataTree created by
initialize_script_tree.step_data (xarray.DataTree, DataTreeDitto, xarray.Dataset, xarray.DataArray, or) – convertible object Result returned by a plugin call. Values must either already be DataTree-compatible or be convertible by
DataTreeDitto. Scalars and other simple values should be wrapped in aDataset,DataArray, or supported container such as adictbefore attaching.step_id (str, optional) – Name to use for the attached result node. Defaults to plugin_name.
plugin_kind (str) – Registered plugin kind that produced step_data, or
"manual"for user-created script data. Values are validated against the cached GeoIPS interface list plus"manual".plugin_name (str, optional) – Plugin name that produced step_data. Required for registered plugin kinds. For
plugin_kind="manual", omitted plugin names are recorded as"manual".start_time (datetime.datetime, optional) – Step start datetime. Defaults to the current UTC time for registered plugin kinds. For
plugin_kind="manual", omitted times are recorded asNone.end_time (datetime.datetime, optional) – Step end datetime. Defaults to the current UTC time for registered plugin kinds. For
plugin_kind="manual", omitted times are recorded asNone.retention_policy (RetentionPolicy or str, optional) – Retention policy used for this step. Defaults to the policy stored on the root script DataTree.
- Returns:
The same root script DataTree, updated in place and returned for convenient chaining.
- Return type:
xarray.DataTree
- Raises:
ValueError – If tree is not an initialized script DataTree, if no step name can be determined, if the step name already exists, or if the retention policy is invalid.
TypeError – If step_data cannot be converted to a script DataTree node.
- geoips.utils.types.script_datatree.attach_script_result(script_tree, result, *, plugin, step_id=None, step_start_time=None, retention_policy=None)[source]#
Attach a scripted plugin result and return the updated script tree.
Thin convenience wrapper around
attach_plugin_resultthat derivesplugin_kindfrom plugin’s interface andplugin_namefromplugin.name, and defaults the end time to the current UTC time. Used byBaseClassPlugin._invokeso the two script-mode attach sites do not duplicate the metadata-derivation logic.
- geoips.utils.types.script_datatree.get_current_data(tree)[source]#
Return the dataset from the most recent data-containing script step.
- Parameters:
tree (xarray.DataTree) – Root script DataTree created by
initialize_script_tree.- Returns:
Dataset from the most recent top-level reader, interpolator, algorithm, or manual step containing data variables, including data stored in child nodes such as reader outputs. The returned object is a mutable, coord-normalized dataset copy intended for inspection, modification, and reinsertion with
add_data_step.- Return type:
xarray.Dataset
- Raises:
ValueError – If tree is not an initialized script DataTree or no data-containing step is available.
- geoips.utils.types.script_datatree.get_output_products(tree, step_id=None)[source]#
Return products written by scripted output formatter steps.
- Parameters:
tree (xarray.DataTree) – Root script DataTree created by
initialize_script_tree.step_id (str, optional) – Specific output formatter step to inspect. If omitted, products from all steps with
attrs["output_products"]are returned in tree order.
- Returns:
Output products recorded by output formatter steps.
- Return type:
list
- Raises:
ValueError – If tree is not an initialized script tree, step_id is unknown, or no output products are available.
Examples
>>> from geoips.scripting import get_output_products >>> output_products = get_output_products(tree) >>> output_products ["/path/to/output.png"]
- geoips.utils.types.script_datatree.initialize_script_tree(name, retention_policy, **attrs)[source]#
Initialize a root DataTree for OBP-style scripted plugin calls.
The returned tree is intended to be passed as the
dataargument to direct plugin calls. Plugins infer script-mode OBP behavior from the tree’sexecution_modemetadata and attach results back onto this script tree usingstep_id.- Parameters:
name (str) – Name for the root script DataTree.
retention_policy (RetentionPolicy or str) – Retention policy to apply after scripted plugin calls. May be supplied as a
RetentionPolicyvalue or its string value. May be overridden on individual steps.attrs (dict) – Additional root-level metadata to store on the script DataTree.
- Returns:
Root DataTree with standard script execution metadata.
- Return type:
xarray.DataTree
- Raises:
ValueError – If retention_policy is not recognized, or if attrs attempts to override reserved script metadata fields.
Examples
>>> from geoips.scripting import RetentionPolicy, initialize_script_tree >>> tree = initialize_script_tree( ... "abi_infrared_test", ... retention_policy=RetentionPolicy.metadata_only, ... ) >>> tree = reader_plugin( ... data=tree, ... filenames=fnames, ... step_id="read_data", ... )
- geoips.utils.types.script_datatree.is_script_tree(tree)[source]#
Return whether tree is an initialized script DataTree.
- geoips.utils.types.script_datatree.normalize_retention_policy(retention_policy)[source]#
Return a canonical retention policy from a string or RetentionPolicy.
This internal helper lets user-facing functions accept either
RetentionPolicy.metadata_onlystyle values or equivalent string values such as"metadata_only".
- geoips.utils.types.script_datatree.plugin_kind(plugin)[source]#
Return the singular plugin kind for script step metadata.
Uses the plugin’s
interfaceattribute (e.g."filename_formatters") and returns its singular form (e.g."filename_formatter").
- geoips.utils.types.script_datatree.script_call_data(data, kwargs)[source]#
Return the data object to pass through plugin preprocessing.
Script calls keep the accumulated script tree in
data; the plugin’s own call should operate on the current data input (xarray_objkwarg when a conduit injected one, otherwise the tree itself).
geoips.utils.types.tokenization module#
Stable tokenization helpers for DataTree provenance.
Wraps dask.base.tokenize to produce deterministic, content-addressed
tokens for step outputs, argument dictionaries, and step provenance chains.
Tokens are prefixed with "dask:" so future migrations to a different
hash provider remain detectable and safe to compare by full-string equality.
- geoips.utils.types.tokenization.compute_arguments_hash(arguments: dict[str, Any]) str[source]#
Tokenize a step’s arguments dictionary.
The hash covers keys and values in a stable order so that semantically identical argument dicts produce identical tokens even when supplied via different code paths.
- Parameters:
arguments (dict) – The step’s
argumentsdictionary from the workflow spec.- Returns:
A
"dask:"-prefixed token string.- Return type:
str
- geoips.utils.types.tokenization.compute_step_output_token(step_output: Any, plugin_name: str, plugin_kind: str, arguments: dict[str, Any], upstream_tokens: dict[str, str] | None = None) str[source]#
Compute a step’s
output_tokenfor provenance attrs.The token MUST change when any of plugin identity, arguments, or upstream tokens change. It MUST NOT change for cosmetic refactors that produce the same data.
- Parameters:
step_output (Any) – The return value of a step’s
call()method (a Dataset, DataTree, numpy array, dict, etc.).plugin_name (str) – Plugin name (e.g.
"abi_netcdf").plugin_kind (str) – Plugin kind (e.g.
"reader").arguments (dict) – The step’s
argumentsdictionary.upstream_tokens (dict[str, str] or None) – Mapping of upstream step-id → output_token, or
Nonefor reader steps with no dependencies.
- Returns:
A
"dask:"-prefixed token, or"untokenizable:<exc>"if tokenization raises an exception.- Return type:
str
- geoips.utils.types.tokenization.compute_token(*objs: Any) str[source]#
Compute a stable, deterministic token over the given objects.
Wraps
dask.base.tokenizeand prefixes its output so that future migrations to a different hash provider remain forward-compatible in storedattrs.- Parameters:
*objs (Any) – Objects to include in the token. The call is positional so that callers cannot accidentally pass the same objects in a different order and get the same token.
- Returns:
A
"dask:<hex>"token string.- Return type:
str
Examples
>>> compute_token("hello", 42) 'dask:...' >>> compute_token("hello", 42) == compute_token("hello", 42) True
geoips.utils.types.yaml_plugin_callable module#
Adapter wrapping any YAML plugin dict into a callable DataTree participant.
Every YAML-defined plugin (feature_annotator, gridline_annotator, product, product_default, sector, …) becomes a first-class DAG step that adds its configuration / metadata to the step DataTree.
The Workflow._resolve_plugin static method automatically wraps dict
results (from YAML-based interfaces) in a YamlPluginCallable so that
the workflow executor can call them uniformly.
- class geoips.utils.types.yaml_plugin_callable.YamlPluginCallable(yaml_plugin: dict[str, Any])[source]#
Bases:
objectWraps a YAML plugin dict into a callable DataTree participant.
The adapter satisfies the informal protocol that
Workflow.call()expects:plg(data=upstream, **arguments) -> xr.DataTree
It stores the YAML plugin’s
specin the returned DataTree’sds.attrstogether with metadata keys (plugin_kind,output_key) that downstream hooks use to map the child node to the correct keyword argument.- Parameters:
yaml_plugin (dict) – The raw YAML plugin dict as returned by a YAML-based interface’s
get_plugin(name). Must contain at least"interface"and"spec";"name"and"family"are optional.
- call(data: DataTree | None = None, **kwargs: Any) DataTree[source]#
Produce a DataTree node carrying the YAML plugin’s specification.
- Parameters:
data (xr.DataTree or None) – Upstream DataTree (ignored for most YAML plugins; gridline annotators may use it for automatic spacing computation).
kwargs – Step arguments from the workflow specification. Currently forwarded for interface-specific post-processing.
- Returns:
A
DataTreeDittowhoseds.attrscontain the plugin’sspecdictionary and the standard routing metadata.- Return type:
xr.DataTree
- property spec: dict[str, Any]#
The
specsection of the wrapped YAML plugin dict.
Module contents#
Types subpackage init file.
The imports below trigger registration of the shared
TypeConverterRegistry and all built-in / extended converters
at import time so that both DataTreeDitto and the
plugin-lifecycle hooks can discover them.
Note
In a future version the import-time side-effects should be
replaced with explicit register_converters() calls from the
framework bootstrap entry point.