| Type: | Package |
| Title: | Time of Emergence of Climate Signals from Internal Variability |
| Version: | 0.1.0 |
| Description: | Detects when a forced climate change signal emerges from internal variability ('time of emergence') in annual climate time series such as temperature or precipitation. The signal is estimated with a linear, quadratic or locally weighted smoother and compared with noise estimated from a baseline period. Emergence is defined through configurable signal-to-noise thresholds and persistence rules. Uncertainty in the time of emergence is quantified by autoregressive or moving-block bootstrap resampling. Helpers are provided for multi-member ensembles, threshold sensitivity, anomaly and annual aggregation, Mann-Kendall trend tests with trend-free prewhitening, and synthetic data generation. The approach builds on Hawkins and Sutton (2012) <doi:10.1029/2011GL050087>, Yue et al. (2002) <doi:10.1002/hyp.1095> and Sen (1968) <doi:10.1080/01621459.1968.10480934>. |
| License: | MIT + file LICENSE |
| Depends: | R (≥ 3.5.0) |
| Imports: | graphics, grDevices, stats |
| Suggests: | knitr, rmarkdown, testthat (≥ 3.0.0) |
| VignetteBuilder: | knitr |
| Config/testthat/edition: | 3 |
| Encoding: | UTF-8 |
| LazyData: | true |
| RoxygenNote: | 7.3.1 |
| NeedsCompilation: | no |
| Packaged: | 2026-09-30 09:32:57 UTC; root |
| Author: | Abul Kashem Faruki Fahim
|
| Maintainer: | Abul Kashem Faruki Fahim <farukifahim@du.ac.bd> |
| Repository: | CRAN |
| Date/Publication: | 2026-10-10 10:50:02 UTC |
toeclim: Time of Emergence of Climate Signals from Internal Variability
Description
Tools for answering the question "when does the forced climate change signal in this time series become distinguishable from natural variability?". The package estimates a smooth signal, a noise level from a baseline period, and reports the time of emergence (ToE): the first time the signal-to-noise ratio exceeds a chosen threshold and stays there.
Workflow
Prepare data with
toe_annual()andtoe_anomaly().Characterise the record with
toe_trend()andtoe_noise().Estimate emergence for one series with
toe_emerge(), or for an ensemble withtoe_ensemble().Quantify robustness with the bootstrap in
toe_emerge(), withtoe_prob()and withtoe_sensitivity().Test methods on synthetic data from
toe_simulate()or the bundled toe_example data set.
Author(s)
Maintainer: Abul Kashem Faruki Fahim farukifahim@du.ac.bd (ORCID) [copyright holder]
References
Hawkins, E. and Sutton, R. (2012). Time of emergence of climate signals. Geophysical Research Letters, 39, L01702. doi:10.1029/2011GL050087
Yue, S., Pilon, P., Phinney, B. and Cavadias, G. (2002). The influence of autocorrelation on the ability to detect trend in hydrological series. Hydrological Processes, 16, 1807-1829. doi:10.1002/hyp.1095
Sen, P. K. (1968). Estimates of the regression coefficient based on Kendall's tau. Journal of the American Statistical Association, 63, 1379-1389. doi:10.1080/01621459.1968.10480934
Plot a time-of-emergence analysis
Description
Draws the observed series, the fitted signal, the noise envelope
(baseline mean +/- k * sigma) and the time of emergence. If a bootstrap
was run, its interval is shaded.
Usage
## S3 method for class 'toe'
plot(x, xlab = "Time", ylab = "Value", main = "Time of emergence", ...)
Arguments
x |
A |
xlab, ylab |
Axis labels. |
main |
Title. |
... |
Further arguments passed to |
Value
x, invisibly.
Examples
d <- toe_simulate(n_years = 150, slope = 0.03, onset = 1970, seed = 8)
plot(toe_emerge(d$member_01, d$year, baseline = c(1900, 1950)))
Plot ensemble time of emergence
Description
Shows every member (thin lines), the ensemble mean, the pooled emergence time and a rug of the individual member emergence times.
Usage
## S3 method for class 'toe_ensemble'
plot(
x,
xlab = "Time",
ylab = "Value",
main = "Ensemble time of emergence",
...
)
Arguments
x |
A |
xlab, ylab |
Axis labels. |
main |
Title. |
... |
Further arguments passed to |
Value
x, invisibly.
Examples
d <- toe_simulate(n_years = 150, onset = 1970, n_members = 6, seed = 9)
ens <- toe_ensemble(d[, grep("^member", names(d))], d$year,
baseline = c(1900, 1950))
plot(ens)
Aggregate sub-annual data to annual values
Description
Collapses monthly, daily or other sub-annual observations to one value per
calendar year. Years with too few valid observations are set to NA so that
partial years do not bias the annual statistic.
Usage
toe_annual(x, dates, fun = mean, min_frac = 0.8)
Arguments
x |
Numeric vector of observations. |
dates |
Vector of the same length as |
fun |
Function used to aggregate within each year. Defaults to
|
min_frac |
Minimum fraction (0 to 1) of the maximum number of
observations per year that must be non-missing for a year to be kept.
Defaults to |
Value
A data frame with columns year, value (the aggregated value,
NA for incomplete years) and n (number of valid observations).
See Also
Examples
dates <- seq(as.Date("2000-01-01"), as.Date("2004-12-01"), by = "month")
x <- rnorm(length(dates), mean = 10)
x[c(3, 4, 5, 6, 7, 8)] <- NA # a gappy year
toe_annual(x, dates)
Compute anomalies relative to a baseline climatology
Description
Subtracts a climatological mean, computed over a baseline period, from every observation. The climatology can be a single mean or can be resolved by calendar month or day of year to remove the seasonal cycle.
Usage
toe_anomaly(x, time, baseline, by = c("none", "month", "day"))
Arguments
x |
Numeric vector of observations. |
time |
Either numeric years (only with |
baseline |
Numeric vector |
by |
Resolution of the climatology: |
Value
A data frame with columns time, value, climatology and
anomaly.
See Also
Examples
dates <- seq(as.Date("1980-01-01"), as.Date("2019-12-01"), by = "month")
x <- 10 + 8 * sin(2 * pi * (as.integer(format(dates, "%m")) - 1) / 12) +
rnorm(length(dates))
a <- toe_anomaly(x, dates, baseline = c(1981, 2010), by = "month")
head(a)
Time of emergence of a climate signal
Description
Estimates when a forced signal becomes distinguishable from internal
variability in a single time series. The series is decomposed into a smooth
signal (relative to the baseline mean) and noise (standard deviation
estimated from the baseline period or from residuals). The time of
emergence is the first time after the baseline at which the
signal-to-noise ratio |S/N| reaches k and persistence criteria are met.
Usage
toe_emerge(
x,
time = NULL,
baseline,
signal = c("quadratic", "linear", "loess"),
span = 0.5,
k = 2,
persist = 5L,
sustain = c("window", "end"),
noise = c("baseline", "residual"),
direction = c("both", "positive", "negative"),
n_boot = 0L,
boot = c("ar1", "block"),
block_length = NULL,
conf_level = 0.9,
seed = NULL
)
Arguments
x |
Numeric vector, typically annual anomalies or annual means. Missing values are dropped with a warning. |
time |
Numeric vector of times (e.g. years), strictly increasing. If
|
baseline |
Numeric vector |
signal |
Signal estimator: |
span |
Smoothing span for |
k |
Signal-to-noise threshold in units of noise standard deviations.
Default |
persist |
Minimum number of consecutive time steps for which the
threshold must be exceeded. Default |
sustain |
How persistence is judged. |
noise |
Noise estimator. |
direction |
Direction of change that counts as emergence: |
n_boot |
Number of bootstrap replicates used to quantify uncertainty in
the time of emergence. |
boot |
Bootstrap scheme: |
block_length |
Block length for |
conf_level |
Confidence level for the bootstrap interval. Default
|
seed |
Optional integer seed. The global random number state is restored on exit. |
Details
The bootstrap resamples residuals around the fitted signal, adds them back
to the signal, and repeats the entire procedure (signal fit, noise
estimate and emergence rule). The resulting distribution of emergence times
includes NA for replicates that never emerge; the proportion that
emerge is reported as prob_emerged. The interval is computed from the
replicates that do emerge.
Persistence is counted in observations, so time should be regularly
spaced (e.g. annual).
Value
An object of class toe, a list with elements
toeTime of emergence, or
NAif the signal never emerges.dataData frame with
time,value,signal(fit minus baseline mean),snrandexceed.sigmaNoise standard deviation used.
baseline_meanBaseline mean of
x.bootNULL, or a list withtoe(vector of replicate times),ci,prob_emerged,conf_levelandmethod.paramsThe settings used.
Choosing the signal model
Forced climate responses are rarely straight lines: they are often flat
and then accelerate. A straight-line fit to such a record is too high early
on and can cross the noise threshold before the change actually begins.
In a simulation study bundled with the package's development (200 series,
true onset 1970, true emergence about 1990), a linear signal produced a
median emergence year of 1971 and emerged before onset in 35% of series,
whereas quadratic and loess signals gave medians of 1990 and 1989 and
never emerged before onset. "quadratic" is therefore the default. Use
"linear" only when a constant rate of change is plausible.
References
Hawkins, E. and Sutton, R. (2012) doi:10.1029/2011GL050087.
See Also
toe_ensemble(), toe_sensitivity(), toe_prob(),
toe_noise(), toe_simulate()
Examples
d <- toe_simulate(n_years = 150, slope = 0.03, onset = 1970,
sigma = 0.3, phi = 0.5, seed = 10)
fit <- toe_emerge(d$member_01, d$year, baseline = c(1900, 1950))
fit
# With bootstrap uncertainty (small n_boot to keep the example fast)
fit_b <- toe_emerge(d$member_01, d$year, baseline = c(1900, 1950),
n_boot = 100, seed = 1)
fit_b$boot$ci
plot(fit_b)
Time of emergence across an ensemble
Description
Applies toe_emerge() to every member of a multi-member ensemble (e.g. a
climate model initial-condition large ensemble) and summarises the spread
of emergence times. Optionally also estimates a pooled emergence time
from the ensemble-mean signal against the average single-member noise.
Usage
toe_ensemble(x, time = NULL, baseline, pooled = TRUE, ...)
Arguments
x |
A numeric matrix or data frame with one row per time step and one column per ensemble member. |
time |
Numeric vector of times with length |
baseline |
Numeric vector |
pooled |
Logical. Also estimate the pooled ensemble-mean emergence?
Default |
... |
Further arguments passed to |
Value
An object of class toe_ensemble, a list with
membersData frame with
member,toeandsigma.summaryNamed vector:
n,n_emerged,median,min,max,q05,q95of member emergence times (over members that emerge).pooledA
toeobject for the ensemble mean (orNULL).dataData frame of
timeand the input members.
See Also
Examples
d <- toe_simulate(n_years = 150, slope = 0.03, onset = 1970,
n_members = 8, seed = 4)
ens <- toe_ensemble(d[, grep("^member", names(d))], d$year,
baseline = c(1900, 1950))
ens
Synthetic 10-member ensemble of annual temperature anomalies
Description
A synthetic data set that mimics a regional annual-mean temperature
anomaly from a single-model initial-condition large ensemble. It is
generated with toe_simulate() and is intended for examples, tests and
teaching; it does not represent any real model or observation.
Usage
toe_example
Format
A data frame with 201 rows (1900-2100) and 12 variables:
- year
Calendar year.
- forced
The true forced response (degrees C), known by construction.
- member_01, member_02, member_03, member_04, member_05, member_06, member_07, member_08, member_09, member_10
Annual anomaly (degrees C) for each ensemble member.
Details
The forced response is flat until 1980 and then warms at 0.03 degrees C per year. Noise is AR(1) with standard deviation 0.35 and lag-1 autocorrelation 0.6.
Source
Simulated; see data-raw/toe_example.R.
See Also
toe_simulate(), toe_ensemble()
Examples
head(toe_example[, 1:4])
Estimate internal variability (noise)
Description
Removes a smooth signal from a series and characterises what is left: its standard deviation, lag-1 autocorrelation and the effective number of independent samples.
Usage
toe_noise(
x,
time = NULL,
signal = c("quadratic", "linear", "loess"),
span = 0.5
)
Arguments
x |
Numeric vector. |
time |
Numeric vector of times, strictly increasing. If |
signal |
Signal model removed before computing noise statistics:
|
span |
Smoothing span for |
Value
A list with elements sigma (residual standard deviation, adjusted
for the degrees of freedom used by the signal model), phi (lag-1
autocorrelation), n_eff (effective sample size,
n * (1 - phi) / (1 + phi), capped at n), residuals and signal.
See Also
Examples
d <- toe_simulate(n_years = 100, sigma = 0.3, phi = 0.6, seed = 42)
str(toe_noise(d$member_01, d$year)[c("sigma", "phi", "n_eff")])
Probability of emergence by a given time
Description
Uses the bootstrap distribution stored in a toe_emerge() result to
estimate the probability that the signal has emerged by each of the
supplied times, P(ToE <= t). Replicates that never emerge count as "not
emerged".
Usage
toe_prob(object, times)
Arguments
object |
A |
times |
Numeric vector of times at which to evaluate the probability. |
Value
A data frame with columns time and prob.
See Also
Examples
d <- toe_simulate(n_years = 150, slope = 0.03, onset = 1970, seed = 3)
f <- toe_emerge(d$member_01, d$year, baseline = c(1900, 1950),
n_boot = 100, seed = 2)
toe_prob(f, times = c(1990, 2000, 2010, 2030))
Sensitivity of the time of emergence to threshold choices
Description
Re-estimates emergence over a grid of signal-to-noise thresholds k and
persistence lengths, making the dependence on these subjective choices
explicit.
Usage
toe_sensitivity(
x,
time = NULL,
baseline,
k = c(1, 2, 3),
persist = c(1, 5, 10),
...
)
Arguments
x |
Numeric vector, typically annual anomalies or annual means. Missing values are dropped with a warning. |
time |
Numeric vector of times (e.g. years), strictly increasing. If
|
baseline |
Numeric vector |
k |
Numeric vector of thresholds. |
persist |
Numeric vector of persistence lengths. |
... |
Further arguments passed to |
Value
A data frame with columns k, persist and toe.
See Also
Examples
d <- toe_simulate(n_years = 150, slope = 0.03, onset = 1970, seed = 5)
toe_sensitivity(d$member_01, d$year, baseline = c(1900, 1950),
k = c(1, 2, 3), persist = c(1, 5, 10))
Simulate synthetic climate series with a known forced signal
Description
Generates annual series consisting of a piecewise-linear forced response
(flat until onset, then rising at slope per year) plus stationary AR(1)
noise. Useful for testing emergence methods against a known truth.
Usage
toe_simulate(
n_years = 150,
start = 1900,
slope = 0.03,
onset = start + 60,
sigma = 0.3,
phi = 0.5,
n_members = 1,
seed = NULL
)
Arguments
n_years |
Number of years. Default |
start |
First year. Default |
slope |
Forced trend after |
onset |
Year at which the trend begins. Default |
sigma |
Marginal standard deviation of the noise. Default |
phi |
Lag-1 autocorrelation of the noise, between -1 and 1 (exclusive).
Default |
n_members |
Number of independent noise realisations (ensemble
members). Default |
seed |
Optional integer seed; the global random state is restored. |
Value
A data frame with columns year, forced (the true forced
response) and one column per member named member_01, member_02, ...
See Also
Examples
d <- toe_simulate(n_years = 100, n_members = 3, seed = 1)
head(d)
Robust trend test: Sen's slope with a Mann-Kendall test
Description
Estimates the linear trend with the Theil-Sen estimator and tests its significance with the Mann-Kendall test. Because serial correlation inflates false-positive rates, the test optionally applies trend-free prewhitening (TFPW; Yue et al., 2002) when the lag-1 autocorrelation of the detrended series is significant.
Usage
toe_trend(x, time = NULL, conf_level = 0.95, prewhiten = TRUE)
Arguments
x |
Numeric vector. |
time |
Numeric vector of times (e.g. years), strictly increasing. If
|
conf_level |
Confidence level for the slope interval. Default |
prewhiten |
Logical; apply trend-free prewhitening when lag-1
autocorrelation is significant? Default |
Value
An object of class toe_trend, a list with elements slope,
intercept, slope_ci, conf_level, S (Mann-Kendall statistic),
z, p_value, n, r1 (lag-1 autocorrelation of detrended data),
prewhitened (logical) and call. The slope is in units of x per unit
of time.
References
Sen (1968) doi:10.1080/01621459.1968.10480934; Yue et al. (2002) doi:10.1002/hyp.1095.
See Also
Examples
d <- toe_simulate(n_years = 80, slope = 0.02, onset = 1900, seed = 1)
toe_trend(d$member_01, d$year)