Fit a temporal reference model for contemporaneous ARA background subtraction
Source:R/reference_model.R
fit_reference_model.RdFits per-analyte temporal models on reference-site chemistry so that
add_mspaf() can subtract a contemporaneous background (what the
reference site would have shown at the same moment as the target sample)
rather than a static time-average.
Usage
fit_reference_model(
reference,
hydro = NULL,
hydro_type = "rainfall",
latitude = NULL,
longitude = NULL,
conc_units = NULL,
analyte_metadata = NULL,
imputation_model = NULL,
match_window_days = 5L,
match_hydro_tol = NULL,
api_tau_bounds_short = c(1, 30),
api_tau_bounds_long = c(20, 365),
auto_select = TRUE,
min_obs_model = 20L,
summary = "geom_mean",
silo_start = NULL,
silo_end = NULL,
silo_api_key = NULL,
eps = 1e-09
)Arguments
- reference
Long-format reference chemistry data frame. Required columns:
sample_id,site_id,datetime,analyte,value,detected. Toxicant concentrations must be in µg/L; supply them via aunits.analytecolumn or viaconc_units.- hydro
Daily hydrology data frame (
date,value), orNULLto fetch SILO rainfall automatically. See Hydrology input above.- hydro_type
Character; one of
"rainfall","stage","discharge". Ignored ifhydroalready has atypecolumn. Default"rainfall".- latitude, longitude
Decimal-degree coordinates; required only when
hydro = NULL(SILO auto-fetch path).- conc_units
Unit string (e.g.
"mg/L","ug/L") for reference chemistry when nounits.analytecolumn is present.- analyte_metadata
Analyte metadata, or
NULLfor the bundled CSV.- imputation_model
Optional
imputation_modelfromfit_imputation_model()(fit on the reference site's own chemistry). When supplied, missing analytes are imputed in raw concentration space before the per-analyte models are fitted, so a well-sampled analyte lifts a sparsely-sampled one into a richer spread of hydrological regimes. Imputed rows (detected = TRUE) are used as model anchors alongside measured observations. Requires brms. DefaultNULL(measured observations only).- match_window_days
Integer; tier-1 time tolerance in days (default 5).
- match_hydro_tol
Numeric; tier-1 hydro tolerance (default
NULL→0.5 × IQRof the reference event-API series).- api_tau_bounds_short
Length-2 numeric
c(lo, hi)search range (days) for the short-store recession constanttau_short(defaultc(1, 30)). A degeneratec(x, x)fixestau_short = x.- api_tau_bounds_long
Length-2 numeric
c(lo, hi)search range (days) for the long-store recession constanttau_long(defaultc(20, 365)).- auto_select
Logical; if
TRUE(default), selecttau_short,tau_longper analyte by profiled AIC. IfFALSE, use the parsimonious defaults (tau_short = 7,tau_long = 60) for all analytes.- min_obs_model
Integer; minimum detected observations required to attempt tier-2 modelling (default
20L). Analytes below this fall directly to tier 3.- summary
Static-fallback summary statistic (tier 3): one of
"geom_mean"(default),"median","arith_mean","p80","p90","p95".- silo_start, silo_end
Start/end dates for SILO auto-fetch. Default
NULL: derived from the reference chemistry date range, padded on the left by5 × max(api_tau_bounds_long)days so the recursive reservoir has enough burn-in (about 5 tau) to converge before the first observation.- silo_api_key
Passed to
get_silo_rainfall()whenhydro = NULL.- eps
Small positive guard for log transform (default
1e-9).
Value
An object of class reference_model:
$modelsNamed list (one per analyte) carrying
gamm_fit,tau_short,tau_long,best_aic,null_aic,tier,n_obs,static_ref, andobs(normalised observations with hydro features — used for tier-1 matching).$hydroDaily hydro series used for index computation.
$hydro_type"rainfall","stage", or"discharge".$match_window_daysTier-1 time window.
$match_hydro_tolTier-1 hydro tolerance (computed or supplied).
$static_refTibble
(analyte, ref_norm)— tier-3 fallback for all analytes.$fit_dateDate the model was fitted.
Details
Package invariant: reference and target are assumed to share the same catchment. The hydrology series supplied here (or fetched automatically from SILO) applies to both sites. This invariant should hold for near-field leachate assessments where a headwater reference is paired with a downstream target in the same sub-catchment.
Three-tier resolver (evaluated per analyte × target date):
Tier 1 — direct match. A reference observation within
±match_window_daysdays whose event-API is withinmatch_hydro_tol(default:0.5 × IQRof the reference API series). This gate rejects time-close but hydrologically-mismatched grabs (e.g. a dry-weather reference next to a wet-event target).Tier 2 — GAM prediction. A per-analyte
mgcv::gamwiths(doy, bs="cc") + s(hydro_short) + s(hydro_long). The reservoir recession constantstau_short,tau_longare selected per analyte by profiled AIC over theapi_tau_bounds_short/api_tau_bounds_longranges (continuous, with atau_long >= 1.5*tau_shortseparation and a ΔAIC ≥ 2 adoption gate over a parsimonious default). The analyte falls back to tier 3 if the best model has higher AIC than the null (intercept-only) model, or if fewer thanmin_obs_modeldetected observations are available.Tier 3 — static fallback. Geometric mean of all normalised reference observations (identical to
prepare_reference()withsummary = "geom_mean").
Hydrology input — supply exactly one of:
hydro: a data frame with columnsdate(Date) andvalue(numeric), plus atypecolumn OR supplyhydro_type =separately. Supported types:"rainfall"(daily mm; → API),"stage"(m; → antecedent mean),"discharge"(m³/s; → antecedent mean).latitude+longitude: ifhydro = NULL, SILO daily rainfall is fetched automatically viaget_silo_rainfall(). Requires the weatherOz package and a valid SILO API key.
Examples
if (FALSE) { # \dontrun{
# Fit using SILO auto-fetch
ref <- subset(leachate_demo(), site_id == "reference")
ref_model <- fit_reference_model(
reference = ref,
latitude = -33.87,
longitude = 151.21,
conc_units = "ug/L"
)
ref_model
# Or supply your own gauge record
ref_model2 <- fit_reference_model(
reference = ref,
hydro = my_stage_df, # data.frame(date, value)
hydro_type = "stage",
conc_units = "ug/L"
)
} # }