toad.postprocessing

class toad.postprocessing.Aggregation(toad)

Bases: object

Aggregation methods for TOAD objects.

cluster_occurrence_rate(cluster_vars=None)

Share of input clusterings in which a grid cell was ever assigned a cluster.

For each spatial cell and each label field, TOAD checks whether any timestep has a non-noise label (>= 0); multiple cluster events at different times in the same run still count as one yes. The result is the mean over inputs, in [0, 1] (1 = every included clustering ever labelled that cell).

This is a time-collapsed hotspot diagnostic, not spacetime consensus: it does not require agreement on timing or cluster id across inputs.

Parameters:

cluster_vars (list[str] | None) – Label variables to include. If None, uses all TOAD.cluster_vars. Each must use -1 for noise and >= 0 for cluster membership.

Returns:

2D DataArray named cluster_occurrence_rate (or a uniquified name).

Return type:

DataArray

compute_consensus(cluster_vars=None, *, min_consensus, temporal_tolerance, spatial_tolerance, stitch_meridian='auto', show_progress=True, output_label_suffix='', output_label=None, overwrite=False, min_cluster_area=2)

Merge several input cluster maps into one spacetime consensus field on self.td.data.

Use this when you have multiple cluster label fields on the same time × space grid (different models, parameters, or variables) and want regions where enough inputs agree that an abrupt shift occurred, within chosen time and space windows.

Algorithm

  1. For each input, build a mask of native event voxels (non-noise cluster labels, >= 0).

  2. Dilate each mask in (time, y, x) by temporal_tolerance and spatial_tolerance for support counting only.

  3. At each native event voxel, count how many distinct inputs have dilated support covering that cell.

  4. Retain the voxel if the count reaches max(1, ceil(min_consensus * n_inputs)).

  5. Group retained voxels into consensus cluster ids using the same tolerances for spacetime connectivity (max(1, tolerance) along each axis).

  6. Optionally drop clusters whose spatial footprint is below min_cluster_area.

Dilation never writes extra cells to the output: only voxels that were detected in at least one input can appear in the consensus mask. Spatial tolerance is in native grid indices, not kilometres. With stitch_meridian, the first and last longitude column can be treated as neighbours during dilation and labelling on global grids.

Writes

Two variables are merged into self.td.data (default names cluster_consensus and cluster_consensus_rate):

  • Labels (variable_type=consensus_cluster): NaN if every input has no abrupt shift at that cell; -1 if at least one input had a defined label but the cell is not in consensus (or was filtered out); non-negative integers are consensus cluster ids.

  • Rate (variable_type=consensus_rate): supporting inputs divided by total inputs at each native event voxel, including voxels below the consensus threshold; 0 where no input assigned a cluster; NaN where the label is NaN.

Both arrays store cluster_vars, min_consensus, min_consensus_members, tolerance settings, and stitch_meridian / stitch_meridian_applied. For a per-cluster table after the fact, call consensus_summary().

Parameters:
  • cluster_vars (List[str] | None) – Input clustering variables to include. If None, uses all self.td.cluster_vars.

  • min_consensus (float) – Fraction in [0, 1] of inputs required per retained voxel after dilation. Required; no default.

  • temporal_tolerance (int) – Time-step radius for support dilation and cluster connectivity. Required; 0 means exact-time support only.

  • spatial_tolerance (int) – Grid-cell radius in y/x for support dilation and cluster connectivity. Required; 0 means exact spatial support only.

  • stitch_meridian (bool | Literal['auto']) – False, True, or "auto" (default). "auto" enables seam stitching when the grid spans nearly all longitudes.

  • show_progress (bool) – Show a progress bar while processing inputs. Default: True.

  • output_label_suffix (str) – Suffix for the default label name cluster_consensus.

  • output_label (str | None) – Explicit consensus labels variable name. If None, uses "cluster_consensus" + output_label_suffix.

  • overwrite (bool) – Replace existing variables with the same names. If False, uniquify names like toad.clustering.compute_clusters().

  • min_cluster_area (int | None) – Drop consensus clusters whose spatial footprint (cells at any time) is strictly below this value; ids are re-sorted afterward. Default 2. None disables the filter.

Return type:

None

See also

consensus_clustering for a longer guide and Consensus tutorial for a worked example.

Example

>>> td.compute_consensus(
...     cluster_vars=['var_dts_cluster', 'var_dts_cluster_1'],
...     min_consensus=0.7,
...     temporal_tolerance=5,
...     spatial_tolerance=1,
...     min_cluster_area=10,
... )
>>> td.plot.consensus_overview()
>>> td.aggregate.consensus_summary().head()
Raises:

