toad.postprocessing¶
- class toad.postprocessing.Aggregation(toad)¶
Bases:
objectAggregation 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 oneyes. 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-1for noise and>= 0for 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
For each input, build a mask of native event voxels (non-noise cluster labels,
>= 0).Dilate each mask in
(time, y, x)bytemporal_toleranceandspatial_tolerancefor support counting only.At each native event voxel, count how many distinct inputs have dilated support covering that cell.
Retain the voxel if the count reaches
max(1, ceil(min_consensus * n_inputs)).Group retained voxels into consensus cluster ids using the same tolerances for spacetime connectivity (
max(1, tolerance)along each axis).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 namescluster_consensusandcluster_consensus_rate):Labels (
variable_type=consensus_cluster):NaNif every input has no abrupt shift at that cell;-1if 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;0where no input assigned a cluster;NaNwhere the label isNaN.
Both arrays store
cluster_vars,min_consensus,min_consensus_members, tolerance settings, andstitch_meridian/stitch_meridian_applied. For a per-cluster table after the fact, callconsensus_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;
0means exact-time support only.spatial_tolerance (int) – Grid-cell radius in
y/xfor support dilation and cluster connectivity. Required;0means 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.Nonedisables 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]`, ormin_cluster_areais 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 (seekeep_full_timeseries). Convenient for overlaying trajectories from the same region across inputs.For when shifts occurred, use
consensus_summary()orconsensus_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_varis 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, elseself.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
Falseandda_clustersis 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 matchestoad.core.TOAD.get_timeseries()for the chosenaggregation.- 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_idand the inputcluster_varhas 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 anxr.Dataset(per-cluster ×cluster_varmeans/stds) and a longDataFrameof 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_dimwhen present onda_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 inputcluster_varvalues 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_dimwhen present onda_clusters.distribution_result (tuple[Dataset, DataFrame] | None) – If provided, a prior
(dataset, dataframe)tuple fromconsensus_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 (seetoad.utils.cluster_consensus_utils.consensus_shift_time_distribution()). To plot full base-variable trajectories over a shared spatial region with a looser time rule, useconsensus_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 astoad.core.TOAD._resolve_consensus_var()).- Returns:
DataFrame with one row per consensus cluster. Includes
mean_consensus_rate, spatialareaand centroid columns,median_median_shift_time(median of per-input spatial medians), related between-input std columns, andpooled_median_shift_time/pooled_std_shift_timeover all pooled event-time samples; seetoad.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 inself.td.dataor axarray.DataArrayof 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:
objectInterface 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_idsis 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_lonwhen 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
Per-voxel member-support spacetime consensus. |
|