Processor: BiasAdjustModelToStation
Registry key: bias_adjust_model_to_station | Priority: 60 | Category: Data Refinement
Apply quantile delta mapping (QDM) bias adjustment to gridded climate model data using HDP (Historical Data Platform) weather station observations as the training reference. Output is bias-adjusted at the requested station locations, with a station dimension (and lat/lon/elevation coordinates along it) on a single data variable, rather than one data variable per station.
Algorithm
flowchart TD
Start([execute]) --> DictCheck{result is dict?}
DictCheck -->|Yes| ExecDict[_execute_dict<br/>per-key recursion]
DictCheck -->|No| LoadObs[_load_station_data<br/>HDP reference]
LoadObs --> TypeCheck{Dataset / DataArray?}
TypeCheck -->|Yes| ProcSingle[_process_single_dataset]
TypeCheck -->|No| TypeErr[raise TypeError]
ExecDict --> ProcSingle
ProcSingle --> Preproc[_preprocess_hdp<br/>rename, unit check, attrs]
Preproc --> BiasAdjust[_bias_adjust_model_data<br/>QDM via xclim]
BiasAdjust --> UpdateCtx[update_context]
UpdateCtx --> End([Output: Dataset with a 'station' dimension])
click Start "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "execute"
click ExecDict "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "_execute_dict"
click LoadObs "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "_load_station_data"
click ProcSingle "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "_process_single_dataset"
click Preproc "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "_preprocess_hdp"
click BiasAdjust "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "_bias_adjust_model_data"
click UpdateCtx "https://github.com/cal-adapt/climakitae/blob/main/climakitae/new_core/processors/bias_adjust_model_to_station.py" "update_context"
Parameters
The processor takes a dict:
| Key | Type | Default | Description |
|---|---|---|---|
stations |
list[str] |
[] |
HDP station_id values to bias-adjust against (e.g. "ASOSAWOS_69007093217"). Required for non-trivial use. |
historical_slice |
tuple[int, int] |
(1980, 2014) |
Years used as the training period. Must overlap each station's actual observational coverage, which varies per HDP station. |
window |
int |
90 |
Window size (days) for seasonal grouping in QDM. |
nquantiles |
int |
20 |
Number of quantiles for the QDM mapping. |
group |
str |
"time.dayofyear" |
Temporal grouping passed to xclim QDM. |
kind |
str |
"+" |
Adjustment kind: "+" (additive) or "*" (multiplicative). |
Requirements
- Activity ID: WRF (dynamical downscaling). LOCA2 already includes statistical bias adjustment at the watershed level and is not the intended input.
- Variable: Designed for hourly
t2(temperature, matched to HDP'stas) ordew_point(dewpoint, matched to HDP'stdps, ortdps_derivedwheretdpsisn't available). Not every HDP network provides every variable — requesting a station from a network known not to provide the needed variable is rejected up front. - Time coverage: Input must overlap the requested historical training period (default 1980–2014). HDP station coverage varies widely by station, from a few years to multiple decades.
- Multiple networks: Requested stations may span multiple HDP networks in a single call.
- Calendar: All inputs are converted to a
noleapcalendar internally for consistency.
Example
from climakitae.new_core.user_interface import ClimateData
data = (ClimateData()
.catalog("cadcat")
.activity_id("WRF")
.institution_id("UCLA")
.variable_id("t2")
.table_id("1hr")
.grid_label("d03")
.processes({
"time_slice": ("1980-01-01", "2050-12-31"),
"bias_adjust_model_to_station": {"stations": ["KSAC"]},
})
.get())
# Result: single data variable with a 'station' dimension, time-sliced to requested range.
Code References
| Method | Link to Code | Purpose |
|---|---|---|
__init__ |
View on Github | Read configuration dict with defaults |
_preprocess_hdp |
View on Github | Rename / unit-check / attribute the raw HDP station slice |
_load_station_data |
View on Github | Resolve station IDs against the HDP catalog, load HDP subset, return reference Dataset |
_bias_adjust_model_data |
View on Github | Build QDM (xclim) train/adjust, vectorized across all stations at once |
_process_single_dataset |
View on Github | Load reference, run vectorized QDM across stations, return dataset with a station dimension |
_execute_dict |
View on Github | Recursive dict path |
execute |
View on Github | Dispatcher: dict / Dataset / DataArray |
update_context |
View on Github | Record stations and QDM parameters in new_attrs |
set_data_accessor |
View on Github | Receive DataCatalog reference (used by _load_station_data) |
Earlier docs implied an early "activity_id == WRF" guard with line numbers in the 80–145 range. Those line numbers do not exist in the source — the file's first method (
__init__) starts at line 148. The activity-id constraint is enforced by data availability rather than an explicit early-return check.