API Reference#
Quick reference#
Function |
Description |
|---|---|
Compute Scaled RI (RI₀₋₃ by default) from six isoGDGT abundances |
|
Forward: temperature → proxy percentiles (pure Python) |
|
Inverse: proxy → temperature with full uncertainty (runs Stan) |
|
Flag reconstructed samples the calibration cannot support |
|
Download forward posteriors from Zenodo |
|
Download training CSVs + CMEMS NO₃ field |
|
Print and return |
|
Flag samples outside the published calibration domain (no fitting required) |
|
Control the number of forward draws M a reconstruction marginalises over |
|
Build validated Stan data dict for forward calibration |
|
Run forward calibration Stan sampling |
|
Persist forward posterior as compressed NetCDF |
|
Load a forward or invT posterior from the cache |
|
Divergences, R-hat, ESS, E-BFMI |
Prediction#
Compute Scaled Ring Index#
- compute_scaledRI(gdgt0, gdgt1, gdgt2, gdgt3, cren, cren_prime, *, cren_weight=3, cren_rings=None)[source]#
Compute Scaled Ring Index from six isoGDGT abundances.
Accepts raw LC/MS peak areas or fractional abundances — both give identical results because the formula divides by the total sum of all six GDGTs, so any common scale factor drops out. Default
cren_weight=3produces scaledRI_cren3 (RI₀₋₃), the canonical proxy used in TEXAS calibration posteriors.- Parameters:
gdgt0 (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
gdgt1 (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
gdgt2 (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
gdgt3 (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
cren (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
cren_prime (float or array-like) – isoGDGT abundances — GDGT-0, GDGT-1, GDGT-2, GDGT-3, crenarchaeol, crenarchaeol regioisomer (cren’). Raw LC/MS peak areas and fractional abundances give the same result (see above).
cren_weight (float) – Weight carried by both crenarchaeol and its regioisomer, which also sets the normalisation (see Notes).
3→ scaledRI_cren3 / RI₀₋₃ (default, recommended).4→ scaledRI / RI₀₋₄ (Zhang et al. 2016 convention).cren_rings (int, optional) – Deprecated alias for
cren_weight. Emits aDeprecationWarning.
- Returns:
Scaled Ring Index, dimensionless, nominally in [0, 1].
- Return type:
numpy.ndarray or float
Notes
The formula is:
RI = (1·GDGT1 + 2·GDGT2 + 3·GDGT3 + cren_weight·cren + cren_weight·cren') / (GDGT0 + GDGT1 + GDGT2 + GDGT3 + cren + cren') scaledRI = RI / cren_weightThe parameter does two jobs at once: it is the coefficient on cren and cren’ in the numerator and the constant the whole index is divided by, so it fixes the scale on which every sample is expressed, not just the two crenarchaeol terms. That second job is what makes a value chosen here part of the proxy’s definition rather than a detail — a posterior calibrated at 3 cannot read an index built at 4.
It was called
cren_ringsuntil 2026-08-21, which was misleading twice over: it named only the first job, and it implied a count of cyclic moieties. Neither 3 nor 4 is that count. They are calibration conventions, which is why both are offered and why neither is “correct”.Examples
>>> compute_scaledRI(0.45, 0.10, 0.08, 0.05, 0.30, 0.02) array(0.45666...)
>>> import pandas as pd >>> df = pd.read_csv("my_gdgt_data.csv") >>> df["scaledRI_cren3"] = compute_scaledRI( ... df["GDGT-0"], df["GDGT-1"], df["GDGT-2"], df["GDGT-3"], ... df["cren"], df["cren_prime"], ... )
Predict proxy from T#
- predict_proxy_from_T(temperatures, posterior, *, n_draws=500, percentiles=[5, 50, 95], return_full=False, seed=42, gdgt23ratio=None, no3=None, no3_cutoff=None, suffix=None, fwd_cache_dir=None)[source]#
Forward prediction: temperature → proxy percentiles (Scaled RI, TEX86, or any fitted proxy).
Samples n_draws self-consistent parameter sets from the forward calibration posterior (all parameters drawn from the same posterior index, preserving correlations) and evaluates the calibration curve at each requested temperature. Corresponds to the forward model described in Eq. 1 / Eq. 6–7 of the manuscript.
- Parameters:
temperatures (array-like) – Temperatures (°C) at which to evaluate the calibration curve.
posterior (xr.Dataset or str) – Forward calibration posterior — either a loaded xr.Dataset or a saved-file name string (looked up in the posterior cache).
n_draws (int) – Number of posterior draws to sample. Default 500.
percentiles (list of float) – Percentiles to return, e.g. [5, 50, 95].
return_full (bool) – If True, also return the full (n_draws × len(temperatures)) ensemble array and run metadata under keys
"ensemble"and"metadata".seed (int) – Random seed for reproducible draw sampling.
gdgt23ratio (array-like, optional) – GDGT-2/GDGT-3 ratio values (one per temperature point). Required only when the posterior was fitted with the multivariate model (β_{G₂/₃} correction).
no3 (array-like, optional) – Nitrate concentration values (one per temperature point). Required only when the posterior was fitted with NO₃ correction.
no3_cutoff (float, optional) – Nitrate threshold (μmol/L) below which the NO₃ correction applies. Defaults to the value stored in the posterior attributes.
suffix (str, optional) – Force a specific parameter suffix (e.g.
"crtp"). Auto-detected by priority order when omitted.fwd_cache_dir (Path or str, optional) – Directory to resolve posterior in when it is given as a name string. Defaults to the standard forward posterior cache. Ignored when a loaded Dataset is passed.
- Returns:
"x_vals"— temperature array (°C)"pN"— one key per requested percentile, e.g."p5","p50","p95""ensemble"— full array, shape (n_draws, len(temperatures)), if return_full=True"metadata"— run metadata dict, if return_full=True- Return type:
dict with keys
Predict T from proxy observations#
- predict_T_from_proxyObs(proxyObs, prior_mu_t, prior_sigma_t, fwd_posterior=None, *, proxy_name=None, temptype=None, site_name=None, predictors=None, no3=None, gdgt23ratio=None, site_lat=None, site_lon=None, no3_dataset=None, no3_dataset_var='no3_sf2tc_avg', flags=True, tex86=None, config=None, chains=4, iter_warmup=500, iter_sampling=1000, seed=42, constraint_type='unconstrained', min_temp=None, threads_per_chain=None, save_results=False, save_draws=False, filename_tag=None, cache_dir=None, fwd_cache_dir=None)[source]#
Inverse reconstruction: scaled RI → temperature percentiles.
Runs the TEXAS-Bay inverse Stan model to infer paleotemperature from observed scaled Ring Index values. Marginalises over M draws from the forward calibration posterior to propagate calibration uncertainty into the temperature reconstruction. Corresponds to Section 8 (Applications to Paleothermometry) of the manuscript.
- Parameters:
proxyObs (array-like, shape (N,)) – Observed proxy values from downcore or coretop samples (e.g. scaledRI, TEX86).
prior_mu_t (float or array-like, shape (N,)) – Prior mean temperature (°C). Scalar applies the same prior to all N observations; array sets a site-specific prior per sample.
prior_sigma_t (float) – Prior temperature uncertainty (°C). Use a diffuse value (e.g. 10) when little prior information is available.
fwd_posterior (str or xr.Dataset, optional) –
The forward calibration posterior. When omitted, the full multivariate T0-shift calibration for temptype is used —
tx.GHEB.sst.sri03.G23-N1p0for SST,tx.GHEB.thm.sri03.G23-N1p0for thermoT — which ships with the package, so no download is required. Accepts either:str — name of the saved posterior (without
.ncextension) in the posterior cache directory. The file is loaded automatically.xr.Dataset — a pre-loaded posterior Dataset. No file I/O or Zenodo download is attempted; pass this when the cache is unavailable (e.g. Google Colab with a Drive-mounted
.nc):ds = xr.open_dataset("my_drive/posterior.nc") result = predict_T_from_proxyObs(..., fwd_posterior=ds)
temptype (str, optional) – Temperature type:
"SST"or"thermoT". Optional. It does not change the reconstruction, which follows the calibration supplied: when fwd_posterior is given, the target is read from that posterior’s own attributes and temptype only labels the metadata and output filenames (a value conflicting with the calibration raises a warning). It matters in exactly one case — when fwd_posterior is omitted, it chooses which default calibration is used, SST or thermoT.site_name (str, optional) – Label attached to result metadata and output filenames.
predictors (dict, optional) – Non-thermal predictor arrays for the N observations, e.g.
{"gdgt23ratio": array, "no3": array}. Must be provided when the forward posterior was fitted with the multivariate model. Overridden by no3 / gdgt23ratio shorthands when both are given.no3 (float or array-like, optional) –
Nitrate concentration (µmol/L) for the N observations.
Array (length N): per-observation values — use modern WOA23 values extracted at each sample’s location (
ocean_prop_dscolumn"no3_sf2tc_avg").Scalar: broadcast to all N observations. Pass a value above
no3_cutoff(e.g.no3=10.0whenno3_cutoff=1.0) to effectively disable the NO₃ correction — all observations fall outside the correction window.
Overrides any
"no3"key in predictors. Ignored when site_lat / site_lon / no3_dataset are also provided (the lookup result takes priority).gdgt23ratio (float or array-like, optional) – GDGT-2/GDGT-3 ratio for the N observations. Scalar or array, same broadcast rules as no3. Overrides any
"gdgt23ratio"key in predictors.site_lat (float or array-like, optional) – Decimal latitude(s) of the study site(s). Scalar for a single drill core; array of length N to assign a distinct location to each observation. Requires site_lon and no3_dataset.
site_lon (float or array-like, optional) – Decimal longitude(s) of the study site(s). Same shape rules as site_lat.
no3_dataset (xr.Dataset, optional) – WOA23-derived dataset with a
(lat, lon)grid, typically theocean_prop_dsgenerated in the preprocessing notebook (SI_code0). Must contain no3_dataset_var. When provided together with site_lat / site_lon, the NO₃ value at those coordinates is looked up via bilinear interpolation and used as the predictor. The result is a scalar (one drill site) or array (per-obs sites), and is broadcast to all N observations when scalar. Optional when site_lat / site_lon are given: if omitted, the ~20 MBocean_prop_dsfield is downloaded from Zenodo and cached automatically (seeTEXAS.data.ocean_lookup.get_ocean_prop_ds()/TEXAS.download_ocean_properties()) — pass it explicitly to avoid the download (e.g. a pre-loaded copy, or a Colab session with no persistent cache).no3_dataset_var (str) – Variable name to extract from no3_dataset. Default
"no3_sf2tc_avg".flags (bool, default True) – Attach
result["flags"], a DataFrame with one row per observation marking rows the reconstruction cannot support — most importantly proxy values outside the calibration curve’s attainable range, which return a converged, plausible-looking temperature that is really a readout of the prior. SeeTEXAS.quality.compute_quality_flags(). Computing them costs no extra sampling.tex86 (float or array-like, optional) – TEX86 for the same samples, used only by the flags. The published calibration-domain ellipse is two-dimensional (TEX86 × Scaled RI), so the
outside_domaincheck needs both; without this it is reported aspd.NArather than as passing.config (InvTConfig, optional) – Controls number of forward-posterior draws (M), seed, etc. Defaults to
InvTConfig(), which auto-selects M = min(500, max(100, available_draws // 4)) — M=500 for a typical 4-chain/1000-sample forward posterior (4000 draws), the value the published paleo reconstructions use.chains (int) – Number of MCMC chains. Default 4.
iter_warmup (int) – Warmup iterations per chain. Default 500.
iter_sampling (int) – Sampling iterations per chain. Default 1000.
seed (int) – Random seed. Default 42.
constraint_type (str) –
Temperature constraint applied in the Stan model:
"unconstrained"(default): no lower bound; P5 can be unrealistically cold near the calibration curve’s lower asymptote."truncated_prior"(recommended whenmin_tempis set): proper truncated Normal prior via inverse-CDF reparameterization — P50 is data-driven and P5 is bounded atmin_tempwithout warm bias.
"hard_constraint"(hard lower bound via<lower=min_temp>) was withdrawn in 2026-09: its Jacobian biases P50 warm for polar sites, which is what"truncated_prior"was written to fix. The model is kept inarchive/submission-2026-04/stan_models/and can be run by passing its absolute path asstan_model_path."reparameterized"and"soft"were listed in earlier type hints but never existed as Stan models; all three now raiseValueErrorinstead of failing later with a missing-file error.min_temp (float, optional) – Lower temperature bound (°C). Required for
"truncated_prior". Typically −1.8 (seawater freezing point). When provided without an explicitconstraint_type, automatically selects"truncated_prior".threads_per_chain (int, optional) – Enable within-chain parallelism via Stan’s
reduce_sum.save_results (bool) – If True, save the quantile posterior
.ncand results.npzto the invT cache directory.save_draws (bool) – If True, also save the raw posterior draws (pre-quantile) as a separate
{base}_draws.ncfile in the invT cache directory. The file containst_estwith dims(chain, draw, obs_idx)and is suitable for kernel-density plots or custom quantile calculation. Default False.filename_tag (str or list of str, optional) – Extra tag(s) appended to the output filename.
cache_dir (Path or str, optional) – Directory where
.ncand.npzfiles are written when save_results or save_draws is True. Defaults to the standard invT cache (~/.texas/cache/TEXAS_invT_posterior_cache/for pip installs, ordata/cache/TEXAS_invT_posterior_cache/in the repo).fwd_cache_dir (Path or str, optional) – Directory to resolve fwd_posterior in when it is given as a name string. Defaults to the standard forward posterior cache. This is a separate directory from cache_dir, which controls only where results are written.
proxy_name (str | None)
- Returns:
"proxyObs"— input proxy array"proxy_name"— proxy type label (e.g."scaledRI","TEX86")"p5"— 5th percentile temperature (°C), shape (N,)"p50"— median temperature (°C), shape (N,)"p95"— 95th percentile temperature (°C), shape (N,)"metadata"— run metadata dict (model name, attrs, etc.)"flags"— DataFrame of per-observation quality flags, N rows,when flags is True
- Return type:
dict with keys
Examples
Keep only the observations the calibration can actually support:
>>> result = predict_T_from_proxyObs(ri, prior_mu_t=25, prior_sigma_t=10) >>> keep = ~result["flags"]["any_flag"].to_numpy(dtype=bool) >>> sst = result["p50"][keep]
Per-observation quality flags#
Returned automatically as result["flags"], and callable on its own against a
saved reconstruction.
- compute_quality_flags(proxyObs, fwd_posterior, *, predictors=None, prior_sigma_t=None, result=None, tex86=None, suffix=None, domain_confidence=0.9, prior_dominated_ratio=0.85)[source]#
Flag observations a reconstruction cannot support, one row per input.
- Parameters:
proxyObs (array-like, shape (N,)) – The observations handed to the inverse model.
fwd_posterior (xr.Dataset) – The forward calibration the reconstruction used. Both the parameter draws and the
attrsrecording the calibration’s own data range are read from it.predictors (dict, optional) –
{"gdgt23ratio": ..., "no3": ...}as passed to the reconstruction. Scalars are broadcast. Absent predictors that the calibration uses are reported bypredictor_missing.prior_sigma_t (float, optional) – The temperature prior SD. Required for
prior_dominated; without it that column ispd.NA.result (dict, optional) – The reconstruction result.
prior_dominatedneedsp16/p84from it; without it that column ispd.NA.tex86 (float or array-like, optional) – TEX86 for the same samples. The published calibration-domain ellipse is two-dimensional (TEX86 x Scaled RI), so
outside_domaincan only be evaluated when both are available; it ispd.NAotherwise.suffix (str, optional) – Parameter suffix to read (
"crtp","culmeso", …). Chosen by the usual priority when omitted.domain_confidence (float, default 0.90) – Confidence level of the Mahalanobis ellipse.
prior_dominated_ratio (float, default 0.85) – Posterior/prior SD ratio at or above which a row is prior-dominated.
- Returns:
N rows. Boolean columns from
FLAG_COLUMNS, graded columns fromDIAGNOSTIC_COLUMNS, andany_flag.A check that could not be evaluated is
pd.NA, neverFalse— “not assessed” and “passed” are different answers, and collapsing them would quietly launder the first into the second.any_flagtherefore ORs only what was actually evaluated, and only the defect columns:ADVISORY_COLUMNSare reported but do not vote.- Return type:
pd.DataFrame
Download and cache#
Download posteriors#
- download_posteriors(names=None, cache_dir=None, force=False)[source]#
Download forward calibration posteriors from Zenodo.
- Parameters:
names (list of str, optional) – Subset of
POSTERIOR_REGISTRYkeys to download. When omitted, downloads every posterior of the current record version (~475 MB — dominated by the six full multivariate EIV posteriors at ~78–81 MB each; passnames=to fetch only what you need). Superseded initial-submission posteriors are pinned to the v0.2.0 record and must be requested by name.cache_dir (Path or str, optional) – Destination directory. Defaults to the standard posterior cache.
force (bool) – Re-download files that already exist locally.
- Returns:
Local paths of the downloaded
.ncfiles.- Return type:
list of Path
Examples
Download only the univariate SST posterior (~0.3 MB):
>>> download_posteriors(["gen_logi_fixed_hier_crtp_univ_priorApprox_SST_scaledRI_cren3"])
Download all#
- download_all(cache_dir=None, data_dir=None, force=False)[source]#
Download everything from Zenodo: forward posteriors + training data.
Files are downloaded individually; already-cached files are skipped unless force=True. Total download is ~490 MB (dominated by the six full EIV multivariate posteriors at ~78–81 MB each).
- Parameters:
cache_dir (Path or str, optional) – Destination for
.ncposteriors. Defaults to the standard posterior cache directory.data_dir (Path or str, optional) – Destination for training data files. Defaults to
data/spreadsheets/.force (bool) – Re-download files that already exist locally.
- Return type:
None
Download training data#
- download_training_data(dest_dir=None, force=False)[source]#
Download GDGT training data files from Zenodo.
Downloads the coretop/culture/mesocosm training CSVs, the CMEMS NO₃ uncertainty field used in the EIV calibration, and the WOA23-derived
ocean_prop_dsgridded ocean properties. The CSVs and the CMEMS field are needed only to re-run the SI preprocessing and calibration notebooks from scratch and are NOT required for inverse temperature reconstructions — usedownload_posteriors()for that.ocean_prop_dsis the exception: it is also used at inference time bypredict_T_from_proxyObs()for the optionalsite_lat/site_lonNO₃ lookup — seedownload_ocean_properties()to fetch just that one file. It also isn’t hosted on the TEXAS record at all; it comes from the companion GRL paper’s Zenodo record (seeTRAINING_DATA_REGISTRY["ocean_prop_ds"]["record"]).- Parameters:
dest_dir (Path or str, optional) – Destination directory. Defaults to
data/spreadsheets/in the repo (or~/.texas/data/spreadsheets/when pip-installed).force (bool) – Re-download files that already exist locally.
- Returns:
Local paths of the downloaded files.
- Return type:
list of Path
List posteriors#
- list_posteriors(model_type='both', cache_dir=None)[source]#
List available posterior files in the cache directory.
Prints a summary and returns a dict of stem names that can be passed directly to
predict_T_from_proxyObs(fwd_posterior=...).- Parameters:
model_type ("forward", "invT", or "both") – Which cache to inspect. Default
"both".cache_dir (Path or str, optional) – Override the default cache root. When given, both forward and invT subdirectories are looked for under this path.
- Returns:
{"forward": [...], "invT": [...]}— lists of stem names (no.nc).- Return type:
dict
Set cache directory#
- set_cache_dir(path)[source]#
Override TEXAS cache directories at runtime.
Call this before any posterior I/O. For a persistent override, set the
TEXAS_CACHE_DIRenvironment variable instead.- Parameters:
path (str | Path) – Root directory for all TEXAS caches. Three subdirectories will be used inside it:
TEXAS_posterior_cache/,TEXAS_invT_posterior_cache/andTEXAS_kriged_grids_cache/.- Return type:
None
Screening#
Screen a record#
Flags samples lying outside the TEX₈₆–Scaled RI domain the calibration was trained on, using the same 90 % χ² Mahalanobis ellipse used to build the training set. A flagged sample is an extrapolation, not necessarily a bad measurement — the recommendation is to flag and interpret with caution rather than exclude.
The ellipse is a fixed property of the published calibration (the core-top reference cluster of Section 5.1), so nothing needs fitting — an unfitted detector on the standard features adopts it automatically:
from TEXAS.data import MahalanobisOutlierDetector
detector = MahalanobisOutlierDetector(["TEX86", "scaledRI_cren3"], confidence=0.90)
df["flagged"] = detector.detect_outliers_manual(df)
detect_outliers_manual is the manuscript’s criterion: the ellipse plus the
warm-end exception, so samples with TEX₈₆ > 0.75 and Scaled RI₀₋₃ > 0.75 are
retained rather than flagged — the calibration retains them too (Section 5.1,
Fig. 4). detect_outliers applies the bare ellipse and would flag warm samples
the calibration actually covers.
Do not call fit() or fit_predict() on your own record: that re-centres
the ellipse onto the record, so the more unusual your data the less it flags.
- class MahalanobisOutlierDetector(features, confidence=0.9, method='chi2', use_pinv_if_singular=True)[source]#
Fit Mahalanobis distance parameters on training data, apply to any dataset.
Examples
>>> # Fit on coretop data >>> detector = MahalanobisOutlierDetector(['TEX86', 'ringIndex']) # default confidence=0.90 >>> detector.fit(coretop_df) >>> coretop_df['mahal_dist'] = detector.transform(coretop_df) >>> coretop_df['outliers'] = detector.detect_outliers(coretop_df) >>> >>> # Apply to downcore data >>> downcore_df['mahal_dist'] = detector.transform(downcore_df) >>> downcore_df['outliers'] = detector.detect_outliers(downcore_df)
- Parameters:
features (list[str])
confidence (float)
method (Literal['chi2', 'chi2_rounddown'])
use_pinv_if_singular (bool)
- classmethod from_calibration(confidence=0.9)[source]#
Return a detector fixed to TEXAS’s published calibration domain.
Explicit form of the default behaviour: a detector on the standard features screens against this domain without being fitted at all.
The ellipse is a property of the calibration – Section 5.1 fits it to core-top samples with GDGT-2/GDGT-3 <= 5 – not of the data being screened. Fitting on your own record instead re-centres the ellipse onto that record, so the more unusual the record the less it flags: an all-warm Paleogene section would report nothing.
Examples
>>> detector = MahalanobisOutlierDetector.from_calibration() >>> df["flagged"] = detector.detect_outliers(df)
- Parameters:
confidence (float)
- Return type:
- fit(df, *, columns=None, on_unscorable='warn')[source]#
Fit mean, covariance, and threshold on training data.
- Parameters:
df (pd.DataFrame) – Training data
columns (dict, optional) – Mapping {logical_name: physical_column} for callers whose DataFrame uses different column names than
self.features.on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
self – Fitted detector instance
- Return type:
- transform(df, col_name=None, *, columns=None, on_unscorable='warn')[source]#
Compute Mahalanobis distances using fitted parameters.
- Parameters:
df (pd.DataFrame) – Data to transform
col_name (str, optional) – If provided, add distances to df as this column
columns (dict, optional) – Mapping {logical_name: physical_column}.
on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
distances – Mahalanobis distances
- Return type:
pd.Series
- detect_outliers(df, col_name=None, *, columns=None, on_unscorable='warn')[source]#
Detect outliers using fitted threshold.
- Parameters:
df (pd.DataFrame) – Data to screen
col_name (str, optional) – If provided, add outlier flags to df as this column
columns (dict, optional) – Mapping {logical_name: physical_column}.
on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
outliers – Boolean series (True=outlier, False=inlier, NaN=invalid)
- Return type:
pd.Series
- detect_outliers_manual(df, col_name=None, exclude_condition=None, *, columns=None, on_unscorable='warn')[source]#
Detect outliers using the manuscript’s screening criterion.
This is the recommended call for screening a record. It applies the calibration-domain ellipse and then restores the warm-end exception: samples with TEX86 > 0.75 and Scaled RI(0-3) > 0.75 are retained, not flagged, because the calibration itself retains them (Section 5.1, Fig. 4 – “data with TEX86 and Scaled RI above 0.75 are retained in the calibration dataset”). Screening with the bare ellipse instead (
detect_outliers()) would flag warm samples the calibration actually covers.Needs no
fit(): on the standard features the published calibration domain is adopted automatically.- Parameters:
df (pd.DataFrame) – Data to screen
col_name (str, optional) – If provided, add manual outlier flags to df as this column
exclude_condition (pd.Series, optional) – Boolean series indicating samples to exclude from outlier detection. If None, applies default: (ringIndex > 3) & (TEX86 > 0.7)
columns (dict, optional) – Mapping {logical_name: physical_column} for callers whose DataFrame uses different column names than
self.features.on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
manual_outliers – Boolean series with manual exceptions applied
- Return type:
pd.Series
Examples
>>> # Use default exception >>> outliers = detector.detect_outliers_manual(df) >>> >>> # Custom exception >>> custom_exclude = (df['SST'] > 30) & (df['TEX86'] > 0.8) >>> outliers = detector.detect_outliers_manual(df, exclude_condition=custom_exclude)
- fit_predict(df, col_name=None, *, columns=None, on_unscorable='warn')[source]#
Fit on df and flag its rows in one call (sklearn-style).
Equivalent to
fit(df)followed bydetect_outliers(df).Warning
This fits the ellipse on df itself, which is right when df is a reference/training set and wrong for screening a record against the calibration – the domain would move with the data, so an unusual record flags less rather than more. To screen your own data, just call
detect_outliers(): an unfitted detector on the standard features uses TEXAS’s published calibration domain automatically.- Parameters:
df (pd.DataFrame) – Data to fit on and screen
col_name (str, optional) – If provided, add outlier flags to df as this column
columns (dict, optional) – Mapping {logical_name: physical_column}.
on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
outliers – Boolean series (True=outlier, False=inlier, NaN=invalid)
- Return type:
pd.Series
- fit_transform(df, dist_col=None, outlier_col=None, manual_outlier_col=None, *, columns=None, on_unscorable='warn')[source]#
Fit and transform in one step.
- Parameters:
df (pd.DataFrame) – Training data
dist_col (str, optional) – Column name for distances
outlier_col (str, optional) – Column name for outlier flags
manual_outlier_col (str, optional) – Column name for manual outlier flags
columns (dict, optional) – Mapping {logical_name: physical_column}.
on_unscorable ({'warn', 'raise', 'ignore'}, default 'warn') – Policy for rows that map to a present column but are NaN/Inf.
- Returns:
results – Dictionary containing: - ‘distances’: Mahalanobis distances - ‘outliers’: Outlier flags - ‘manual_outliers’: Manual outlier flags - ‘threshold’: Computed threshold
- Return type:
dict
Data builders#
Build forward data#
- build_fwd_data(*, t_cul=None, proxy_cul=None, t_meso=None, proxy_meso=None, t_crtp=None, proxy_crtp=None, gdgt23ratio_crtp=None, sd_gdgt23ratio_crtp=None, no3_crtp=None, sd_no3_crtp=None, no3_cutoff=None, proxy_residuals_crtp=None, sd_proxyObs=None, R2_thermal=None, culmeso_posterior=None, prior_mean_t0=None, prior_sd_t0=None, prior_mean_k=None, prior_sd_k=None, prior_mean_b=None, prior_sd_b=None, prior_mean_v=None, prior_sd_v=None)[source]#
Build the Stan data dictionary for forward calibration models.
- Handles all forward model variants:
culmeso / Q1_culmeso / v1_culmeso : pass t_cul, proxy_cul, t_meso, proxy_meso
culmesocore : add t_crtp, proxy_crtp
hier_crtp_multiv : add gdgt23ratio_crtp, no3_crtp
hier_crtp_multiv_priorApprox : add culmeso_posterior (extracts hyperpriors)
hier_crtp_univ_priorApprox : add culmeso_posterior (no predictors needed)
- Parameters:
t_cul – Culture temperature and proxy arrays.
proxy_cul – Culture temperature and proxy arrays.
t_meso – Mesocosm temperature and proxy arrays.
proxy_meso – Mesocosm temperature and proxy arrays.
t_crtp – Coretop temperature and proxy arrays.
proxy_crtp – Coretop temperature and proxy arrays.
gdgt23ratio_crtp – GDGT-2/GDGT-3 ratio for coretop samples. Sets use_gdgt23ratio=1 if non-zero/non-NaN.
sd_gdgt23ratio_crtp – Per-site measurement SE of gdgt23ratio (same units, linear). Required for the _eiv model; always included in the data dict (defaults to zeros when not provided, which disables the G₂/₃ EIV measurement model).
no3_crtp – Nitrate concentration for coretop samples. Sets use_no3=1 if non-zero/non-NaN.
sd_no3_crtp – Per-site measurement SE of NO₃ (μmol/L, linear space). Required for the _eiv model. Always included (defaults to zeros; sites with sd=0 receive only the lognormal prior and skip the normal measurement model).
no3_cutoff (float | None) – NO3 threshold for the nonthermal correction. Priority: (1) this arg, (2) culmeso_posterior attrs, (3) auto-calculated via Spearman method.
proxy_residuals_crtp (ndarray | None) – Pre-computed proxy residuals for NO3 threshold calculation. If omitted, residuals are computed internally by fitting a generalized logistic curve. Warning: Stan models use generalized logistic — residuals from other functional forms may shift the threshold.
culmeso_posterior (Dataset | None) – xr.Dataset from a completed culmeso forward run. Auto-extracts prior_mean_*/prior_sd_* hyperpriors and no3_cutoff (if saved in attrs).
prior_mean_*/prior_sd_* – Manual hyperprior values. Override auto-extracted values from culmeso_posterior for individual params.
R2_thermal (float | None)
- Returns:
- Stan-ready data dict with proxyObs_* keys, N_* counts, use_* flags,
and hyperpriors — ready for get_posterior().
- Return type:
dict
Build invT input data#
- build_invT_inputData(proxyObs=None, prior_mu_t=None, prior_sigma_t=None, *, scaledRI=None, fwd_posterior_name=None, predictors=None, config=None, fwd_posterior=None, fwd_cache_dir=None)[source]#
Build the data dictionary for Stan’s inverse model and sampler configuration.
WORKFLOW: ───────── 1. Load forward calibration posterior from .nc file (or accept a pre-loaded Dataset) 2. Randomly sample M parameter sets from that posterior 3. Extract calibration curve parameters (t0, k, b, v, sigma) 4. Package optional environmental predictors (GDGT-2/3, NO3) if used 5. Return data dict (for Stan) + sampler_kwargs (for CmdStanPy)
- Parameters:
proxyObs (ndarray | List[float]) – Observed proxy values to predict temperature from (length N). Any proxy is accepted: scaledRI, TEX86, ringIndex, etc.
prior_mu_t (ndarray | float) – Prior mean temperature (scalar or array of length N)
prior_sigma_t (float) – Prior temperature uncertainty (e.g., 10°C)
fwd_posterior_name (str | None) – Name of saved forward calibration (without .nc extension). Not required when fwd_posterior is supplied directly.
predictors (Dict[str, ndarray] | None) – Optional environmental covariates {‘gdgt23ratio’: array, ‘no3’: array}
config (InvTConfig | None) – Configuration object controlling M, seed, etc.
fwd_posterior (Dataset | None) – Pre-loaded forward posterior xr.Dataset. When provided, fwd_posterior_name is ignored and no file I/O is performed. Useful when running from Google Colab or any pip-install context where the posterior cache is not available.
fwd_cache_dir (str | Path | None) – Directory to resolve fwd_posterior_name in. Defaults to the standard forward posterior cache. Use this to read posteriors from a project-local bundle without copying them into the cache.
scaledRI (ndarray | List[float])
- Returns:
Dictionary for Stan’s data block sampler_kwargs: Dictionary for CmdStanPy sampling configuration
- Return type:
data
InvT configuration#
WOA23 NO₃ lookup#
- lookup_no3_from_woa(lat, lon, woa_dataset, variable='no3_sf2tc_avg', method='linear')[source]#
Look up modern NO₃ at one or more lat/lon coordinates from a WOA23-derived xarray Dataset.
The dataset is typically the preprocessed
ocean_prop_dsgenerated in SI_code1, which contains thermocline-depth-integrated WOA23 climatology on a regular(lat, lon)grid. The returned value(s) are time-invariant (climatological mean) and intended as a modern-ocean proxy for the NO₃ correction in paleo reconstructions.- Parameters:
lat (float or array-like) – Latitude(s) in decimal degrees (−90 to 90). Pass a scalar for a single drill site; pass an array of length N to match N observations.
lon (float or array-like) – Longitude(s) in decimal degrees. Both −180–180 and 0–360 conventions are accepted — the function normalises to match the dataset’s convention automatically.
woa_dataset (xr.Dataset) – WOA23-derived dataset with a
(lat, lon)grid containing variable. Dimensions must be named"lat"and"lon".variable (str) – Name of the NO₃ variable to extract. Default
"no3_sf2tc_avg"(thermocline depth-integrated annual average from SI_code1).method ({"linear", "nearest"}) – Interpolation method.
"linear"(default) performs bilinear interpolation and is preferred for smooth fields."nearest"snaps to the closest grid cell and is useful when the dataset is sparse or has NaN-masked shelves.
- Returns:
NO₃ value(s) in µmol/L. Shape matches the scalar/array input: a 0-d array for scalar inputs, 1-d array of length N for array inputs. NaN is returned for locations outside the dataset’s valid range (e.g. continental shelves masked in WOA23).
- Return type:
np.ndarray
- Raises:
KeyError – If variable is not found in woa_dataset.
ValueError – If woa_dataset does not have
"lat"and"lon"dimensions.
Examples
Single drill site:
>>> no3_val = lookup_no3_from_woa(15.3, -23.7, ocean_prop_ds) >>> # returns scalar-equivalent float; broadcasts to all N obs automatically >>> result = predict_T_from_proxyObs(..., no3=no3_val)
Multi-site stack (per-obs lookup):
>>> no3_arr = lookup_no3_from_woa(core_df["lat"].values, ... core_df["lon"].values, ... ocean_prop_ds) >>> result = predict_T_from_proxyObs(..., no3=no3_arr)
Forward calibration#
Get posterior#
- get_posterior(data, stan_file, temptype, proxy_name, *, iter_warmup=None, iter_sampling=None, threads_per_chain=None, chains=None, parallel_chains=None, adapt_delta=None, max_treedepth=None, **kwargs)[source]#
Run forward calibration Stan sampling and return the posterior.
Wraps
StanSamplerwith automatic predictor detection, CPU configuration, and metadata attachment. The returned dataset can be passed directly topredict_proxy_from_Tor saved withsave_posterior.- Parameters:
data (dict) – Stan data dict built by
build_fwd_data(). Predictor flags (use_gdgt23ratio,use_no3) are auto-detected from the arrays present; you do not need to set them manually.stan_file (str) – Stan model name (without
.stan), e.g."gen_logi_fixed_hier_crtp_multiv_priorApprox_eiv".temptype (str) – Temperature variable type, e.g.
"SST"or"thermoT". Stored in the posterior metadata.proxy_name (str) – Proxy type, e.g.
"scaledRI_cren3". Required — stored in the.ncattrs and validated downstream when the posterior is used for inverse reconstruction.iter_warmup (int, optional) – HMC warmup iterations per chain (default: CmdStan default, 1000).
iter_sampling (int, optional) – Post-warmup sampling iterations per chain (default: 1000).
chains (int, optional) – Number of independent chains (default: 4).
parallel_chains (int, optional) – Chains to run simultaneously (auto-detected from CPU count).
threads_per_chain (int, optional) – Threads per chain for
reduce_summodels (auto-enabled for models whose filename containsreduce_sum).adapt_delta (float, optional) – Target acceptance rate (default: 0.8). Increase toward 0.99 to reduce divergences at the cost of more leapfrog steps.
max_treedepth (int, optional) – Maximum tree depth for HMC (default: 10).
**kwargs – Additional keyword arguments forwarded to
CmdStanModel.sample.
- Returns:
posterior (xr.Dataset) – Forward calibration posterior with parameter draws and metadata attrs (model name, temptype, proxy_name, priors, diagnostics).
diagnostics (str) – Human-readable sampler diagnostic summary (divergences, R-hat, ESS, E-BFMI).
- Raises:
ValueError – If active predictors are present but a univariate model is requested, or if an EIV model is requested without
R2_thermal.- Return type:
Tuple[Dataset, str]
Examples
>>> data = build_fwd_data(t_crtp=..., proxy_crtp=..., ...) >>> posterior, diag = get_posterior( ... data, ... stan_file="gen_logi_fixed_hier_crtp_univ_priorApprox", ... temptype="SST", ... proxy_name="scaledRI_cren3", ... ) >>> save_posterior(posterior)
Save posterior#
- save_posterior(posterior, cache_dir=None, overwrite=True, filename_suffix='', layout='auto', run='auto')[source]#
Save a forward-model posterior to disk as compressed NetCDF.
The filename is auto-generated from the posterior’s metadata attrs:
{model}_{temptype}[_gdgt23ratio][_no3_{cutoff}][_{proxy_name}]{suffix}.nc- Parameters:
posterior (xr.Dataset) – Forward calibration posterior returned by
get_posterior(). Must havestan_model_name,temptype, andproxy_nameattrs set (proxy_nameis required — a warning is raised if missing).cache_dir (str or Path, optional) – Directory to write the file. Defaults to the standard forward posterior cache (
data/cache/TEXAS_posterior_cache/for source installs,~/.texas/cache/TEXAS_posterior_cache/for pip installs).overwrite (bool) – If
False, raiseFileExistsErrorwhen the output path already exists. DefaultTrue.filename_suffix (str, optional) – Extra tag appended before
.ncunder the legacy layout, and the run/member token under the case layout. Leading/trailing underscores are stripped. Do not pass a date here. Filenames no longer carry date stamps; the run date is recorded in therun_timestampattr, where it survives a rename and does not have to be parsed back out of a path. Preferrun=for an explicit member.run (str or int, optional) – Optional run/member token under the case layout.
"auto"(default) writes no member, so a configuration has one canonical path and a re-run replaces it; pass a value only to keep a run deliberately apart. An explicit run wins over filename_suffix for the case path. Withoverwrite=Falsean existing file raisesFileExistsError.layout ({"auto", "case", "legacy"}) – Where to write.
"case"uses the CESM-style case directory (tx.v026.GHEB.sst.ri3.G23-N1p0/fwd.nc);"legacy"uses the historical long flat filename;"auto"(default) prefers the case layout and falls back to legacy with a warning if no case id can be derived. SeeTEXAS.utils.naming.
- Returns:
Absolute path of the saved
.ncfile.- Return type:
Path
Load posterior#
- load_posterior(model_name, model_type='forward', cache_dir=None)[source]#
Load a posterior from disk: {model_name}.nc in the appropriate cache directory.
- Parameters:
model_name (str) – Name of the model file (without .nc extension)
model_type (Literal['forward', 'invT']) – Type of posterior (“forward” or “invT”)
cache_dir (str | Path | None) – Custom cache directory (overrides default locations)
- Returns:
xarray.Dataset containing the posterior
- Raises:
FileNotFoundError – If the posterior file doesn’t exist
- Return type:
Dataset
Ensemble#
Generate ensemble (auto)#
- generate_ensemble_auto(post_ds, x_vals, model_type='auto', gdgt23ratio=None, no3=None, no3_cutoff=None, return_full_ensemble=False, suffix=None, **kwargs)[source]#
Sample draws from a forward posterior and compute calibration-curve percentiles.
Inspects the posterior’s
stan_model_nameattr anddata_varsto determine the model function, parameter names, and optional-predictor flags automatically, then delegates togenerate_ensemble.- Parameters:
post_ds (xr.Dataset) – Forward calibration posterior returned by
get_posterior()or loaded withload_posterior().x_vals (np.ndarray) – Temperature values (°C) at which to evaluate the calibration curve.
model_type ({"auto", "forward", "inverse"}) – Force forward or inverse dispatch;
"auto"(default) infers from the posterior. InvT posteriors are not supported — usepredict_T_from_proxyObs()instead.gdgt23ratio (np.ndarray, optional) – GDGT-2/3 ratio values; required when the posterior was fitted with a multivariate (GDGT-2/3) model.
no3 (np.ndarray, optional) – NO₃ concentrations (µmol/L); required when the posterior uses the NO₃ correction.
no3_cutoff (float, optional) – Override the NO₃ cutoff from the posterior attrs.
return_full_ensemble (bool) – If
True, return the full M × N draw matrix in addition to percentiles. DefaultFalse.suffix (str, optional) – Force a specific parameter suffix (e.g.
"crtp"); overrides auto-detection.**kwargs – Forwarded to
generate_ensemble.
- Returns:
Keys
"p1"…"p99"(and optionally"ensemble") — each a numpy array of lengthlen(x_vals).- Return type:
dict
- Raises:
NotImplementedError – If called with an invT posterior.
Detect model and params#
Diagnostics#
Sampler diagnostics#
Summary table#
Plotting#
Plot prior distributions#
- plot_prior_distributions(priors_list=None, posterior_datasets=None, posterior_labels_list=None, show_suptitle=True, kde_bw=0.3, focus_on_posterior=True, include_groups=('t0', 'k', 'b', 'v', 'a', 'beta_G23', 'beta_NO3', 'gamma_G23', 'gamma_NO3', 'betaLogit_G23', 'betaLogit_NO3', 'sigma_proxyObs'), suffix_include=None, zoomin_suffix=None, zoomin_dataset_idx=None, use_linestyle_by_param=False, show_histogram=True, show_annotation=False, set_linewidth=1.5, set_fig_width_factor=3, set_fig_height_factor=3.5, set_leg_max_ncol=3, color_list=None, param_source_map=None, annotation_style='ci95', show_subplot_legend=True, show_figure_legend=True, show_prior_expression=True, cache_dir=None)[source]#
Plot priors + any number of posterior distributions in a grid, split by parameter group (t0, k, b, etc.).
- Parameters:
param_source_map (Dict[str, int] | None) –
Optional dict mapping a param group name to the index of the dataset in
posterior_datasetsthat should be used as the sole source for that group. All other datasets are skipped for that group.Use this when different parameters come from different posteriors — e.g. logistic params (t0, k, b…) from a
culmesorun and beta coefficients from a multivariatecrtprun:plot_prior_distributions( posterior_datasets=[culmeso_ds, crtp_multiv_ds], param_source_map={"beta_G23": 1, "beta_NO3": 1}, )
When a group is not in
param_source_map, all datasets are searched as usual.include_groups (Sequence[str]) – Parameter-group prefixes to draw, in panel order. The default covers the thermal parameters plus every coefficient naming scheme in
PREDICTOR_GROUPS(beta_*for the parent model,gamma_*for t0shift,betaLogit_*for boundedCeil), so the same call works for any of them and for figures mixing several. A group with no matching variable in any dataset is skipped, as is a coefficient group whose predictor no dataset switched on.cache_dir (str | Path | None) – Directory to resolve any name strings in
posterior_datasets. Defaults to the standard forward posterior cache. Loaded Datasets are passed through untouched.priors_list (List[str] | Dict[str, str] | None)
posterior_datasets (List[xr.Dataset] | None)
posterior_labels_list (List[str] | None)
show_suptitle (bool)
kde_bw (float)
focus_on_posterior (bool)
suffix_include (List[str] | None)
zoomin_suffix (str | List[str] | None)
zoomin_dataset_idx (int | None)
use_linestyle_by_param (bool)
show_histogram (bool)
show_annotation (bool)
set_linewidth (float)
set_fig_width_factor (float)
set_fig_height_factor (float)
set_leg_max_ncol (int)
color_list (Sequence[str] | None)
annotation_style (Literal['ci95', 'ci68', 'sigma'])
show_subplot_legend (bool)
show_figure_legend (bool)
show_prior_expression (bool)