ValueError – If no cluster variables are found, a tolerance is negative,

Parameters:
  • cluster_vars (List[str] | None)

  • min_consensus (float)

  • temporal_tolerance (int)

  • spatial_tolerance (int)

  • stitch_meridian (bool | Literal['auto'])

  • show_progress (bool)

  • output_label_suffix (str)

  • output_label (str | None)

  • overwrite (bool)

  • min_cluster_area (int | None)

Return type:

None

:raises min_consensus` is outside [0, :py:class:`1]`, or min_cluster_area is invalid:

consensus_cluster_timeseries(da_clusters, consensus_cluster_id, *, var=None, cluster_vars=None, aggregation='raw', percentile=None, normalize=None, keep_full_timeseries=True)

Extract per-input timeseries for one consensus cluster.

Uses consensus_extraction_mask_2d() — a spatial footprint where consensus and each input were active at least once (not necessarily at the same time), then aggregates the base variable over those cells for the full time axis (see keep_full_timeseries). Convenient for overlaying trajectories from the same region across inputs.

For when shifts occurred, use consensus_summary() or consensus_shift_time_distribution() instead; those require consensus and input labels at the same (time, y, x) voxel.

Parameters:
  • da_clusters (DataArray) – Consensus labels from compute_consensus() / TOAD.compute_consensus().

  • consensus_cluster_id (int) – Consensus cluster id to extract.

  • var (str | None) – Optional base variable override used for all returned timeseries. If omitted, each cluster_var is mapped to its own base variable.

  • cluster_vars (list[str] | None) – Optional subset of input clustering variables. Defaults to da_clusters.attrs["cluster_vars"] when available, else self.td.cluster_vars.

  • aggregation (Literal['raw', 'mean', 'sum', 'std', 'median', 'percentile', 'max', 'min'] | str) – Same as toad.core.TOAD.get_timeseries().

  • percentile (float | None) – Required when aggregation="percentile".

  • normalize (Literal['max', 'max_each'] | str | None) – Same as toad.core.TOAD.get_timeseries().

  • keep_full_timeseries (bool) – If False and da_clusters is time-resolved, values outside the consensus cluster’s overall start/end window are masked out.

Returns:

Mapping {cluster_var: xr.DataArray} for input clusterings with a non-empty footprint. Each series matches toad.core.TOAD.get_timeseries() for the chosen aggregation.

Return type:

dict[str, DataArray]

consensus_extraction_mask_2d(da_clusters, consensus_cluster_id, cluster_var)

2D boolean mask of grid cells used by consensus_cluster_timeseries().

A cell is True iff, at some timestep, the consensus label equals consensus_cluster_id and the input cluster_var has a non-noise label (>= 0). Those conditions need not hold at the same time — the mask is collapsed with OR over time, then used to extract full time series on the resulting spatial footprint.

This is looser than the support rule in consensus_summary() / consensus_shift_time_distribution(), which require consensus and input to agree at the same (time, y, x) when computing shift-time statistics.

Parameters:
  • da_clusters (DataArray) – Consensus label field.

  • consensus_cluster_id (int) – Target consensus cluster id.

  • cluster_var (str) – One input clustering variable name.

Returns:

DataArray of bool with dimensions self.td.space_dims.

Return type:

DataArray

consensus_shift_time_distribution(da_clusters, *, spatial_dims=None, time_dim=None)

Export event-time samples behind the consensus summary shift columns.

Wraps toad.utils.cluster_consensus_utils.consensus_shift_time_distribution(). Returns an xr.Dataset (per-cluster × cluster_var means/stds) and a long DataFrame of per-cell transition times for histograms.

Parameters:
  • da_clusters (DataArray) – Consensus labels from compute_consensus() / TOAD.compute_consensus().

  • spatial_dims (tuple[str, str] | None) – Defaults to self.td.space_dims.

  • time_dim (str | None) – Inferred from self.td.time_dim when present on da_clusters.

Returns:

(xr.Dataset, pandas.DataFrame) — see the utility docstring.

Return type:

tuple[Dataset, DataFrame]

consensus_shift_time_distributions(da_clusters, *, spatial_dims=None, time_dim=None, distribution_result=None, source_input_cluster_var=None)

Return transition-time samples grouped by consensus cluster id.

This is a plotting-friendly wrapper around consensus_shift_time_distribution(). It aggregates across all input cluster_var values and returns {cluster_id: shift_times}, which is convenient for violin plots of consensus-cluster timing distributions.

Parameters:
  • da_clusters (DataArray) – Consensus labels from compute_consensus() / TOAD.compute_consensus().

  • spatial_dims (tuple[str, str] | None) – Defaults to self.td.space_dims.

  • time_dim (str | None) – Inferred from self.td.time_dim when present on da_clusters.

  • distribution_result (tuple[Dataset, DataFrame] | None) – If provided, a prior (dataset, dataframe) tuple from consensus_shift_time_distribution() for the same inputs; recomputation of the long table is skipped.

  • source_input_cluster_var (str | None) – If set, use only long-form rows from this input clustering (see toad.utils.cluster_consensus_utils.consensus_shift_time_distributions()).

Returns:

Mapping from consensus cluster id to a 1D array of transition times. In spacetime mode the samples match the summary pipeline exactly, so the same spatial cell may appear multiple times if it belongs to the same consensus component at multiple timesteps.

Return type:

dict[int, ndarray]

consensus_summary(consensus_var=None)

Rebuild the per-cluster summary table from stored consensus label and rate arrays.

Shift-time columns use strict same-(time, y, x) agreement between consensus and each input (see toad.utils.cluster_consensus_utils.consensus_shift_time_distribution()). To plot full base-variable trajectories over a shared spatial region with a looser time rule, use consensus_cluster_timeseries() instead.

Parameters:

consensus_var (str | None) – Name of the consensus labels variable (variable_type=consensus_cluster). If None, infers the variable when exactly one consensus label exists on the dataset (same resolution rules as toad.core.TOAD._resolve_consensus_var()).

Returns:

DataFrame with one row per consensus cluster. Includes mean_consensus_rate, spatial area and centroid columns, median_median_shift_time (median of per-input spatial medians), related between-input std columns, and pooled_median_shift_time / pooled_std_shift_time over all pooled event-time samples; see toad.utils.cluster_consensus_utils._build_consensus_summary_df_spacetime().

Return type:

DataFrame

label_shift_time_distributions(label_data, *, spatial_dims=None, time_dim=None)

Transition-time samples per cluster id in one time-resolved label field.

For violin-style plots of a normal clustering, pass that cluster map’s name. Same convention as the consensus long table (event time at each labelled spacetime cell).

See toad.utils.cluster_consensus_utils.label_field_shift_time_distributions().

Parameters:
  • label_data (str | DataArray)

  • spatial_dims (tuple[str, str] | None)

  • time_dim (str | None)

Return type:

dict[int, ndarray]

label_shift_time_samples(label_data, *, spatial_dims=None, time_dim=None)

Per-cell event times for a single 3D label field (non-consensus or any labels).

Wraps toad.utils.cluster_consensus_utils.label_field_shift_time_samples(). Pass a variable name in self.td.data or a xarray.DataArray of labels.

Parameters:
  • label_data (str | DataArray)

  • spatial_dims (tuple[str, str] | None)

  • time_dim (str | None)

Return type:

DataFrame

class toad.postprocessing.Stats(toad, var)

Bases: object

Interface to access specialized statistics calculators for clusters: time, space, and general metrics.

Used when calling td.stats(var) explicitly; _StatsAccessor in core.py delegates here for td.stats.time etc.

cluster_summary(cluster_ids=None, *, extended=False, shift_threshold=0.5, exclude_noise=True)

Per-cluster overview table of time, space, and size metrics.

Provides a compact dashboard of all detected clusters for quick inspection, CSV export, or downstream filtering — analogous to toad.postprocessing.Aggregation.consensus_summary() for consensus labels.

Parameters:
  • cluster_ids (int | list[int] | range | None) – Subset of clusters to include. Defaults to all non-noise clusters.

  • extended (bool) – If True, add IQR timing bounds, shift amplitudes, pooled transition times, and clustering metadata from variable attributes.

  • shift_threshold (float) – Minimum shift magnitude for pooled transition-time columns (extended mode only).

  • exclude_noise (bool) – Whether to exclude noise (cluster ID -1) when cluster_ids is None.

Returns:

DataFrame with one row per cluster. Minimal columns always include cluster_id, start_time, end_time, duration_timesteps, size, footprint_area, median_time, and spatial centre columns (center_lat/center_lon when geographic coordinates exist).

Return type:

DataFrame

Example

>>> td.cluster_summary("temperature")
>>> td.stats("temperature").cluster_summary(extended=True)
property general

Access general statistics for clusters.

property space

Access space-related statistics for clusters.

property time

Access time-related statistics for clusters.

Modules

aggregation

member_support_consensus

Per-voxel member-support spacetime consensus.

stats