climate_ref.results.outliers
#
Outlier detection for scalar metric values.
This is a port of the logic previously living in the ref-app backend, and has been hoisted here to ensure all consumers use the same logic.
Outlier detection is read logic, not presentation policy. All consumers should see the same set of outliers. The outlier detection is performed at run-time (instead of a pre-computed flag) as the outlier configuration may depend on the use-case. We may also adopt other outlier detection algorithms in future.
The algorithm is source-id-aware Inter-Quartile Range (IQR).
Within each group_by group,
IQR bounds are computed on the per-source_id mean value
(so each model is weighted equally regardless of ensemble size),
then applied to individual values.
The values that are outside factor * IQR are flagged as outliers.
"Reference" values are never flagged.
Non-finite values (NaN/inf) are always flagged.
AnnotatedScalar
#
A scalar ORM row paired with its outlier verdict.
Source code in packages/climate-ref/src/climate_ref/results/outliers.py
OutlierPolicy
#
Configuration for scalar outlier detection.
The defaults reproduce the behaviour users currently see through the ref-app API
(factor=10.0, source-id-aware IQR grouped by ("statistic", "metric")).
Source code in packages/climate-ref/src/climate_ref/results/outliers.py
enabled
property
#
Whether detection should run.
factor = 10.0
class-attribute
instance-attribute
#
Multiplier on the IQR to set the outlier bounds (Q1 - factor*IQR, Q3 + factor*IQR).
group_by = ('statistic', 'metric')
class-attribute
instance-attribute
#
CV dimensions to group by before computing bounds. Missing dimensions are ignored.
method = attrs.field(default='iqr', validator=(attrs.validators.in_(_SUPPORTED_METHODS)))
class-attribute
instance-attribute
#
Detection method. "off" disables detection; "iqr" enables it.
min_n = attrs.field(default=4, validator=(attrs.validators.ge(2)))
class-attribute
instance-attribute
#
Minimum sample size required to run detection.
On the source-id-aware path this counts distinct non-reference source_id with a finite mean.
On the fallback path it counts finite values.
Non-finite values (NaN/inf) are excluded from the count
and are flagged unconditionally regardless of whether detection runs.
detect_scalar_outliers(scalar_values, policy)
#
Annotate scalar values with outlier verdicts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scalar_values
|
Sequence[ScalarMetricValue]
|
The full (unpaginated) set of scalar rows for the query scope. Detection must run over the whole set so IQR bounds are globally consistent. |
required |
policy
|
OutlierPolicy
|
Detection configuration. |
required |
Returns:
| Type | Description |
|---|---|
tuple[list[AnnotatedScalar], int]
|
A tuple of (annotated values in input order, total number of outliers). |