knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
This vignette documents the calculation of the spectral transfer functions for the effects of vapour diffusion and time uncertainty. The transfer functions describe the loss in spectral power as a function of frequency that is expected due to these two processes: for time uncertainty, the loss applies to the spectrum of the common signal recorded by the spatial average of an array of proxy records (the "stacked" record); for diffusion, it applies to the loss in average spectral power of the individual records. Proxy records refer here, more specifically, to any proxy time series that are based on layer counting in the case of time uncertainty and to stable isotope records from firn/ice cores in the case of diffusion.
The documentation utilises as examples the code for calculating the transfer functions for the DML and WAIS isotope records studied in Münch and Laepple (2018). In there, you will also find a detailed description of the basic method (see Appendix B).
library(proxysnr)
For the modelling of time uncertainty we need the package simproxyage:
# check if package is available pkg.flag <- requireNamespace("simproxyage", quietly = TRUE) if (!pkg.flag) { message(paste("Package \"simproxyage\" not found.", "No time uncertainty transfer functions will be calculated.")) } else { library(simproxyage) }
If you have installed proxysnr without additionally installing the package
simproxyage and you try to rebuild this vignette, you will receive the
warning message here that simproxyage is not available; then, no time
uncertainty transfer functions can be calculated. To do so, head over to the
github page for
simproxyage and install the package using remotes::install_github
.
First, we set general parameters that are required for the calculations.
We set a seed for reproducible results:
set.seed(4122018)
For convenience, list objects are used for saving the transfer functions:
# for diffusion transfer function dtf <- list() # for time uncertainty transfer function ttf <- list()
A specific resolution of the created surrogate white noise time series is used for the diffusion calculations, for which, in general, a higher resolution compared to the target resolution of the isotope records is adopted. This is necessary for numerical stability of the diffusion results at the high-frequency end.
Here, the target resolution of the isotope records is 1 yr (annual resolution) and a simulation resolution of 0.5 yr has proven sufficient for the numerical stability of the results:
res <- 1/2
If the simulation resolution differs from the target resolution, also the simulated frequency axis of the diffusion transfer function will differ from the respective frequency axis of the proxy spectra. Therefore, the transfer functions are interpolated in frequency space on the target frequency axis of the proxy spectra, which hence needs to be supplied.
Here, for convenience, we load the required target frequency axes from the data supplied with the package.
ff <- list() ff$dml1 <- diffusion.tf$dml1$freq ff$dml2 <- diffusion.tf$dml2$freq ff$wais <- diffusion.tf$wais$freq
Finally, we specify the number of Monte Carlo simulations used to obtain the transfer functions. In general, an average of a large number of simulations is needed to reduce the spectral uncertainties and obtain smooth estimates. However, since this takes considerable amount of computation time, for the vignette building only a small number of simulations is used here:
ns <- 10
Note that for the results of Münch and Laepple (2018), ns
has been set to
100,000
, which required a computation time of 1--3 hours depending on the data
set (using a 2.4 GHz Intel Core i5 processor).
In the following, we document all data-set-specific parameters needed for the calculations along the example of the DML1 data set of isotope records.
Specify the number of proxy records ("cores") in the studied array:
nc <- 15
Specify the time axis common to all proxy records in the array in units of the original (target) resolution of the records (here, years), which gives the number of proxy data points:
# set time axis t <- seq(1994, 1801) # number of proxy data points nt <- length(t)
Specify the time points of age control points where the time uncertainty is assumed to be zero:
acp <- c(1994, 1884, 1816, 1810)
Set the rate of the random process which perturbs the proxy record chronologies, so here the rate of missing or double-counting of a layer. We use symmetric rates here:
rate <- 0.013
Specify a numeric vector with two entries to use asymmetric rates.
For the diffusion simulations, estimates of the diffusion length (in units of
the record resolution) are needed as a function of time since deposition (see
the parameter sigma
in the call of the function DiffusionTF
below, and
?DiffusionTF
). Along with proxysnr, the diffusion length estimates for the
DML and WAIS cores are provided in diffusion.length
; for details see
?diffusion.length
. Calculation of these estimates is documented in the package
source under ./data-raw/calculate-diffusion-length.R
, where .
is the root of
the package source directory. The relevant site parameters needed for the
diffusion length calculations are provided in clim.site.par
; for details see
?clim.site.par
. For further information see the publication Münch and Laepple
(2018).
Finally, run the calculations and store only the ratio of average output over input spectra, i.e. the transfer function.
Run the diffusion model:
tmp <- DiffusionTF(nt = nt / res, nc = nc, ns = ns, sigma = diffusion.length$dml1[, -1], res = res)$ratio
Since we used a certain simulation resolution, we have to interpolate onto the target resolution of our proxy data. Additionally, we store meta data on the simulations:
dtf$dml1 <- tmp dtf$dml1$freq <- ff$dml1 dtf$dml1$spec <- approx(tmp$freq, tmp$spec, dtf$dml1$freq)$y attr(dtf$dml1, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(dtf$dml1, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(dtf$dml1, "log-smooth") <- "Log-smooth applied: No." class(dtf$dml1) <- "spec"
Run the time uncertainty model with Gaussian white noise as the surrogate data and document the meta data:
if (pkg.flag) { ttf$dml1 <- TimeUncertaintyTF(t = t, acp = acp, nt = nt, nc = nc, ns = ns, rate = rate, surrogate.fun = rnorm)$ratio } else { ttf$dml1$freq <- dtf$dml1$freq ttf$dml1$spec <- rep(NA, length(dtf$dml1$freq)) } attr(ttf$dml1, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(ttf$dml1, "rate") <- sprintf("Process rate used: %1.3f.", rate) attr(ttf$dml1, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(ttf$dml1, "log-smooth") <- "Log-smooth applied: No." class(ttf$dml1) <- "spec"
We run the calculations for the DML2 isotope records...
nc <- 3 t <- seq(1994, 1000) nt <- length(t) acp <- c(1994, 1884, 1816, 1810, 1459, 1259) rate <- 0.013 tmp <- DiffusionTF(nt = nt / res, nc = nc, ns = ns, sigma = diffusion.length$dml2[, -1], res = res)$ratio dtf$dml2 <- tmp dtf$dml2$freq <- ff$dml2 dtf$dml2$spec <- approx(tmp$freq, tmp$spec, dtf$dml2$freq)$y if (pkg.flag) { ttf$dml2 <- TimeUncertaintyTF(t = t, acp = acp, nt = nt, nc = nc, ns = ns, rate = rate, surrogate.fun = rnorm)$ratio } else { ttf$dml2$freq <- dtf$dml2$freq ttf$dml2$spec <- rep(NA, length(dtf$dml2$freq)) } attr(dtf$dml2, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(dtf$dml2, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(dtf$dml2, "log-smooth") <- "Log-smooth applied: No." attr(ttf$dml2, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(ttf$dml2, "rate") <- sprintf("Process rate used: %1.3f.", rate) attr(ttf$dml2, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(ttf$dml2, "log-smooth") <- "Log-smooth applied: No." class(dtf$dml2) <- "spec" class(ttf$dml2) <- "spec"
... and the WAIS isotope records:
nc <- 5 t <- seq(2000, 1800) nt <- length(t) acp <- c(2000, 1992, 1964, 1885, 1837, 1816, 1810) rate <- 0.027 tmp <- DiffusionTF(nt = nt / res, nc = nc, ns = ns, sigma = diffusion.length$wais[, -1], res = res)$ratio dtf$wais <- tmp dtf$wais$freq <- ff$wais dtf$wais$spec <- approx(tmp$freq, tmp$spec, dtf$wais$freq)$y if (pkg.flag) { ttf$wais <- TimeUncertaintyTF(t = t, acp = acp, nt = nt, nc = nc, ns = ns, rate = rate, surrogate.fun = rnorm)$ratio } else { ttf$wais$freq <- dtf$wais$freq ttf$wais$spec <- rep(NA, length(dtf$wais$freq)) } attr(dtf$wais, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(dtf$wais, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(dtf$wais, "log-smooth") <- "Log-smooth applied: No." attr(ttf$wais, "version") <- sprintf("Creation date: %s.", Sys.time()) attr(ttf$wais, "rate") <- sprintf("Process rate used: %1.3f.", rate) attr(ttf$wais, "N.sim") <- sprintf("Number of simulations used: N = %s", formatC(ns, big.mark = ",", format = "d")) attr(ttf$wais, "log-smooth") <- "Log-smooth applied: No." class(dtf$wais) <- "spec" class(ttf$wais) <- "spec"
The obtained transfer functions can be plotted with:
PlotTF(dtf = dtf, ttf = ttf, names = c("DML1", "DML2", "WAIS"), col = c("black", "firebrick", "dodgerblue"))
The transfer functions for simulations with ns = 10^5
as used and shown in
Münch and Laepple (2018) are provided along proxysnr in the variables
diffusion.tf
and time.uncertainty.tf
; see ?diffusion.tf
,
?time.uncertainty.tf
, str(diffusion.tf)
, str(time.uncertainty.tf)
for details.
These can be plotted by simply calling
PlotTF(names = c("DML1", "DML2", "WAIS"), col = c("black", "firebrick", "dodgerblue"))
Münch, T. and Laepple, T.: What climate signal is contained in decadal- to centennial-scale isotope variations from Antarctic ice cores?, Clim. Past, 14, 2053-2070, doi: 10.5194/cp-14-2053-2018, 2018.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.