1 |
# F14C <> BP14C |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname F14C |
|
7 |
#' @aliases BP14C_to_F14C,numeric,numeric-method |
|
8 |
setMethod( |
|
9 |
f = "BP14C_to_F14C", |
|
10 |
signature = c(values = "numeric", errors = "numeric"), |
|
11 |
definition = function(values, errors, lambda = 8033) { |
|
12 | 1x |
values <- exp(values / -lambda) |
13 | 1x |
sigma <- values * errors / lambda |
14 | 1x |
data.frame(value = values, error = sigma) |
15 |
} |
|
16 |
) |
|
17 | ||
18 |
#' @export |
|
19 |
#' @rdname F14C |
|
20 |
#' @aliases F14C_to_BP14C,numeric,numeric-method |
|
21 |
setMethod( |
|
22 |
f = "F14C_to_BP14C", |
|
23 |
signature = c(values = "numeric", errors = "numeric"), |
|
24 |
definition = function(values, errors, lambda = 8033, asymmetric = FALSE, |
|
25 |
rounding = getOption("ananke.round")) { |
|
26 |
## Validation |
|
27 | 5x |
choices <- c("none", "stuiver") |
28 | 5x |
rounding <- match.arg(rounding, choices = choices, several.ok = FALSE) |
29 | ||
30 | 5x |
z <- values |
31 | ||
32 |
## van der Plicht and Hogg 2006, p. 239 |
|
33 | 5x |
below_2sigma <- z < 2 * errors |
34 | 5x |
values[below_2sigma] <- values[below_2sigma] + 2 * errors[below_2sigma] |
35 | ||
36 | 5x |
below_zero <- z < 0 |
37 | 5x |
values[below_zero] <- 2 * errors[below_zero] |
38 | ||
39 |
## van der Plicht and Hogg 2006, eq. 6 |
|
40 |
## Bronk Ramsey 2008, p. 260 |
|
41 | 5x |
ages <- -lambda * log(values) |
42 | 5x |
sigma <- lambda * errors / values |
43 | ||
44 | 5x |
sigma_plus <- sigma_minus <- sigma |
45 | 5x |
if (asymmetric) { |
46 | 3x |
sigma_plus <- - lambda * log(values - errors) - ages |
47 | 3x |
sigma_minus <- ages + lambda * log(values + errors) |
48 |
} |
|
49 | ||
50 | 5x |
sigma_plus[below_zero | below_2sigma] <- NA_real_ |
51 | 5x |
sigma_minus[below_zero | below_2sigma] <- NA_real_ |
52 | ||
53 |
## The reported age can be no older than the radiocarbon age of the |
|
54 |
## fraction modern of the sample plus it's error |
|
55 |
# limit <- -lambda * log(values + errors) |
|
56 |
# ages[ages > limit] <- limit[ages > limit] |
|
57 | ||
58 |
## Rounding |
|
59 | 5x |
if (identical(rounding, "stuiver")) { |
60 | 2x |
ages <- round_values_stuiver(ages) |
61 | 2x |
sigma_plus <- round_errors_stuiver(sigma_plus) |
62 | 2x |
sigma_minus <- round_errors_stuiver(sigma_minus) |
63 |
} |
|
64 | ||
65 | 5x |
data.frame(age = ages, plus = sigma_plus, minus = sigma_minus) |
66 |
} |
|
67 |
) |
|
68 | ||
69 |
## Stuiver & Polach (1977), p. 362 |
|
70 |
round_any <- function(x, accuracy, f = round) { |
|
71 | 31x |
f(x / accuracy) * accuracy |
72 |
} |
|
73 |
round_values_stuiver <- function(x) { |
|
74 | 4x |
y <- x[!is.na(x)] |
75 | 4x |
y[y < 1000] <- round_any(y[y < 1000], 5) |
76 | 4x |
y[1000 <= y & y <= 9999] <- round_any(y[1000 <= y & y < 9999], 10) |
77 | 4x |
y[10000 <= y & y <= 20000] <- round_any(y[10000 <= y & y <= 20000], 50) |
78 | 4x |
y[y > 20000] <- round_any(y[y > 20000], 100) |
79 | 4x |
x[!is.na(x)] <- y |
80 | 4x |
x |
81 |
} |
|
82 |
round_errors_stuiver <- function(x) { |
|
83 | 5x |
y <- x[!is.na(x)] |
84 | 5x |
y[y < 50] <- round_any(y[y < 50], 5) |
85 | 5x |
y[50 <= y & y <= 1000] <- round_any(y[50 <= y & y <= 1000], 10) |
86 | 5x |
y[y > 1000] <- round_any(y[y > 1000], 100) |
87 | 5x |
x[!is.na(x)] <- y |
88 | 5x |
x |
89 |
} |
1 |
# 14C CALIBRATION |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname c14_calibrate |
|
7 |
#' @aliases c14_calibrate,numeric,numeric-method |
|
8 |
setMethod( |
|
9 |
f = "c14_calibrate", |
|
10 |
signature = signature(values = "numeric", errors = "numeric"), |
|
11 |
definition = function(values, errors, curves = "intcal20", |
|
12 |
names = NULL, positions = NULL, |
|
13 |
reservoir_offsets = 0, reservoir_errors = 0, |
|
14 |
from = 55000, to = 0, resolution = 1, |
|
15 |
normalize = TRUE, F14C = FALSE, |
|
16 |
method = c("student", "normal"), |
|
17 |
dfs = 100, drop = TRUE, eps = 1e-06, |
|
18 |
verbose = getOption("ananke.verbose")) { |
|
19 |
## Validation |
|
20 | 10x |
method <- match.arg(method) |
21 | 10x |
n <- length(values) |
22 | 8x |
if (is.null(names)) names <- paste0("X", seq_len(n)) |
23 | 10x |
if (is.null(positions)) positions <- values |
24 | 10x |
if (length(curves) == 1) |
25 | 10x |
curves <- rep(curves, n) |
26 | 10x |
if (length(reservoir_offsets) == 1) |
27 | 10x |
reservoir_offsets <- rep(reservoir_offsets, n) |
28 | 10x |
if (length(reservoir_errors) == 1) |
29 | 10x |
reservoir_errors <- rep(reservoir_errors, n) |
30 | 10x |
if (length(dfs) == 1) |
31 | 10x |
dfs <- rep(dfs, n) |
32 | ||
33 | 10x |
arkhe::assert_missing(values) |
34 | 10x |
arkhe::assert_missing(errors) |
35 | 10x |
arkhe::assert_unique(names) |
36 | 10x |
arkhe::assert_length(errors, n) |
37 | 10x |
arkhe::assert_length(names, n) |
38 | 10x |
arkhe::assert_length(curves, n) |
39 | 10x |
arkhe::assert_length(reservoir_offsets, n) |
40 | 10x |
arkhe::assert_length(reservoir_errors, n) |
41 | 10x |
arkhe::assert_length(dfs, n) |
42 | ||
43 |
## Calibration time range |
|
44 | 10x |
cal_range <- seq(from = from, to = to, by = -resolution) |
45 | ||
46 |
## Calibration curve |
|
47 | 10x |
curves <- tolower(curves) |
48 | 10x |
curve_range <- approx_curve(unique(curves), out = cal_range, F14C = F14C) |
49 | ||
50 |
## Marine reservoir offset |
|
51 | 10x |
values <- values - reservoir_offsets |
52 | 10x |
errors <- sqrt(errors^2 + reservoir_errors^2) |
53 | ||
54 |
## Calibrate |
|
55 | 10x |
calibrate_fun <- if (F14C) calibrate_F14C else calibrate_BP14C |
56 | 10x |
dens <- vector(mode = "list", length = n) |
57 | 10x |
status <- integer(n) |
58 | 10x |
for (i in seq_len(n)) { |
59 | 14x |
d <- calibrate_fun( |
60 | 14x |
x = values[i], |
61 | 14x |
error = errors[i], |
62 | 14x |
mu = curve_range[[curves[i]]]$mu, |
63 | 14x |
tau = curve_range[[curves[i]]]$tau, |
64 | 14x |
df = dfs[i], |
65 | 14x |
method = method |
66 |
) |
|
67 | ||
68 |
## Check |
|
69 | 14x |
if (anyNA(d)) { |
70 | ! |
d[is.na(d)] <- 0 |
71 | ! |
msg <- tr_("Consider changing the calibration time range to a narrower interval.") |
72 | ! |
if (verbose) message(msg) |
73 |
} |
|
74 | ||
75 | 14x |
max_cal <- curve_range[[curves[i]]]$max |
76 | 14x |
min_cal <- curve_range[[curves[i]]]$min |
77 | ||
78 | 14x |
if (values[[i]] >= max_cal || values[[i]] <= min_cal) { |
79 |
## L'age à calibrer est hors de l'étendue de la courbe de calibration |
|
80 | ! |
if (verbose) warning(print_out(names[[i]], maybe = FALSE), call. = FALSE) |
81 | 3x |
status[i] <- 1L |
82 | 11x |
} else if (d[1] > eps || d[length(d)] > eps) { |
83 |
## L'age calibré est en partie hors de l'étendue de la courbe |
|
84 | ! |
if (verbose) warning(print_out(names[[i]], maybe = TRUE), call. = FALSE) |
85 | 3x |
status[i] <- 2L |
86 |
} |
|
87 | ||
88 | 14x |
d[d < eps] <- 0 |
89 | 14x |
dens[[i]] <- d |
90 |
} |
|
91 | ||
92 |
## Build matrix |
|
93 | 10x |
dens <- do.call(rbind, dens) |
94 | ||
95 |
## Normalize |
|
96 | ! |
if (F14C & !normalize) normalize <- TRUE |
97 | 10x |
if (normalize) { |
98 | 10x |
dens <- dens / rowSums(dens, na.rm = TRUE) |
99 | 10x |
dens[dens < eps] <- 0 |
100 | 10x |
dens <- dens / rowSums(dens, na.rm = TRUE) |
101 |
} |
|
102 | ||
103 |
## Drop |
|
104 | 10x |
if (drop) { |
105 | 10x |
keep_zero <- colSums(dens, na.rm = TRUE) > 0 |
106 | 10x |
keep_from <- which.max(keep_zero) # First TRUE |
107 | 10x |
keep_to <- length(keep_zero) - which.max(rev(keep_zero)) + 1 # Last TRUE |
108 | 10x |
keep <- seq(from = keep_from, to = keep_to, by = 1) |
109 | 10x |
dens <- dens[, keep, drop = FALSE] |
110 | 10x |
cal_range <- cal_range[keep] |
111 |
} |
|
112 | ||
113 | 10x |
time_series <- aion::series( |
114 | 10x |
object = t(dens), |
115 | 10x |
time = cal_range, |
116 | 10x |
calendar = BP(), |
117 | 10x |
names = names |
118 |
) |
|
119 | 10x |
.CalibratedAges( |
120 | 10x |
time_series, |
121 | 10x |
values = values, |
122 | 10x |
errors = errors, |
123 | 10x |
curves = curves, |
124 | 10x |
reservoir_offsets = reservoir_offsets, |
125 | 10x |
reservoir_errors = reservoir_errors, |
126 | 10x |
F14C = F14C, |
127 | 10x |
positions = positions, |
128 | 10x |
status = status |
129 |
) |
|
130 |
} |
|
131 |
) |
|
132 | ||
133 |
calibrate_BP14C <- function(x, error, mu, tau, df = 100, method = "student") { |
|
134 | 14x |
tau <- error^2 + tau^2 |
135 | 14x |
dens <- switch( |
136 | 14x |
method, |
137 | 14x |
student = stats::dt(x = (x - mu) / sqrt(tau), df = df), |
138 | 14x |
normal = stats::dnorm(x, mean = mu, sd = sqrt(tau)) |
139 |
) |
|
140 | 14x |
dens |
141 |
} |
|
142 |
calibrate_F14C <- function(x, error, mu, tau, ...) { |
|
143 | ! |
p1 <- (x - mu)^2 |
144 | ! |
p2 <- 2 * (error^2 + tau^2) |
145 | ! |
p3 <- sqrt(error^2 + tau^2) |
146 | ! |
dens <- exp(-p1 / p2) / p3 |
147 | ! |
dens |
148 |
} |
1 |
# PLOT |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
## 14C ========================================================================= |
|
6 |
#' @export |
|
7 |
#' @method plot CalibratedAges |
|
8 |
plot.CalibratedAges <- function(x, calendar = get_calendar(), density = TRUE, |
|
9 |
interval = c("hdr", "credible", "none"), |
|
10 |
level = 0.954, fixed = TRUE, decreasing = TRUE, |
|
11 |
col.density = "grey", col.interval = "#77AADD", |
|
12 |
main = NULL, sub = NULL, |
|
13 |
axes = TRUE, frame.plot = FALSE, |
|
14 |
ann = graphics::par("ann"), |
|
15 |
panel.first = NULL, panel.last = NULL, ...) { |
|
16 |
## Check |
|
17 | ! |
c14_validate(x) |
18 | ! |
interval <- match.arg(interval, several.ok = FALSE) |
19 | ||
20 |
## Graphical parameters |
|
21 | ! |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis") |
22 | ! |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis") |
23 | ! |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis") |
24 | ! |
if (length(col.density) == 1) |
25 | ! |
col.density <- rep(col.density, length.out = NCOL(x)) |
26 | ! |
if (length(col.interval) == 1) |
27 | ! |
col.interval <- rep(col.interval, length.out = NCOL(x)) |
28 | ! |
fill.density <- grDevices::adjustcolor(col.density, alpha.f = 0.5) |
29 | ! |
fill.interval <- grDevices::adjustcolor(col.interval, alpha.f = 0.5) |
30 | ||
31 |
## Clean |
|
32 | ! |
out <- x@status == 1L # Out of calibration range |
33 | ! |
x <- x[, !out, , drop = FALSE] |
34 | ! |
col.density <- col.density[!out] |
35 | ! |
fill.density <- fill.density[!out] |
36 | ! |
col.interval <- col.interval[!out] |
37 | ! |
fill.interval <- fill.interval[!out] |
38 | ||
39 |
## Compute interval |
|
40 | ! |
if (!identical(interval, "none")) { |
41 | ! |
calc_interval <- switch( |
42 | ! |
interval, |
43 | ! |
hdr = interval_hdr, |
44 | ! |
credible = interval_credible |
45 |
) |
|
46 | ! |
int <- calc_interval(x, level = level) |
47 | ! |
int <- as.list(int, calendar = calendar) |
48 |
} |
|
49 | ||
50 |
## Fixed vs reordered y scale |
|
51 | ! |
n <- NCOL(x) |
52 | ! |
pos <- x@positions |
53 | ! |
if (isTRUE(fixed)) pos <- order(order(pos)) |
54 | ! |
delta <- if (!isTRUE(fixed)) diff(range(x@positions)) / n else 0.9 |
55 | ||
56 |
## Save and restore |
|
57 | ! |
lab <- labels(x) |
58 | ! |
mar <- graphics::par("mar") |
59 | ! |
mar[2] <- inch2line(lab, cex = cex.axis) + 0.5 |
60 | ! |
old_par <- graphics::par(mar = mar) |
61 | ! |
on.exit(graphics::par(old_par)) |
62 | ||
63 |
## Open new window |
|
64 | ! |
grDevices::dev.hold() |
65 | ! |
on.exit(grDevices::dev.flush(), add = TRUE) |
66 | ! |
graphics::plot.new() |
67 | ||
68 |
## Set plotting coordinates |
|
69 | ! |
xlim <- range(aion::time(x, calendar = NULL)) |
70 | ! |
ylim <- if (!isTRUE(fixed)) range(x@values) else c(1, n) |
71 | ! |
if (!isTRUE(decreasing)) { |
72 | ! |
ylim <- rev(ylim) - c(0, delta) |
73 |
} else { |
|
74 | ! |
ylim <- ylim + c(0, delta) |
75 |
} |
|
76 | ! |
if (!is.null(calendar)) xlim <- aion::as_year(xlim, calendar = calendar) |
77 | ! |
graphics::plot.window(xlim = xlim, ylim = ylim) |
78 | ||
79 |
## Evaluate pre-plot expressions |
|
80 | ! |
panel.first |
81 | ||
82 |
## Plot |
|
83 | ! |
years <- aion::time(x, calendar = calendar) |
84 | ! |
tick_height <- graphics::par("tcl") * graphics::strheight("M") * -1 |
85 | ! |
if (isFALSE(density)) tick_height <- 0 |
86 | ! |
for (i in seq_len(n)) { |
87 | ! |
y <- x[, i, k = 1, drop = TRUE] |
88 | ! |
y <- (y - min(y)) / max(y - min(y)) * delta |
89 | ||
90 | ! |
if (isTRUE(density)) { |
91 | ! |
d0 <- which(y > 0) # Keep only density > 0 |
92 | ! |
lb <- if (min(d0) > 1) min(d0) - 1 else min(d0) |
93 | ! |
ub <- if (max(d0) < length(years)) max(d0) + 1 else max(d0) |
94 | ! |
xi <- c(years[lb], years[d0], years[ub]) |
95 | ! |
if (!isTRUE(decreasing)) { |
96 | ! |
yi <- c(pos[i], pos[i] - y[d0], pos[i]) |
97 |
} else { |
|
98 | ! |
yi <- c(pos[i], y[d0] + pos[i], pos[i]) |
99 |
} |
|
100 | ||
101 | ! |
graphics::polygon(xi, yi, border = NA, col = fill.density[i]) |
102 | ! |
graphics::lines(xi, yi, lty = "solid") |
103 |
} |
|
104 | ||
105 | ! |
if (!identical(interval, "none")) { |
106 | ! |
h <- int[[i]] |
107 | ||
108 | ! |
if (isTRUE(density)) { |
109 | ! |
for (j in seq_len(nrow(h))) { |
110 | ! |
debut <- h[j, "start"] |
111 | ! |
fin <- h[j, "end"] |
112 | ! |
if (debut < fin) is_in_h <- xi >= debut & xi <= fin |
113 | ! |
else is_in_h <- xi <= debut & xi >= fin |
114 | ! |
xh <- xi[is_in_h] |
115 | ! |
yh <- yi[is_in_h] |
116 | ! |
graphics::polygon( |
117 | ! |
x = c(xh[1], xh, xh[length(xh)]), |
118 | ! |
y = c(pos[i], yh, pos[i]), |
119 | ! |
border = NA, col = fill.interval[i] |
120 |
) |
|
121 |
} |
|
122 |
} |
|
123 | ||
124 | ! |
params <- list(x0 = h[, "start"], x1 = h[, "end"], |
125 | ! |
y0 = pos[i], y1 = pos[i], lend = 1) |
126 | ! |
dots <- list(...) |
127 | ! |
dots <- utils::modifyList(dots, params) |
128 | ! |
if (isFALSE(density)) dots$col <- col.interval[i] |
129 | ! |
do.call(graphics::segments, dots) |
130 | ! |
graphics::segments( |
131 | ! |
x0 = c(h[, "start"], h[, "end"]), |
132 | ! |
x1 = c(h[, "start"], h[, "end"]), |
133 | ! |
y0 = pos[i], y1 = pos[i] + tick_height, |
134 | ! |
lend = 1, ... |
135 |
) |
|
136 |
} |
|
137 |
} |
|
138 | ||
139 |
## Evaluate post-plot and pre-axis expressions |
|
140 | ! |
panel.last |
141 | ||
142 |
## Construct Axis |
|
143 | ! |
if (axes) { |
144 | ! |
aion::year_axis(side = 1, format = TRUE, calendar = calendar, |
145 | ! |
current_calendar = calendar) |
146 | ! |
graphics::axis(side = 2, at = pos, labels = lab, las = 2, |
147 | ! |
lty = 0, cex.axis = cex.axis, col.axis = col.axis, |
148 | ! |
font.axis = font.axis) |
149 |
} |
|
150 | ||
151 |
## Plot frame |
|
152 | ! |
if (frame.plot) { |
153 | ! |
graphics::box() |
154 |
} |
|
155 | ||
156 |
## Add annotation |
|
157 | ! |
if (ann) { |
158 | ! |
xlab <- if (is.null(calendar)) expression(italic("rata die")) else format(calendar) |
159 | ! |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = NULL) |
160 |
} |
|
161 | ||
162 | ! |
invisible(x) |
163 |
} |
|
164 | ||
165 |
#' @export |
|
166 |
#' @rdname c14_plot |
|
167 |
#' @aliases plot,CalibratedAges,missing-method |
|
168 |
setMethod("plot", c(x = "CalibratedAges", y = "missing"), plot.CalibratedAges) |
|
169 | ||
170 |
## SPD ========================================================================= |
|
171 |
#' @export |
|
172 |
#' @method plot CalibratedSPD |
|
173 |
plot.CalibratedSPD <- function(x, calendar = get_calendar(), |
|
174 |
main = NULL, sub = NULL, |
|
175 |
ann = graphics::par("ann"), |
|
176 |
axes = TRUE, frame.plot = FALSE, |
|
177 |
panel.first = NULL, panel.last = NULL, ...) { |
|
178 | ! |
n <- NCOL(x) |
179 | ||
180 |
## Graphical parameters |
|
181 | ! |
col <- list(...)$col %||% c("grey") |
182 | ! |
if (length(col) != n) col <- rep(col, length.out = n) |
183 | ! |
col <- grDevices::adjustcolor(col, alpha.f = 0.5) |
184 | ||
185 |
## Plot |
|
186 | ! |
panel_density <- function(x, y, ...) { |
187 | ! |
graphics::polygon(x = c(x, rev(x)), y = c(y, rep(0, length(y))), |
188 | ! |
border = NA, ...) |
189 | ! |
graphics::lines(x, y, col = "black") |
190 |
} |
|
191 | ||
192 | ! |
methods::callNextMethod( |
193 | ! |
x, facet = "multiple", |
194 | ! |
calendar = calendar, |
195 | ! |
panel = panel_density, |
196 | ! |
main = main, sub = sub, ann = ann, axes = axes, |
197 | ! |
frame.plot = frame.plot, |
198 | ! |
panel.first = panel.first, |
199 | ! |
panel.last = panel.last, |
200 | ! |
col = col, |
201 |
... |
|
202 |
) |
|
203 | ||
204 | ! |
invisible(x) |
205 |
} |
|
206 | ||
207 |
#' @export |
|
208 |
#' @rdname c14_plot |
|
209 |
#' @aliases plot,CalibratedSPD,missing-method |
|
210 |
setMethod("plot", c(x = "CalibratedSPD", y = "missing"), plot.CalibratedSPD) |
|
211 | ||
212 |
## RECE ======================================================================== |
|
213 |
#' @export |
|
214 |
#' @method plot RECE |
|
215 |
plot.RECE <- function(x, calendar = get_calendar(), ...) { |
|
216 |
## Binary array |
|
217 | ! |
bin <- array(FALSE, dim = c(nrow(x), max(x), ncol(x))) |
218 | ! |
for (j in seq_len(ncol(x))) { |
219 | ! |
z <- x[, j, , drop = TRUE] |
220 | ! |
for (i in seq_along(z)) { |
221 | ! |
bin[i, z[i], j] <- z[i] > 0 |
222 |
} |
|
223 |
} |
|
224 | ! |
bin <- apply(X = bin, MARGIN = c(1, 2), FUN = sum) |
225 | ! |
bin[bin == 0] <- NA |
226 | ||
227 |
## Add annotation |
|
228 | ! |
years <- aion::time(x, calendar = NULL) |
229 | ||
230 |
## Plot |
|
231 | ! |
graphics::image( |
232 | ! |
x = years, |
233 | ! |
y = seq_len(max(x)), |
234 | ! |
z = log(bin), |
235 | ! |
xlab = format(calendar), |
236 | ! |
ylab = "Count", |
237 | ! |
xaxt = "n", |
238 | ! |
yaxt = "n", |
239 |
... |
|
240 |
) |
|
241 | ||
242 |
## Construct axes |
|
243 | ! |
aion::year_axis(side = 1, format = TRUE, calendar = calendar, |
244 | ! |
current_calendar = NULL) |
245 | ! |
graphics::axis(side = 2, at = seq_len(max(x)), las = 1) |
246 | ||
247 | ! |
invisible(x) |
248 |
} |
|
249 | ||
250 |
#' @export |
|
251 |
#' @rdname rec_plot |
|
252 |
#' @aliases plot,RECE,missing-method |
|
253 |
setMethod("plot", c(x = "RECE", y = "missing"), plot.RECE) |
|
254 | ||
255 | ||
256 |
## Proxy ======================================================================= |
|
257 |
#' @export |
|
258 |
#' @method plot ProxyRecord |
|
259 |
plot.ProxyRecord <- function(x, calendar = get_calendar(), |
|
260 |
iqr = TRUE, |
|
261 |
xlab = NULL, ylab = NULL, |
|
262 |
col = grDevices::hcl.colors(12, "YlOrRd", rev = TRUE), |
|
263 |
col.mean = "black", col.iqr = col.mean, |
|
264 |
lty.mean = 1, lty.iqr = 3, |
|
265 |
lwd.mean = 2, lwd.iqr = lwd.mean, ...) { |
|
266 |
## Get data |
|
267 | ! |
years <- aion::time(x, calendar = NULL) |
268 | ! |
z <- apply( |
269 | ! |
X = x@density, |
270 | ! |
MARGIN = 1, |
271 | ! |
FUN = function(d) (d - min(d)) / max(d - min(d)) |
272 |
) |
|
273 | ! |
z[z == 0] <- NA |
274 | ||
275 |
## Plot |
|
276 | ! |
graphics::image( |
277 | ! |
x = years, |
278 | ! |
y = x@proxy, |
279 | ! |
z = t(z), |
280 | ! |
col = col, |
281 | ! |
xaxt = "n", |
282 | ! |
yaxt = "n", |
283 | ! |
xlab = xlab %||% format(calendar), |
284 | ! |
ylab = ylab %||% "Proxy", |
285 |
... |
|
286 |
) |
|
287 | ||
288 |
## Construct axes |
|
289 | ! |
aion::year_axis(side = 1, format = TRUE, calendar = calendar, |
290 | ! |
current_calendar = NULL) |
291 | ! |
graphics::axis(side = 2, las = 1) |
292 | ||
293 | ! |
if (isTRUE(iqr)) { |
294 | ! |
m <- mean(x) |
295 | ! |
graphics::lines(x = years, y = m, col = col.mean, |
296 | ! |
lty = lty.mean, lwd = lwd.mean) |
297 | ||
298 | ! |
q <- quantile(x, probs = c(0.25, 0.75)) |
299 | ! |
graphics::lines(x = years, y = q[, 1], col = col.iqr, |
300 | ! |
lty = lty.iqr, lwd = lwd.iqr) |
301 | ! |
graphics::lines(x = years, y = q[, 2], col = col.iqr, |
302 | ! |
lty = lty.iqr, lwd = lwd.iqr) |
303 |
} |
|
304 | ||
305 | ! |
invisible(x) |
306 |
} |
|
307 | ||
308 |
#' @export |
|
309 |
#' @rdname proxy_plot |
|
310 |
#' @aliases plot,ProxyRecord,missing-method |
|
311 |
setMethod("plot", c(x = "ProxyRecord", y = "missing"), plot.ProxyRecord) |
1 |
# COMBINE 14C |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname c14_combine |
|
7 |
#' @aliases c14_combine,numeric,numeric-method |
|
8 |
setMethod( |
|
9 |
f = "c14_combine", |
|
10 |
signature = c(values = "numeric", errors = "numeric"), |
|
11 |
definition = function(values, errors, groups = NULL) { |
|
12 |
## Validation |
|
13 | 4x |
n <- length(values) |
14 | 1x |
if (is.null(groups)) groups <- "X" |
15 | 3x |
if (length(groups) == 1) groups <- rep(groups, n) |
16 | 4x |
groups <- factor(x = groups, levels = unique(groups)) |
17 | ||
18 | 4x |
arkhe::assert_missing(values) |
19 | 4x |
arkhe::assert_missing(errors) |
20 | 4x |
arkhe::assert_length(errors, n) |
21 | 4x |
arkhe::assert_length(groups, n) |
22 | ||
23 |
## Empty groups must be treated as NA |
|
24 | 4x |
groups[groups == ""] <- NA |
25 | ||
26 |
## Groups with only one date must be treated as NA |
|
27 | 4x |
counts <- table(groups) |
28 | 4x |
one <- groups %in% names(counts)[counts == 1] |
29 | ||
30 |
# NA group will be removed |
|
31 |
# We need to keep isolated dates |
|
32 | 4x |
k <- one | is.na(groups) |
33 | 4x |
solo <- NULL |
34 | 4x |
if (any(k)) { |
35 | 3x |
solo <- data.frame( |
36 | 3x |
groups = as.character(groups[k]), |
37 | 3x |
values = values[k], |
38 | 3x |
errors = errors[k], |
39 | 3x |
chi2 = NA_real_, |
40 | 3x |
p = NA_real_ |
41 |
) |
|
42 |
} |
|
43 | ||
44 | 4x |
combined <- NULL |
45 | 4x |
if (!all(k)) { |
46 | 2x |
groups[k] <- NA |
47 | 2x |
groups <- droplevels(groups) |
48 | ||
49 |
## split() removes NA group |
|
50 | 2x |
values <- split(values, f = groups) |
51 | 2x |
errors <- split(errors, f = groups) |
52 | 2x |
cmbn <- mapply( |
53 | 2x |
FUN = combine, |
54 | 2x |
values = values, |
55 | 2x |
errors = errors, |
56 | 2x |
SIMPLIFY = FALSE |
57 |
) |
|
58 | 2x |
combined <- data.frame(names(cmbn), do.call(rbind, cmbn)) |
59 | 2x |
colnames(combined) <- c("groups", "values", "errors", "chi2", "p") |
60 |
} |
|
61 | ||
62 | 4x |
final <- rbind(solo, combined, make.row.names = FALSE) |
63 | 4x |
final |
64 |
} |
|
65 |
) |
|
66 | ||
67 |
combine <- function(values, errors) { |
|
68 |
## On calcule la moyenne pondérée |
|
69 | 2x |
w <- 1 / errors^2 # Facteur de pondération |
70 | 2x |
moy <- stats::weighted.mean(x = values, w = w) |
71 | ||
72 |
## On calcule l'incertitude associée à la moyenne pondérée |
|
73 | 2x |
err <- sum(1 / errors^2)^(-1 / 2) |
74 | ||
75 |
## On calcule la statistique du test |
|
76 | 2x |
chi2 <- sum(((values - moy) / errors)^2) |
77 | ||
78 |
## On calcule la valeur-p |
|
79 | 2x |
p <- 1 - stats::pchisq(chi2, df = length(values)) |
80 | ||
81 |
## On stocke les résultats |
|
82 | 2x |
c(moy, err, chi2, p) |
83 |
} |
1 |
# 14C UNCALIBRATION |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Uncalibrate ================================================================== |
|
6 |
#' @export |
|
7 |
#' @rdname c14_uncalibrate |
|
8 |
#' @aliases c14_uncalibrate,numeric-method |
|
9 |
setMethod( |
|
10 |
f = "c14_uncalibrate", |
|
11 |
signature = c(object = "numeric"), |
|
12 |
definition = function(object, curves = "intcal20") { |
|
13 |
## Validation |
|
14 | 1x |
n <- length(object) |
15 | ! |
if (length(curves) != n) curves <- rep(curves, n) |
16 | 1x |
uncal <- rep(NA_real_, n) |
17 | ||
18 |
## Calibration curve |
|
19 | 1x |
curve_data <- c14_curve(tolower(curves)) |
20 | ||
21 | 1x |
for (i in seq_len(n)) { |
22 | 1x |
z <- stats::approx( |
23 | 1x |
x = curve_data[[i]][, 1], |
24 | 1x |
y = curve_data[[i]][, 2], |
25 | 1x |
xout = object[i], |
26 | 1x |
rule = 1 |
27 |
) |
|
28 | 1x |
uncal[i] <- z$y |
29 |
} |
|
30 | 1x |
uncal |
31 |
} |
|
32 |
) |
|
33 | ||
34 |
#' @export |
|
35 |
#' @rdname c14_uncalibrate |
|
36 |
#' @aliases c14_uncalibrate,CalibratedAges-method |
|
37 |
setMethod( |
|
38 |
f = "c14_uncalibrate", |
|
39 |
signature = c(object = "CalibratedAges"), |
|
40 |
definition = function(object, n = 10000, rounding = getOption("ananke.round"), |
|
41 |
...) { |
|
42 | ||
43 | ! |
method <- list(...)$method %||% c("L-BFGS-B") |
44 | ||
45 |
## Function to be optimized |
|
46 | ! |
opt_fun <- function(param, curve, samples, ...) { |
47 | ! |
cal <- c14_calibrate( |
48 | ! |
values = round(param[1]), |
49 | ! |
errors = round(param[2]), |
50 | ! |
curves = curve |
51 |
) |
|
52 | ! |
s1 <- samples |
53 | ! |
s2 <- c14_sample(cal, n = n, calendar = BP()) |
54 | ||
55 | ! |
dens1 <- stats::density(s1, from = min(c(s1, s2)), to = max(c(s1, s2)))$y |
56 | ! |
dens2 <- stats::density(s2, from = min(c(s1, s2)), to = max(c(s1, s2)))$y |
57 | ! |
dens1 <- dens1 / sum(dens1) |
58 | ! |
dens2 <- dens2 / sum(dens2) |
59 | ! |
int <- dens1 * log(dens1 / dens2) |
60 | ! |
int <- int[dens1 > 0] |
61 | ! |
int <- int[!is.infinite(int)] |
62 | ! |
sum(int) |
63 |
} |
|
64 | ||
65 | ! |
n <- NCOL(object) |
66 | ! |
curves <- object@curves |
67 | ||
68 |
## Initial values for the parameters to be optimized over |
|
69 | ! |
spl <- c14_sample(object, n = n, calendar = BP()) |
70 | ! |
med <- apply(X = spl, MARGIN = 2, FUN = stats::median) |
71 | ! |
init_mean <- c14_uncalibrate(med, curves = curves) |
72 | ! |
init_sd <- apply(X = spl, MARGIN = 2, FUN = stats::sd) |
73 | ||
74 | ! |
opt_mean <- opt_sd <- rep(NA_real_, n) |
75 | ! |
for (i in seq_len(n)) { |
76 | ! |
cal_spl <- spl[, i] |
77 | ||
78 | ! |
opt_run <- stats::optim( |
79 | ! |
par = c(init_mean[[i]], init_sd[[i]]), |
80 | ! |
fn = opt_fun, |
81 | ! |
method = method, |
82 | ! |
curve = curves[[i]], |
83 | ! |
samples = cal_spl, |
84 | ! |
lower = c(-Inf, 1), |
85 |
... |
|
86 |
) |
|
87 | ! |
opt_mean[[i]] <- opt_run$par[1] |
88 | ! |
opt_sd[[i]] <- opt_run$par[2] |
89 |
} |
|
90 | ||
91 |
## Rounding |
|
92 | ! |
if (identical(rounding, "stuiver")) { |
93 | ! |
opt_mean <- round_values_stuiver(opt_mean) |
94 | ! |
opt_sd <- round_errors_stuiver(opt_sd) |
95 |
} |
|
96 | ||
97 | ! |
data.frame(mean = opt_mean, sd = opt_sd) |
98 |
} |
|
99 |
) |
1 |
# DESCRIBE |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname describe |
|
7 |
#' @aliases describe,CalibratedAges-method |
|
8 |
setMethod( |
|
9 |
f = "describe", |
|
10 |
signature = signature(x = "CalibratedAges"), |
|
11 |
definition = function(x, calendar = get_calendar(), |
|
12 |
level = 0.954, ...) { |
|
13 |
## Get data |
|
14 | 1x |
lab <- labels(x) |
15 | 1x |
val <- x@values |
16 | 1x |
err <- x@errors |
17 | 1x |
crv <- x@curves |
18 | 1x |
reservoir_off <- x@reservoir_offsets |
19 | 1x |
reservoir_err <- x@reservoir_errors |
20 | 1x |
F14C <- x@F14C |
21 | ||
22 |
## Laboratory code |
|
23 | 1x |
if (F14C) { |
24 | ! |
txt_uncal <- "Sample %s contains %.0f +/- %.0f F14C," |
25 |
} else { |
|
26 | 1x |
txt_uncal <- "Sample %s is dated to %.0f +/- %.0f BP," |
27 |
} |
|
28 | 1x |
msg_uncal <- sprintf(txt_uncal, lab, val, err) |
29 | ||
30 |
## Calibration results |
|
31 | 1x |
hdr <- as.list(interval_hdr(x, level = level), calendar = calendar) |
32 | 1x |
msg_cal <- lapply( |
33 | 1x |
X = hdr, |
34 | 1x |
FUN = function(x, calendar, level) { |
35 | ! |
if (is.null(x)) return("but is out of the calibration range of") |
36 | 2x |
p <- if (NROW(x) > 1) sprintf(" (%.1f%%)", x$p * 100) else "" |
37 | 2x |
msg_hdr <- sprintf("[%.0f,%.0f]%s", x$start, x$end, p) |
38 | 2x |
txt_cal <- "calibrated to %s %s (%.1f%% HPD interval) with" |
39 | 2x |
sprintf(txt_cal, paste0(msg_hdr, collapse = " or "), calendar, level) |
40 |
}, |
|
41 | 1x |
calendar = calendar@label, |
42 | 1x |
level = level * 100 |
43 |
) |
|
44 | ||
45 |
## Calibration curve |
|
46 | 1x |
txt_marine <- "marine reservoir offset: %.0f +/- %.0f; " |
47 | 1x |
msg_marine <- sprintf(txt_marine, reservoir_off, reservoir_err) |
48 | 1x |
msg_marine[reservoir_off == 0] <- "" |
49 | 1x |
txt_curve <- "%s (%s%s)." |
50 | 1x |
msg_curve <- sprintf(txt_curve, crv, msg_marine, cite_curve(crv)) |
51 | ||
52 |
## Text |
|
53 | 1x |
msg <- paste(msg_uncal, msg_cal, msg_curve, sep = " ") |
54 | ||
55 |
## Software |
|
56 | 1x |
txt_soft <- "Calibration was computed with R %s.%s (R Core Team %s) and package ananke %s (Frerebeau %s)." |
57 | 1x |
date_soft <- utils::packageDate("ananke") |
58 | 1x |
date_soft <- if (is.na(date_soft)) Sys.Date() else date_soft |
59 | 1x |
msg_soft <- sprintf(txt_soft, R.version$major, R.version$minor, |
60 | 1x |
R.version$year, utils::packageVersion("ananke"), |
61 | 1x |
format(date_soft, format = "%Y")) |
62 | ||
63 |
## Split string |
|
64 | 1x |
fill <- list(...)$fill |
65 | 1x |
if (!is.null(fill) && isTRUE(fill)) { |
66 | ! |
msg <- lapply( |
67 | ! |
X = msg, |
68 | ! |
FUN = function(x, width) { |
69 | ! |
split <- lapply( |
70 | ! |
X = seq(from = 1, to = nchar(x), by = width), |
71 | ! |
FUN = function(i) substr(x, i, i + width - 1) |
72 |
) |
|
73 | ! |
paste0(split, collapse = "\n") |
74 |
}, |
|
75 | ! |
width = getOption("width") |
76 |
) |
|
77 |
} |
|
78 | ||
79 | 1x |
cat(unlist(msg), msg_soft, sep = "\n\n", ...) |
80 | ||
81 | 1x |
invisible(x) |
82 |
} |
|
83 |
) |
1 |
# SUBSET |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Extract ====================================================================== |
|
6 |
## [ --------------------------------------------------------------------------- |
|
7 |
#' @export |
|
8 |
#' @rdname subset |
|
9 |
#' @aliases [,CalibratedAges-method |
|
10 |
setMethod( |
|
11 |
f = "[", |
|
12 |
signature = c(x = "CalibratedAges"), |
|
13 |
function(x, i, j, k, drop = FALSE) { |
|
14 | 1x |
z <- x@.Data |
15 | 1x |
time <- x@.Time |
16 | 1x |
values <- x@values |
17 | 1x |
errors <- x@errors |
18 | 1x |
curves <- x@curves |
19 | 1x |
reservoir_offsets <- x@reservoir_offsets |
20 | 1x |
reservoir_errors <- x@reservoir_errors |
21 | 1x |
positions <- x@positions |
22 | 1x |
status <- x@status |
23 | ||
24 | 1x |
z <- z[i, j, k, drop = drop] |
25 | 1x |
if (!missing(i)) { |
26 | ! |
if (is.character(i)) i <- match(i, dimnames(x)[1L]) |
27 | ! |
time <- time[i] |
28 |
} |
|
29 | 1x |
if (!missing(j)) { |
30 | ! |
if (is.character(j)) j <- match(j, dimnames(x)[2L]) |
31 | ! |
values <- values[j] |
32 | ! |
errors <- errors[j] |
33 | ! |
curves <- curves[j] |
34 | ! |
reservoir_offsets <- reservoir_offsets[j] |
35 | ! |
reservoir_errors <- reservoir_errors[j] |
36 | ! |
positions <- positions[j] |
37 | ! |
status <- status[j] |
38 |
} |
|
39 | ||
40 | 1x |
if (isTRUE(drop)) return(z) |
41 | ! |
methods::initialize(x, z, .Time = time, values = values, errors = errors, |
42 | ! |
curves = curves, reservoir_offsets = reservoir_offsets, |
43 | ! |
reservoir_errors = reservoir_errors, |
44 | ! |
positions = positions, status = status) |
45 |
} |
|
46 |
) |
1 |
# 14C CALIBRATION CURVE |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Get curve ==================================================================== |
|
6 |
#' @export |
|
7 |
#' @rdname c14_curve |
|
8 |
#' @aliases c14_curve,character-method |
|
9 |
setMethod( |
|
10 |
f = "c14_curve", |
|
11 |
signature = c(name = "character"), |
|
12 |
definition = function(name) { |
|
13 | 11x |
curve_ok <- c("intcal20", "intcal13", "intcal09", "intcal04", |
14 | 11x |
"marine20", "marine13", "marine09", "marine04", |
15 | 11x |
"shcal20", "shcal13", "shcal04") |
16 | 11x |
name <- match.arg(name, choices = curve_ok, several.ok = TRUE) |
17 | ||
18 | 11x |
curves <- lapply(X = name, FUN = read_curve) |
19 | 11x |
names(curves) <- name |
20 | 11x |
curves |
21 |
} |
|
22 |
) |
|
23 | ||
24 |
#' @export |
|
25 |
#' @rdname c14_curve |
|
26 |
#' @aliases c14_curve,CalibratedAges-method |
|
27 |
setMethod( |
|
28 |
f = "c14_curve", |
|
29 |
signature = c(name = "CalibratedAges"), |
|
30 |
definition = function(name) { |
|
31 | ! |
methods::callGeneric(name@curves) |
32 |
} |
|
33 |
) |
|
34 | ||
35 |
read_curve <- function(x) { |
|
36 |
## Read data |
|
37 | 11x |
curve_dir <- system.file("extdata", package = "ananke") |
38 | 11x |
curve_path <- file.path(curve_dir, paste0(x, ".14c")) |
39 | 11x |
curve <- utils::read.table(curve_path, header = FALSE, sep = ",", |
40 | 11x |
dec = ".", strip.white = TRUE, |
41 | 11x |
comment.char = "#") |
42 | ||
43 | 11x |
curve <- curve[, c(1, 2, 3)] |
44 | 11x |
colnames(curve) <- c("CALBP", "AGE", "ERROR") |
45 | 11x |
curve |
46 |
} |
|
47 | ||
48 |
cite_curve <- function(x) { |
|
49 | 1x |
curve <- c( |
50 | 1x |
bomb04nh1 = "Hua and Barbetti 2004", |
51 | 1x |
bomb04nh2 = "Hua and Barbetti 2004", |
52 | 1x |
bomb04nh3 = "Hua and Barbetti 2004", |
53 | 1x |
bomb04sh = "Hua and Barbetti 2004", |
54 | 1x |
bomb13nh1 = "Hua, Berbetti and Rakowski 2013", |
55 | 1x |
bomb13nh2 = "Hua, Berbetti and Rakowski 2013", |
56 | 1x |
bomb13nh3 = "Hua, Berbetti and Rakowski 2013", |
57 | 1x |
bomb13sh12 = "Hua, Berbetti and Rakowski 2013", |
58 | 1x |
bomb13sh3 = "Hua, Berbetti and Rakowski 2013", |
59 | 1x |
bomb21nh1 = "Hua et al. 2022", |
60 | 1x |
bomb21nh2 = "Hua et al. 2022", |
61 | 1x |
bomb21nh3 = "Hua et al. 2022", |
62 | 1x |
bomb21sh12 = "Hua et al. 2022", |
63 | 1x |
bomb21sh3 = "Hua et al. 2022", |
64 | 1x |
cariaco04 = "Hughen et al. 2004", |
65 | 1x |
intcal98 = "Stuiver et al. 1998", |
66 | 1x |
intcal04 = "Reimer et al. 2004", |
67 | 1x |
intcal09 = "Reimer et al. 2009", |
68 | 1x |
intcal13 = "Reimer et al. 2013", |
69 | 1x |
intcal20 = "Reimer et al. 2020", |
70 | 1x |
kueppers04 = "Kueppers et al. 2004", |
71 | 1x |
marine98 = "Stuiver, Reimer and Braziunas 1998", |
72 | 1x |
marine04 = "Hughen et al. 2004", |
73 | 1x |
marine09 = "Reimer et al. 2009", |
74 | 1x |
marine13 = "Reimer et al. 2013", |
75 | 1x |
marine20 = "Heaton et al. 2020", |
76 | 1x |
shcal04 = "McCormac et al. 2004", |
77 | 1x |
shcal13 = "Hogg et al. 2013", |
78 | 1x |
shcal20 = "Hogg et al. 2020" |
79 |
) |
|
80 | ||
81 | 1x |
curve[x] |
82 |
} |
|
83 | ||
84 |
# Approximate curve ============================================================ |
|
85 |
#' Interpolate 14C Calibration Curve |
|
86 |
#' |
|
87 |
#' @param name A [`character`] vector naming calibration curves. |
|
88 |
#' @param out A [`numeric`] vector specifying where interpolation is to take |
|
89 |
#' place. |
|
90 |
#' @param F14C A [`logical`] scalar: should estimated F14C values be used |
|
91 |
#' instead of radiocarbon ages? |
|
92 |
#' @return |
|
93 |
#' A `list` of `list` with the following elements: |
|
94 |
#' \tabular{ll}{ |
|
95 |
#' `mu` \tab Interpolated values \cr |
|
96 |
#' `tau` \tab Interpolated errors \cr |
|
97 |
#' `max` \tab Maximum value of the calibration curve \cr |
|
98 |
#' `min` \tab Minimum value of the calibration curve \cr |
|
99 |
#' } |
|
100 |
#' @keywords internal |
|
101 |
#' @noRd |
|
102 |
approx_curve <- function(name, out, F14C = FALSE) { |
|
103 |
## Get data |
|
104 | 10x |
curve_data <- c14_curve(name) |
105 | ||
106 |
## Interpolate |
|
107 | 10x |
lapply( |
108 | 10x |
X = curve_data, |
109 | 10x |
FUN = function(x, xout, F14C) { |
110 | 10x |
if (F14C) { |
111 | ! |
x_f14c <- BP14C_to_F14C(x[, 2], x[, 3]) |
112 | ! |
x[, 2] <- x_f14c$value |
113 | ! |
x[, 3] <- x_f14c$error |
114 |
} |
|
115 | ||
116 | 10x |
list( |
117 | 10x |
mu = stats::approx(x[, 1], x[, 2], xout = xout)$y, |
118 | 10x |
tau = stats::approx(x[, 1], x[, 3], xout = xout)$y, |
119 | 10x |
max = max(x[, 2]), |
120 | 10x |
min = min(x[, 2]) |
121 |
) |
|
122 |
}, |
|
123 | 10x |
xout = out, |
124 | 10x |
F14C = F14C |
125 |
) |
|
126 |
} |
1 |
# REC |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname c14_ensemble |
|
7 |
#' @aliases c14_ensemble,CalibratedAges-method |
|
8 |
setMethod( |
|
9 |
f = "c14_ensemble", |
|
10 |
signature = "CalibratedAges", |
|
11 |
definition = function(object, from = NULL, to = NULL, by = 10, n = 100, |
|
12 |
calendar = BP(), progress = getOption("ananke.progress")) { |
|
13 |
## Check |
|
14 | ! |
c14_validate(object) |
15 | ||
16 |
## Get data |
|
17 | ! |
rd <- aion::time(object, calendar = NULL) |
18 | ! |
if (is.null(from)) from <- aion::start(object, calendar = calendar) |
19 | ! |
if (is.null(to)) to <- aion::end(object, calendar = calendar) |
20 | ! |
grid_years <- seq(from = from, to = to, by = by * sign(to - from)) |
21 | ! |
grid_rd <- aion::fixed(grid_years, calendar = calendar) |
22 | ||
23 |
## Align 14C date densities onto the grid |
|
24 | ! |
c14_dens <- object[, , 1, drop = TRUE] |
25 | ! |
c14_aligned <- apply( |
26 | ! |
X = c14_dens, |
27 | ! |
MARGIN = 2, |
28 | ! |
FUN = function(y, x, grid) { |
29 | ! |
fun <- stats::approxfun(x = x, y = y) |
30 | ! |
fun(grid) |
31 |
}, |
|
32 | ! |
x = rd, |
33 | ! |
grid = grid_rd |
34 |
) |
|
35 | ! |
c14_aligned[is.na(c14_aligned)] <- 0 |
36 | ||
37 |
## Build matrix to store the RECE |
|
38 | ! |
count <- matrix(data = 0, nrow = n, ncol = length(grid_rd)) |
39 | ! |
colnames(count) <- grid_rd |
40 | ||
41 | ! |
progress_bar <- progress |
42 | ! |
if (progress_bar) pbar <- utils::txtProgressBar(max = n, style = 3) |
43 | ||
44 | ! |
n_seq <- seq_len(n) |
45 | ! |
for (i in n_seq) { |
46 |
## Sample |
|
47 | ! |
spl <- apply( |
48 | ! |
X = c14_aligned, |
49 | ! |
MARGIN = 2, |
50 | ! |
FUN = function(x, grid) { |
51 | ! |
if (sum(x) == 0) return(NA) |
52 | ! |
sample(grid, size = 1, prob = x) |
53 |
}, |
|
54 | ! |
grid = grid_rd |
55 |
) |
|
56 |
## Count |
|
57 | ! |
tbl <- unclass(table(spl)) # Named integer vector |
58 | ! |
count[i, names(tbl)] <- tbl |
59 | ! |
if (progress_bar) utils::setTxtProgressBar(pbar, i) |
60 |
} |
|
61 | ! |
count[is.na(count)] <- 0 |
62 | ! |
if (progress_bar) close(pbar) |
63 | ||
64 |
## Return an RECE object |
|
65 | ! |
ts <- aion::series( |
66 | ! |
object = t(count), |
67 | ! |
time = grid_rd |
68 |
# names = colnames(object) |
|
69 |
) |
|
70 | ! |
.RECE(ts) |
71 |
} |
|
72 |
) |
1 |
# AGE-DEPTH MODELING |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname proxy_ensemble |
|
7 |
#' @aliases proxy_ensemble,numeric-method |
|
8 |
setMethod( |
|
9 |
f = "proxy_ensemble", |
|
10 |
signature = c("numeric"), |
|
11 |
definition = function(positions, proxy_values, proxy_errors, proxy_step, |
|
12 |
time_values, time_errors, calendar, |
|
13 |
from = NULL, to = NULL, by = NULL, n = 30, |
|
14 |
progress = getOption("ananke.progress"), |
|
15 |
verbose = getOption("ananke.verbose")) { |
|
16 |
## Validation |
|
17 | ! |
k <- length(positions) |
18 | ! |
if (length(proxy_errors) == 1) proxy_errors <- rep(proxy_errors, k) |
19 | ! |
arkhe::assert_positive(positions) |
20 | ! |
arkhe::assert_decreasing(positions) |
21 | ! |
arkhe::assert_length(proxy_values, k) |
22 | ! |
arkhe::assert_length(proxy_errors, k) |
23 | ! |
arkhe::assert_length(proxy_step, 1) |
24 | ! |
arkhe::assert_length(time_values, k) |
25 | ! |
arkhe::assert_length(time_errors, k) |
26 | ||
27 |
## Missing values |
|
28 | ! |
if (is.null(from)) from <- time_values[[1L]] |
29 | ! |
if (is.null(to)) to <- time_values[[k]] |
30 | ! |
if (is.null(by)) { |
31 | ! |
grid <- getOption("ananke.grid") |
32 | ! |
by <- ((to - from) / (grid - 1)) |
33 |
} |
|
34 | ! |
if (from > to && by > 0) by <- by * -1 |
35 | ||
36 |
## Build a matrix to contain the p(t|zi) densities |
|
37 |
## Rows will refer to depth |
|
38 |
## Columns will refer to the time density |
|
39 | ! |
if (verbose) cat(tr_("Computing p(t|zi) densities..."), sep = "\n") |
40 | ! |
t_grid <- seq(from = from, to = to, by = by) |
41 | ||
42 | ! |
t_z <- .mapply( |
43 | ! |
FUN = function(min, max, x) { |
44 | ! |
stats::dunif(x = x, min = min, max = max) |
45 |
}, |
|
46 | ! |
dots = list( |
47 | ! |
min = time_values - 1 * time_errors, |
48 | ! |
max = time_values + 1 * time_errors |
49 |
), |
|
50 | ! |
MoreArgs = list(x = t_grid) |
51 |
) |
|
52 | ! |
t_z <- do.call(rbind, t_z) |
53 | ! |
t_z <- t(t_z) |
54 | ||
55 |
## Build a matrix to contain the p(x|zi) densities |
|
56 |
## Rows will refer to depth |
|
57 |
## Columns will refer to the proxy density |
|
58 | ! |
if (verbose) cat(tr_("Computing p(x|zi) densities..."), sep = "\n") |
59 | ! |
d <- 2 * max(proxy_errors) |
60 | ! |
x_range <- range(c(range(proxy_values) - d, range(proxy_values) + d)) |
61 | ! |
x_grid <- seq(from = x_range[[1L]], to = x_range[[2L]], by = proxy_step) |
62 | ||
63 | ! |
x_z <- .mapply( |
64 | ! |
FUN = function(mean, sd, x) { |
65 | ! |
stats::dnorm(x = x, mean = mean, sd = sd) |
66 |
}, |
|
67 | ! |
dots = list( |
68 | ! |
mean = proxy_values, |
69 | ! |
sd = proxy_errors |
70 |
), |
|
71 | ! |
MoreArgs = list(x = x_grid) |
72 |
) |
|
73 | ! |
x_z <- do.call(rbind, x_z) |
74 | ! |
x_z <- t(x_z) |
75 | ||
76 |
## Estimate the weighted average density function |
|
77 |
## (for a given proxy measurement at a given time) |
|
78 |
## Eq. 4 of Boers et al. 2017 |
|
79 | ! |
if (verbose) cat(tr_("Computing p(x|t) densities..."), sep = "\n") |
80 | ||
81 | ! |
z <- length(positions) |
82 | ! |
ri <- vapply( |
83 | ! |
X = 2:(z - 1), |
84 | ! |
FUN = function(x, y) (y[x + 1] - y[x - 1]) / 2, |
85 | ! |
FUN.VALUE = numeric(1), |
86 | ! |
y = positions |
87 |
) |
|
88 | ! |
r <- abs(c(positions[2] - positions[1], ri, positions[z] - positions[z - 1])) |
89 | ! |
r_t <- matrix(data = r, nrow = nrow(t_z), ncol = ncol(t_z), byrow = TRUE) |
90 | ! |
r_x <- matrix(data = r, nrow = nrow(x_z), ncol = ncol(x_z), byrow = TRUE) |
91 | ||
92 | ! |
x_t <- t(tcrossprod(r_x * x_z, t_z)) / rowSums(r_t * t_z) |
93 | ||
94 |
## Create an ensemble of potential proxy records |
|
95 | ! |
if (verbose) cat(tr_("Sampling proxy records..."), sep = "\n") |
96 | ! |
Y <- matrix(data = 0, nrow = length(t_grid), ncol = n) |
97 | ||
98 | ! |
if (progress) pb <- utils::txtProgressBar(min = 0, max = n, style = 3) |
99 | ||
100 | ! |
n_seq <- seq_len(n) |
101 | ! |
for (i in n_seq) { |
102 |
## Sample |
|
103 | ! |
Y[, i] <- apply( |
104 | ! |
X = x_t, |
105 | ! |
MARGIN = 1, |
106 | ! |
FUN = function(x, g) sample(g, size = 1, prob = x), |
107 | ! |
g = x_grid |
108 |
) |
|
109 | ! |
if (progress) utils::setTxtProgressBar(pb, i) |
110 |
} |
|
111 | ||
112 | ! |
if (progress) close(pb) |
113 | ||
114 | ! |
ts <- aion::series(object = Y, time = t_grid, calendar = calendar) |
115 | ! |
.ProxyRecord(ts, density = x_t, proxy = x_grid) |
116 |
} |
|
117 |
) |
1 |
# COERCION |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# To list ====================================================================== |
|
6 |
#' @export |
|
7 |
#' @method as.list CalibratedIntervals |
|
8 |
as.list.CalibratedIntervals <- function(x, ..., calendar = get_calendar()) { |
|
9 | 4x |
z <- as.data.frame(x, calendar = calendar) |
10 | 4x |
f <- factor(z$label, levels = unique(z$label)) |
11 | 4x |
z$label <- NULL |
12 | 4x |
split(x = z, f = f) |
13 |
} |
|
14 | ||
15 |
#' @export |
|
16 |
#' @rdname as.list |
|
17 |
#' @aliases as.list,CalibratedIntervals-method |
|
18 |
setMethod("as.list", "CalibratedIntervals", as.list.CalibratedIntervals) |
|
19 | ||
20 |
# To data.frame ================================================================ |
|
21 |
#' @export |
|
22 |
#' @method as.data.frame CalibratedAges |
|
23 |
as.data.frame.CalibratedAges <- function(x, ..., |
|
24 |
calendar = get_calendar()) { |
|
25 | ! |
dens <- x[, , 1, drop = TRUE] |
26 | ! |
z <- data.frame(aion::time(x, calendar = calendar), dens) |
27 | ! |
colnames(z) <- c("time", colnames(x) %||% paste0("X", seq_len(NCOL(x)))) |
28 | ! |
z |
29 |
} |
|
30 | ||
31 |
#' @export |
|
32 |
#' @rdname as.data.frame |
|
33 |
#' @aliases as.data.frame,CalibratedAges-method |
|
34 |
setMethod("as.data.frame", "CalibratedAges", as.data.frame.CalibratedAges) |
|
35 | ||
36 |
#' @export |
|
37 |
#' @method as.data.frame CalibratedIntervals |
|
38 |
as.data.frame.CalibratedIntervals <- function(x, ..., |
|
39 |
calendar = get_calendar()) { |
|
40 |
## Build a data frame |
|
41 | 4x |
data.frame( |
42 | 4x |
label = labels(x), |
43 | 4x |
start = start(x, calendar = calendar), |
44 | 4x |
end = end(x, calendar = calendar), |
45 | 4x |
p = x@p |
46 |
) |
|
47 |
} |
|
48 | ||
49 |
#' @export |
|
50 |
#' @rdname as.data.frame |
|
51 |
#' @aliases as.data.frame,CalibratedIntervals-method |
|
52 |
setMethod("as.data.frame", "CalibratedIntervals", as.data.frame.CalibratedIntervals) |
|
53 | ||
54 |
#' @export |
|
55 |
#' @method as.data.frame RECE |
|
56 |
as.data.frame.RECE <- function(x, ..., calendar = get_calendar()) { |
|
57 | ! |
dens <- x[, , 1, drop = TRUE] |
58 | ! |
z <- data.frame(aion::time(x, calendar = calendar), dens) |
59 | ! |
colnames(z) <- c("time", colnames(x) %||% paste0("X", seq_len(NCOL(x)))) |
60 | ! |
z |
61 |
} |
|
62 | ||
63 |
#' @export |
|
64 |
#' @rdname as.data.frame |
|
65 |
#' @aliases as.data.frame,RECE-method |
|
66 |
setMethod("as.data.frame", "RECE", as.data.frame.RECE) |
|
67 | ||
68 |
#' @export |
|
69 |
#' @method as.data.frame ProxyRecord |
|
70 |
as.data.frame.ProxyRecord <- function(x, ..., |
|
71 |
calendar = get_calendar()) { |
|
72 | ! |
dens <- x[, , 1, drop = TRUE] |
73 | ! |
z <- data.frame(aion::time(x, calendar = calendar), dens) |
74 | ! |
colnames(z) <- c("time", colnames(x) %||% paste0("X", seq_len(NCOL(x)))) |
75 | ! |
z |
76 |
} |
|
77 | ||
78 |
#' @export |
|
79 |
#' @rdname as.data.frame |
|
80 |
#' @aliases as.data.frame,ProxyRecord-method |
|
81 |
setMethod("as.data.frame", "ProxyRecord", as.data.frame.ProxyRecord) |
1 |
# GENERIC METHODS |
|
2 |
#' @include AllClasses.R |
|
3 |
NULL |
|
4 | ||
5 |
# Import S4 generics =========================================================== |
|
6 |
#' @importMethodsFrom arkhe describe |
|
7 |
#' @importMethodsFrom arkhe interval_credible |
|
8 |
#' @importMethodsFrom arkhe interval_hdr |
|
9 |
NULL |
|
10 | ||
11 |
# Tools ======================================================================== |
|
12 |
## Mutators -------------------------------------------------------------------- |
|
13 |
#' Get or Set Parts of an Object |
|
14 |
#' |
|
15 |
#' Getters and setters to extract or replace parts of an object. |
|
16 |
#' @param x An object from which to get or set element(s). |
|
17 |
#' @param value A possible value for the element(s) of `x`. |
|
18 |
#' @return |
|
19 |
#' An object of the same sort as `x` with the new values assigned. |
|
20 |
# @example inst/examples/ex-mutator.R |
|
21 |
#' @author N. Frerebeau |
|
22 |
#' @docType methods |
|
23 |
#' @family mutators |
|
24 |
#' @name mutators |
|
25 |
#' @rdname mutators |
|
26 |
#' @aliases get set |
|
27 |
NULL |
|
28 | ||
29 |
#' Find Labels from Object |
|
30 |
#' |
|
31 |
#' Find a suitable set of labels from an object for use in printing or plotting, |
|
32 |
#' for example. |
|
33 |
#' @param object An object from which to find labels. |
|
34 |
#' @param ... Currently not used. |
|
35 |
#' @return |
|
36 |
#' A [`character`] vector. |
|
37 |
# @example inst/examples/ex-mutator.R |
|
38 |
#' @author N. Frerebeau |
|
39 |
#' @docType methods |
|
40 |
#' @family mutators |
|
41 |
#' @name labels |
|
42 |
#' @rdname labels |
|
43 |
NULL |
|
44 | ||
45 |
## Subset ---------------------------------------------------------------------- |
|
46 |
#' Extract or Replace Parts of an Object |
|
47 |
#' |
|
48 |
#' Operators acting on objects to extract or replace parts. |
|
49 |
#' @param x An object from which to extract element(s) or in which to replace |
|
50 |
#' element(s). |
|
51 |
#' @param i,j,k Indices specifying elements to extract or replace. |
|
52 |
#' @param drop A [`logical`] scalar: should the result be coerced to |
|
53 |
#' the lowest possible dimension? This only works for extracting elements, |
|
54 |
#' not for the replacement. |
|
55 |
# @param value A possible value for the element(s) of `x`. |
|
56 |
# @param ... Currently not used. |
|
57 |
#' @return |
|
58 |
#' A subsetted object. |
|
59 |
# @example inst/examples/ex-subset.R |
|
60 |
#' @author N. Frerebeau |
|
61 |
#' @docType methods |
|
62 |
#' @family mutators |
|
63 |
#' @name subset |
|
64 |
#' @rdname subset |
|
65 |
NULL |
|
66 | ||
67 |
## Coerce ---------------------------------------------------------------------- |
|
68 |
#' Coerce to a Data Frame |
|
69 |
#' |
|
70 |
#' @inheritParams as.list |
|
71 |
#' @return |
|
72 |
#' A [`data.frame`] with an extra `time` column. |
|
73 |
#' @example inst/examples/ex-coerce.R |
|
74 |
#' @author N. Frerebeau |
|
75 |
#' @docType methods |
|
76 |
#' @family mutators |
|
77 |
#' @name as.data.frame |
|
78 |
#' @rdname as.data.frame |
|
79 |
NULL |
|
80 | ||
81 |
#' Coerce to a list |
|
82 |
#' |
|
83 |
#' @param x An object. |
|
84 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
85 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
86 |
#' @param ... Currently not used. |
|
87 |
#' @return |
|
88 |
#' A [`list`]. |
|
89 |
#' @example inst/examples/ex-coerce.R |
|
90 |
#' @author N. Frerebeau |
|
91 |
#' @docType methods |
|
92 |
#' @family mutators |
|
93 |
#' @name as.list |
|
94 |
#' @rdname as.list |
|
95 |
NULL |
|
96 | ||
97 |
# Radiocarbon ================================================================== |
|
98 |
## Calibration curve ----------------------------------------------------------- |
|
99 |
#' 14C Calibration Curve |
|
100 |
#' |
|
101 |
#' @param name A [`character`] vector naming calibration curves (see details). |
|
102 |
#' @param ... Currently not used. |
|
103 |
#' @details |
|
104 |
#' The following calibration curves are available: |
|
105 |
#' |
|
106 |
#' \tabular{ll}{ |
|
107 |
#' **Curve** \tab **Reference** \cr |
|
108 |
# `bomb04nh1` \tab Hua and Barbetti 2004 \cr |
|
109 |
# `bomb04nh2` \tab Hua and Barbetti 2004 \cr |
|
110 |
# `bomb04nh3` \tab Hua and Barbetti 2004 \cr |
|
111 |
# `bomb04sh` \tab Hua and Barbetti 2004 \cr |
|
112 |
# `bomb13nh1` \tab Hua, Berbetti and Rakowski 2013 \cr |
|
113 |
# `bomb13nh2` \tab Hua, Berbetti and Rakowski 2013 \cr |
|
114 |
# `bomb13nh3` \tab Hua, Berbetti and Rakowski 2013 \cr |
|
115 |
# `bomb13sh12` \tab Hua, Berbetti and Rakowski 2013 \cr |
|
116 |
# `bomb13sh3` \tab Hua, Berbetti and Rakowski 2013 \cr |
|
117 |
# `bomb21nh1` \tab Hua et al. 2022 \cr |
|
118 |
# `bomb21nh2` \tab Hua et al. 2022 \cr |
|
119 |
# `bomb21nh3` \tab Hua et al. 2022 \cr |
|
120 |
# `bomb21sh12` \tab Hua et al. 2022 \cr |
|
121 |
# `bomb21sh3` \tab Hua et al. 2022 \cr |
|
122 |
# `cariaco04` \tab Hughen et al. 2004 \cr |
|
123 |
# `intcal98` \tab Stuiver et al. 1998 \cr |
|
124 |
#' `intcal04` \tab Reimer et al. 2004 \cr |
|
125 |
#' `intcal09` \tab Reimer et al. 2009 \cr |
|
126 |
#' `intcal13` \tab Reimer et al. 2013 \cr |
|
127 |
#' `intcal20` \tab Reimer et al. 2020 \cr |
|
128 |
# `kueppers04` \tab Kueppers et al. 2004 \cr |
|
129 |
#d `marine98` \tab Stuiver, Reimer and Braziunas 1998 \cr |
|
130 |
#' `marine04` \tab Hughen et al. 2004 \cr |
|
131 |
#' `marine09` \tab Reimer et al. 2009 \cr |
|
132 |
#' `marine13` \tab Reimer et al. 2013 \cr |
|
133 |
#' `marine20` \tab Heaton et al. 2020 \cr |
|
134 |
#' `shcal04` \tab McCormac et al. 2004 \cr |
|
135 |
#' `shcal13` \tab Hogg et al. 2013 \cr |
|
136 |
#' `shcal20` \tab Hogg et al. 2020 \cr |
|
137 |
#' } |
|
138 |
#' |
|
139 |
#' @return |
|
140 |
#' A `list` of three-column [`data.frame`]: |
|
141 |
#' \tabular{ll}{ |
|
142 |
#' `CALBP` \tab Calibrated age BP \cr |
|
143 |
#' `AGE` \tab Uncalibrated radiocarbon age \cr |
|
144 |
#' `ERROR` \tab Standard deviation \cr |
|
145 |
#' } |
|
146 |
#' @references |
|
147 |
#' Heaton, Timothy J, Peter Köhler, Martin Butzin, Edouard Bard, Ron W Reimer, |
|
148 |
#' William E N Austin, Christopher Bronk Ramsey, et al. (2020). Marine20 The |
|
149 |
#' Marine Radiocarbon Age Calibration Curve (0-55,000 Cal BP). |
|
150 |
#' *Radiocarbon*, 62(4): 779-820. \doi{10.1017/RDC.2020.68}. |
|
151 |
#' |
|
152 |
#' Hogg, Alan G, Timothy J Heaton, Quan Hua, Jonathan G Palmer, Chris SM |
|
153 |
#' Turney, John Southon, Alex Bayliss, et al. (2020). SHCal20 Southern |
|
154 |
#' Hemisphere Calibration, 0-55,000 Years Cal BP. *Radiocarbon*, 62(4): 759-78. |
|
155 |
#' \doi{10.1017/RDC.2020.59}. |
|
156 |
#' |
|
157 |
#' Hogg, Alan G, Quan Hua, Paul G Blackwell, Mu Niu, Caitlin E Buck, Thomas P |
|
158 |
#' Guilderson, Timothy J Heaton, et al. (2013). SHCal13 Southern Hemisphere |
|
159 |
#' Calibration, 0-50,000 Years Cal BP. *Radiocarbon*, 55(4): 1889-1903. |
|
160 |
#' \doi{10.2458/azu_js_rc.55.16783}. |
|
161 |
#' |
|
162 |
#' Hua, Quan, and Mike Barbetti (2004). Review of Tropospheric Bomb 14C Data |
|
163 |
#' for Carbon Cycle Modeling and Age Calibration Purposes. *Radiocarbon*, |
|
164 |
#' 46(3): 1273-1298. \doi{10.1017/S0033822200033142}. |
|
165 |
#' |
|
166 |
#' Hua, Quan, Mike Barbetti, and Andrzej Z Rakowski (2013). Atmospheric |
|
167 |
#' Radiocarbon for the Period 1950-2010. *Radiocarbon*, 55(4): 2059‑2072. |
|
168 |
#' \doi{10.2458/azu_js_rc.v55i2.16177}. |
|
169 |
#' |
|
170 |
#' Hua, Quan, Jocelyn C Turnbull, Guaciara M Santos, Andrzej Z Rakowski, |
|
171 |
#' Santiago Ancapichún, Ricardo De Pol-Holz, Samuel Hammer, et al. (2022). |
|
172 |
#' Atmospheric Radiocarbon for the Period 1950-2019. *Radiocarbon*, |
|
173 |
#' 64(4): 723‑745. \doi{10.1017/RDC.2021.95}. |
|
174 |
#' |
|
175 |
#' Hughen, K., S. Lehman, J. Southon, J. Overpeck, O. Marchal, C. Herring, |
|
176 |
#' and J. Turnbull (2004). 14C Activity and Global Carbon Cycle Changes over |
|
177 |
#' the Past 50,000 Years. *Science*, 303(5655): 202‑207. |
|
178 |
#' \doi{10.1126/science.1090300}. |
|
179 |
#' |
|
180 |
#' Hughen, Konrad A, Mike G L Baillie, Edouard Bard, J Warren Beck, Chanda J H |
|
181 |
#' Bertrand, Paul G Blackwell, Caitlin E Buck, et al. (2004). Marine04 Marine |
|
182 |
#' Radiocarbon Age Calibration, 0-26 cal kyr BP. *Radiocarbon*, |
|
183 |
#' 46(3): 1059‑1086. \doi{10.1017/S0033822200033002}. |
|
184 |
#' |
|
185 |
#' Kueppers, Lara M., John Southon, Paul Baer, and John Harte (2004). Dead Wood |
|
186 |
#' Biomass and Turnover Time, Measured by Radiocarbon, along a Subalpine |
|
187 |
#' Elevation Gradient. *Oecologia*, 141(4): 641‑651. |
|
188 |
#' \doi{10.1007/s00442-004-1689-x}. |
|
189 |
#' |
|
190 |
#' McCormac, F G, A G Hogg, P G Blackwell, C E Buck, T F G Higham, and P J |
|
191 |
#' Reimer (2004). Shcal04 Southern Hemisphere Calibration, 0-11.0 cal kyr BP. |
|
192 |
#' *Radiocarbon*, 46(3): 1087‑1092. \doi{10.1017/S0033822200033014}. |
|
193 |
#' |
|
194 |
#' Reimer, P J, M G L Baillie, E Bard, A Bayliss, J W Beck, P G Blackwell, |
|
195 |
#' C Bronk Ramsey, et al. (2009). IntCal09 and Marine09 Radiocarbon Age |
|
196 |
#' Calibration Curves, 0-50,000 Years cal BP. *Radiocarbon*, 51(4): 1111‑1150. |
|
197 |
#' \doi{10.1017/S0033822200034202}. |
|
198 |
#' |
|
199 |
#' Reimer, Paula J, William E N Austin, Edouard Bard, Alex Bayliss, Paul G |
|
200 |
#' Blackwell, Christopher Bronk Ramsey, Martin Butzin, et al. (2020). |
|
201 |
#' The IntCal20 Northern Hemisphere Radiocarbon Age Calibration Curve |
|
202 |
#' (0-55 cal kBP). *Radiocarbon*, 62(4): 725‑757. \doi{10.1017/RDC.2020.41}. |
|
203 |
#' |
|
204 |
#' Reimer, Paula J, Mike G L Baillie, Edouard Bard, Alex Bayliss, |
|
205 |
#' J Warren Beck, Chanda J H Bertrand, Paul G Blackwell, et al. (2004). |
|
206 |
#' Intcal04 Terrestrial Radiocarbon Age Calibration, 0-26 cal kyr BP. |
|
207 |
#' *Radiocarbon*, 46(3): 1029‑1058. \doi{10.1017/S0033822200032999}. |
|
208 |
#' |
|
209 |
#' Reimer, Paula J, Edouard Bard, Alex Bayliss, J Warren Beck, Paul G |
|
210 |
#' Blackwell, Christopher Bronk Ramsey, Caitlin E Buck, et al. (2013). |
|
211 |
#' IntCal13 and Marine13 Radiocarbon Age Calibration Curves 0-50,000 |
|
212 |
#' Years cal BP. *Radiocarbon*, 55(4): 1869‑1887. |
|
213 |
#' \doi{10.2458/azu_js_rc.55.16947}. |
|
214 |
#' |
|
215 |
#' Stuiver, Minze, Paula J. Reimer, Edouard Bard, J. Warren Beck, G. S. Burr, |
|
216 |
#' Konrad A. Hughen, Bernd Kromer, Gerry McCormac, Johannes van der Plicht, and |
|
217 |
#' Marco Spurk (1998). INTCAL98 Radiocarbon Age Calibration, 24,000-0 cal BP. |
|
218 |
#' *Radiocarbon*, 40(3): 1041‑1083. \doi{10.1017/S0033822200019123}. |
|
219 |
#' |
|
220 |
#' Stuiver, Minze, Paula J. Reimer, and Thomas F. Braziunas. (1998). |
|
221 |
#' High-Precision Radiocarbon Age Calibration for Terrestrial and Marine |
|
222 |
#' Samples. *Radiocarbon*, 40(3): 1127‑1151. \doi{10.1017/S0033822200019172}. |
|
223 |
#' @example inst/examples/ex-14c-curve.R |
|
224 |
#' @author N. Frerebeau |
|
225 |
#' @docType methods |
|
226 |
#' @family radiocarbon tools |
|
227 |
#' @aliases c14_curve-method |
|
228 |
setGeneric( |
|
229 |
name = "c14_curve", |
|
230 | 11x |
def = function(name, ...) standardGeneric("c14_curve") |
231 |
) |
|
232 | ||
233 |
## Calibration ----------------------------------------------------------------- |
|
234 |
#' 14C Calibration |
|
235 |
#' |
|
236 |
#' Calibrates radiocarbon ages. |
|
237 |
#' @param values A [`numeric`] vector giving the BP ages or F14C values to be |
|
238 |
#' calibrated (conventional ages). |
|
239 |
#' @param errors A [`numeric`] vector giving the errors associated to the |
|
240 |
#' values to be calibrated. |
|
241 |
#' @param curves A [`character`] vector specifying the calibration curve to be |
|
242 |
#' used. Different curves can be specified per sample. |
|
243 |
#' @param names A [`character`] vector specifying the names of the samples (e.g. |
|
244 |
#' laboratory codes). |
|
245 |
#' @param positions A [`numeric`] vector giving the position values (e.g. |
|
246 |
#' depths) for each age. |
|
247 |
#' @param reservoir_offsets A [`numeric`] vector giving the offset values for |
|
248 |
#' any marine reservoir effect (defaults to 0; i.e. no offset). |
|
249 |
#' @param reservoir_errors A [`numeric`] vector giving the offset value errors |
|
250 |
#' for any marine reservoir effect (defaults to 0; i.e. no offset). |
|
251 |
#' @param from length-one [`numeric`] vector specifying the earliest data to |
|
252 |
#' calibrate for, in cal. BP years. |
|
253 |
#' @param to A length-one [`numeric`] vector specifying the latest data to |
|
254 |
#' calibrate for, in cal. BP years. |
|
255 |
#' @param resolution A length-one [`numeric`] vector specifying the temporal |
|
256 |
#' resolution (in years) of the calibration. |
|
257 |
#' @param normalize A [`logical`] scalar: should the calibration be normalized? |
|
258 |
#' @param F14C A [`logical`] scalar: should the calibration be carried out in |
|
259 |
#' F14C space? If `TRUE`, `values` must be expressed as F14C. |
|
260 |
#' @param method A [`character`] string specifying the distribution assumed for |
|
261 |
#' the 14C ages. It must be one of "`student`" (the default) or "`normal`. |
|
262 |
#' Only used if `F14C` is `FALSE`. |
|
263 |
#' @param dfs A [`character`] vector giving the degrees-of-freedom values for |
|
264 |
#' the student t-distribution associated with the calibration calculation. |
|
265 |
#' Only used if `method` is "`student`". |
|
266 |
#' @param drop A [`logical`] scalar: should years with zero probability be |
|
267 |
#' discarded? If `TRUE` (the default), results in a narrower time range. |
|
268 |
#' @param eps A length-one [`numeric`] value giving the cutoff below which |
|
269 |
#' calibration values will be removed. |
|
270 |
#' @param verbose A [`logical`] scalar: should extra information be reported |
|
271 |
#' (e.g. warning message for dates out of calibration range)? |
|
272 |
#' @param ... Currently not used. |
|
273 |
#' @return |
|
274 |
#' A [`CalibratedAges-class`] object. |
|
275 |
#' @references |
|
276 |
#' Bronk Ramsey, C. (2008). Radiocarbon Dating: Revolutions in Understanding. |
|
277 |
#' *Archaeometry*, 50:249-275. \doi{10.1111/j.1475-4754.2008.00394.x}. |
|
278 |
#' @note |
|
279 |
#' Adapted from \pkg{Bchron} `BchronCalibrate()` by Andrew Parnell and |
|
280 |
#' \pkg{rcarbon} `calibrate()` by Andrew Bevan and Enrico Crema. |
|
281 |
#' @example inst/examples/ex-14c-calibrate.R |
|
282 |
#' @author N. Frerebeau |
|
283 |
#' @docType methods |
|
284 |
#' @family radiocarbon tools |
|
285 |
#' @aliases c14_calibrate-method |
|
286 |
setGeneric( |
|
287 |
name = "c14_calibrate", |
|
288 |
def = function(values, errors, ...) standardGeneric("c14_calibrate"), |
|
289 |
valueClass = "CalibratedAges" |
|
290 |
) |
|
291 | ||
292 |
#' Uncalibrate a Radiocarbon Date |
|
293 |
#' |
|
294 |
#' @param object A [`CalibratedAges-class`] object or a [`numeric`] vector of |
|
295 |
#' calibrated ages (in years BP). |
|
296 |
#' @param n An [`integer`] specifying the number of random samples. |
|
297 |
#' @param curves A [`character`] vector specifying the calibration curve to be |
|
298 |
#' used. Different curves can be specified. |
|
299 |
#' @param rounding A [`character`] string specifying the rounding convention. |
|
300 |
#' It can be one of "`none`" (the default, no rounding) or "`stuiver`". |
|
301 |
#' Any unambiguous substring can be given. |
|
302 |
#' @param ... Currently not used. |
|
303 |
#' @example inst/examples/ex-14c-uncalibrate.R |
|
304 |
#' @author N. Frerebeau |
|
305 |
#' @docType methods |
|
306 |
#' @family radiocarbon tools |
|
307 |
#' @aliases c14_uncalibrate-method |
|
308 |
setGeneric( |
|
309 |
name = "c14_uncalibrate", |
|
310 | 1x |
def = function(object, ...) standardGeneric("c14_uncalibrate") |
311 |
) |
|
312 | ||
313 |
## F14C ------------------------------------------------------------------------ |
|
314 |
#' F14C |
|
315 |
#' |
|
316 |
#' Converts F14C values to 14C ages. |
|
317 |
#' @param values A [`numeric`] vector giving the radiocarbon ages or the F14C |
|
318 |
#' values. |
|
319 |
#' @param errors A [`numeric`] vector giving the standard deviations. |
|
320 |
#' @param lambda A length-one [`numeric`] vector specifying the mean-life of |
|
321 |
#' radiocarbon (defaults to 14C half-life value as introduced by Libby 1952). |
|
322 |
#' @param asymmetric A [`logical`] scalar: should asymmetric 14C errors be |
|
323 |
#' returned (van der Plicht & Hogg, 2006)? |
|
324 |
#' @param rounding A [`character`] string specifying the rounding convention. |
|
325 |
#' It can be one of "`none`" (the default, no rounding) or "`stuiver`". |
|
326 |
#' Any unambiguous substring can be given. |
|
327 |
#' @param ... Currently not used. |
|
328 |
#' @return |
|
329 |
#' A [`data.frame`]. |
|
330 |
#' @references |
|
331 |
#' Bronk Ramsey, C. (2008). Radiocarbon Dating: Revolutions in Understanding. |
|
332 |
#' *Archaeometry*, 50:249-275. \doi{10.1111/j.1475-4754.2008.00394.x}. |
|
333 |
#' |
|
334 |
#' Stuiver, M., Polach, H. A. (1977). Discussion Reporting of 14C Data. |
|
335 |
#' *Radiocarbon*, 19(3): 355-363. \doi{10.1017/S0033822200003672}. |
|
336 |
#' |
|
337 |
#' van der Plicht, J., Hogg, A. (2006). A Note on Reporting Radiocarbon. |
|
338 |
#' *Quaternary Geochronology*, 1(4): 237-240. |
|
339 |
#' \doi{10.1016/j.quageo.2006.07.001}. |
|
340 |
#' @example inst/examples/ex-f14c.R |
|
341 |
#' @author N. Frerebeau |
|
342 |
#' @docType methods |
|
343 |
#' @family radiocarbon tools |
|
344 |
#' @name F14C |
|
345 |
#' @rdname F14C |
|
346 |
NULL |
|
347 | ||
348 |
#' @rdname F14C |
|
349 |
#' @aliases BP14C_to_F14C-method |
|
350 |
setGeneric( |
|
351 |
name = "BP14C_to_F14C", |
|
352 |
def = function(values, errors, ...) standardGeneric("BP14C_to_F14C"), |
|
353 |
valueClass = "data.frame" |
|
354 |
) |
|
355 | ||
356 |
#' @rdname F14C |
|
357 |
#' @aliases F14C_to_BP14C-method |
|
358 |
setGeneric( |
|
359 |
name = "F14C_to_BP14C", |
|
360 |
def = function(values, errors, ...) standardGeneric("F14C_to_BP14C"), |
|
361 |
valueClass = "data.frame" |
|
362 |
) |
|
363 | ||
364 |
## Combine --------------------------------------------------------------------- |
|
365 |
#' Combine 14C |
|
366 |
#' |
|
367 |
#' Combines radiocarbon dates. |
|
368 |
#' @param values A [`numeric`] vector giving the BP ages to be calibrated. |
|
369 |
#' @param errors A [`numeric`] vector giving the standard deviation of the ages |
|
370 |
#' to be calibrated. |
|
371 |
#' @param groups A [`factor`] in the sense that `as.factor(groups)` defines the |
|
372 |
#' the groups to combine with. If `NULL` (the default), all dates are combined. |
|
373 |
#' `NA`s will be treated as isolated dates. |
|
374 |
#' @param ... Currently not used. |
|
375 |
#' @return |
|
376 |
#' A [`data.frame`] with the following columns: |
|
377 |
#' \tabular{ll}{ |
|
378 |
#' `groups` \tab Group names \cr |
|
379 |
#' `ages` \tab Combined 14C ages \cr |
|
380 |
#' `errors` \tab Combined 14C standard deviations \cr |
|
381 |
#' `chi2` \tab Chi-squared test statistic \cr |
|
382 |
#' `p` \tab Chi-squared test p-value \cr |
|
383 |
#' } |
|
384 |
#' @references |
|
385 |
#' Ward, G. K. and Wilson, S. R. (1978). Procedures for Comparing and Combining |
|
386 |
#' Radiocarbon Age Determinations: A Critique. *Archaeometry* 20(1): 19‑31. |
|
387 |
#' \doi{10.1111/j.1475-4754.1978.tb00208.x}. |
|
388 |
#' @example inst/examples/ex-14c-combine.R |
|
389 |
#' @author N. Frerebeau |
|
390 |
#' @docType methods |
|
391 |
#' @family radiocarbon tools |
|
392 |
#' @aliases c14_combine-method |
|
393 |
setGeneric( |
|
394 |
name = "c14_combine", |
|
395 |
def = function(values, errors, ...) standardGeneric("c14_combine"), |
|
396 |
valueClass = "data.frame" |
|
397 |
) |
|
398 | ||
399 |
## Plot ------------------------------------------------------------------------ |
|
400 |
#' Plot Calibrated Radiocarbon Ages |
|
401 |
#' |
|
402 |
#' @param x A [`CalibratedAges-class`] or [`CalibratedSPD-class`] object. |
|
403 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
404 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
405 |
#' @param density A [`logical`] scalar: should density be drawn? |
|
406 |
#' @param interval A [`character`] string specifying the intervals to be drawn. |
|
407 |
#' It must be one of "`hrd`" (the default), "`credible`" or "`none`". |
|
408 |
#' Any unambiguous substring can be given. |
|
409 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
410 |
#' Only used if `interval` is `TRUE`. |
|
411 |
#' @param fixed A [`logical`] scalar: should a fixed y scale be used? |
|
412 |
#' If `TRUE` (the default), ages are equally spaced along the y axis. |
|
413 |
#' If `FALSE`, age `positions` are used (see [c14_calibrate()]). |
|
414 |
#' @param decreasing A [`logical`] scalar: should the sort order be decreasing? |
|
415 |
#' @param main A [`character`] string giving a main title for the plot. |
|
416 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
417 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
418 |
#' and y labels) appear on the plot? |
|
419 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
420 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
421 |
#' plot? |
|
422 |
#' @param panel.first An an `expression` to be evaluated after the plot axes are |
|
423 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
424 |
#' background grids. |
|
425 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
426 |
#' place but before the axes, title and box are added. |
|
427 |
#' @param col.density,col.interval A specification for the plotting colors. |
|
428 |
#' @param ... Other [graphical parameters][graphics::par] may also be passed as |
|
429 |
#' arguments to this function. |
|
430 |
#' @return |
|
431 |
#' `plot()` is called it for its side-effects: it results in a graphic |
|
432 |
#' being displayed. Invisibly returns `x`. |
|
433 |
#' @example inst/examples/ex-14c-plot.R |
|
434 |
#' @author N. Frerebeau |
|
435 |
#' @docType methods |
|
436 |
#' @family radiocarbon tools |
|
437 |
#' @name c14_plot |
|
438 |
#' @rdname c14_plot |
|
439 |
NULL |
|
440 | ||
441 |
#' Plot a Radiocarbon Event Count Ensemble |
|
442 |
#' |
|
443 |
#' @param x An [`RECE-class`] object. |
|
444 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
445 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
446 |
#' @param ... Further parameters to be passed to [graphics::image()]. |
|
447 |
#' @return |
|
448 |
#' `image()` is called it for its side-effects: it results in a graphic being |
|
449 |
#' displayed (invisibly returns `x`). |
|
450 |
#' @references |
|
451 |
#' Carleton, W. C. (2021). Evaluating Bayesian Radiocarbon‐dated Event Count |
|
452 |
#' (REC) Models for the Study of Long‐term Human and Environmental Processes. |
|
453 |
#' *Journal of Quaternary Science*, 36(1): 110‑23. \doi{10.1002/jqs.3256}. |
|
454 |
#' @author N. Frerebeau |
|
455 |
#' @docType methods |
|
456 |
#' @family radiocarbon tools |
|
457 |
#' @name rec_plot |
|
458 |
#' @rdname rec_plot |
|
459 |
NULL |
|
460 | ||
461 |
## Sample ---------------------------------------------------------------------- |
|
462 |
#' Sample Calibrated Ages |
|
463 |
#' |
|
464 |
#' @param object A [`CalibratedAges-class`] object. |
|
465 |
#' @param n An [`integer`] specifying the number of random samples. |
|
466 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
467 |
#' calendar (see [aion::calendar()]). Defaults to [aion::CE()]. If `NULL`, |
|
468 |
#' *rata die* are returned. |
|
469 |
#' @param ... Currently not used. |
|
470 |
#' @example inst/examples/ex-14c-sample.R |
|
471 |
#' @return An `numeric` matrix. |
|
472 |
#' @author N. Frerebeau |
|
473 |
#' @family radiocarbon tools |
|
474 |
#' @docType methods |
|
475 |
#' @aliases c14_sample-method |
|
476 |
setGeneric( |
|
477 |
name = "c14_sample", |
|
478 | 1x |
def = function(object, ...) standardGeneric("c14_sample") |
479 |
) |
|
480 | ||
481 |
## RECE ------------------------------------------------------------------------ |
|
482 |
#' Radiocarbon Event Count |
|
483 |
#' |
|
484 |
#' @param object A [`CalibratedAges-class`] object. |
|
485 |
#' @param from length-one [`numeric`] vector specifying the earliest data to |
|
486 |
#' calibrate for (in cal BP years). |
|
487 |
#' @param to A length-one [`numeric`] vector specifying the latest data to |
|
488 |
#' calibrate for (in cal BP years). |
|
489 |
#' @param by A length-one [`numeric`] vector specifying the temporal |
|
490 |
#' resolution (in years) of the calibration. |
|
491 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
492 |
#' calendar (see [aion::calendar()]). Defaults to [aion::CE()]. If `NULL`, |
|
493 |
#' *rata die* are returned. |
|
494 |
#' @param n An [`integer`] specifying the number of item to choose randomly. |
|
495 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
496 |
#' @param ... Currently not used. |
|
497 |
#' @return |
|
498 |
#' An [`RECE-class`] object. |
|
499 |
#' @note |
|
500 |
#' This function is currently *experimental*. |
|
501 |
#' @references |
|
502 |
#' Carleton, W. C. (2021). Evaluating Bayesian Radiocarbon‐dated Event Count |
|
503 |
#' (REC) Models for the Study of Long‐term Human and Environmental Processes. |
|
504 |
#' *Journal of Quaternary Science*, 36(1): 110‑23. \doi{10.1002/jqs.3256}. |
|
505 |
#' @author N. Frerebeau |
|
506 |
#' @family radiocarbon tools |
|
507 |
#' @docType methods |
|
508 |
#' @aliases c14_ensemble-method |
|
509 |
setGeneric( |
|
510 |
name = "c14_ensemble", |
|
511 |
def = function(object, ...) standardGeneric("c14_ensemble"), |
|
512 |
valueClass = "RECE" |
|
513 |
) |
|
514 | ||
515 |
## SPD ------------------------------------------------------------------------- |
|
516 |
#' Summed Probability Distributions |
|
517 |
#' |
|
518 |
#' Computes summed probability distributions (SPD) of radiocarbon dates. |
|
519 |
#' @param object A [`CalibratedAges-class`] object. |
|
520 |
#' @param normalize_date A [`logical`] scalar: should the total probability mass |
|
521 |
#' of the calibrated dates be normalised (to sum to unity within the time-span |
|
522 |
#' of analysis)? |
|
523 |
#' @param normalize_spd A [`logical`] scalar: should the total probability mass |
|
524 |
#' of the SPD be normalised (to sum to unity)? |
|
525 |
#' @param ... Currently not used. |
|
526 |
#' @details |
|
527 |
#' Summed probability distributions (SPD) are not statistically valid |
|
528 |
#' estimators of the calendar age of a potential future sample. They should not |
|
529 |
#' be used in any dates-as-data approach to provide a population proxy. |
|
530 |
#' @return |
|
531 |
#' A [`CalibratedSPD-class`] object. |
|
532 |
#' @example inst/examples/ex-14c-spd.R |
|
533 |
#' @author N. Frerebeau |
|
534 |
#' @docType methods |
|
535 |
#' @family radiocarbon tools |
|
536 |
#' @aliases c14_spd-method |
|
537 |
setGeneric( |
|
538 |
name = "c14_spd", |
|
539 |
def = function(object, ...) standardGeneric("c14_spd"), |
|
540 |
valueClass = "CalibratedSPD" |
|
541 |
) |
|
542 | ||
543 |
# Interval ===================================================================== |
|
544 |
## HDR ------------------------------------------------------------------------- |
|
545 |
#' Highest Density Regions |
|
546 |
#' |
|
547 |
#' @param x A [`CalibratedAges-class`] object. |
|
548 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
549 |
#' @param ... Currently not used. |
|
550 |
#' @return |
|
551 |
#' A [`CalibratedIntervals-class`] object. |
|
552 |
#' @references |
|
553 |
#' Hyndman, R. J. (1996). Computing and graphing highest density regions. |
|
554 |
#' *American Statistician*, 50: 120-126. \doi{10.2307/2684423}. |
|
555 |
#' @example inst/examples/ex-14c-hdr.R |
|
556 |
#' @seealso [stats::density()], [arkhe::interval_hdr()] |
|
557 |
#' @author N. Frerebeau |
|
558 |
#' @family statistics |
|
559 |
#' @docType methods |
|
560 |
#' @rdname interval_hdr |
|
561 |
#' @name interval_hdr |
|
562 |
NULL |
|
563 | ||
564 |
## Credible -------------------------------------------------------------------- |
|
565 |
#' Bayesian Credible Interval |
|
566 |
#' |
|
567 |
#' @param x A [`CalibratedAges-class`] object. |
|
568 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
569 |
#' @param n An [`integer`] specifying the number of random samples. |
|
570 |
#' @param ... Currently not used. |
|
571 |
#' @return |
|
572 |
#' A [`CalibratedIntervals-class`] object. |
|
573 |
#' @example inst/examples/ex-14c-credible.R |
|
574 |
#' @seealso [arkhe::interval_credible()] |
|
575 |
#' @author N. Frerebeau |
|
576 |
#' @family statistics |
|
577 |
#' @docType methods |
|
578 |
#' @rdname interval_credible |
|
579 |
#' @name interval_credible |
|
580 |
NULL |
|
581 | ||
582 |
# Proxy Records ================================================================ |
|
583 |
#' Layer-Counted Proxy Records Uncertainties |
|
584 |
#' |
|
585 |
#' Represents layer-counted proxy records as sequences of probability |
|
586 |
#' distributions on absolute, error-free time axes. |
|
587 |
#' @param positions A positive [`numeric`] vector giving the positions (e.g. |
|
588 |
#' depths) at which proxy values and calendar ages were measured. In the case |
|
589 |
#' of layers of non-zero thickness, this should be the middle value of the |
|
590 |
#' slice. It must be in decreasing order (i.e. in chronological order). |
|
591 |
#' @param proxy_values A [`numeric`] vector giving the proxy values. |
|
592 |
#' @param proxy_errors A [`numeric`] vector giving the proxy uncertainties. |
|
593 |
#' @param proxy_step A length-one [`numeric`] vector specifying the step size |
|
594 |
#' (in units of `proxy_values`) at which proxy records densities are to be |
|
595 |
#' estimated. |
|
596 |
#' @param time_values A [`numeric`] vector giving the calendar ages (in years). |
|
597 |
#' @param time_errors A [`numeric`] vector giving the calendar age uncertainties |
|
598 |
#' (in years). |
|
599 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
600 |
#' of `time` (see [aion::calendar()]). |
|
601 |
#' @param from A length-one [`numeric`] vector specifying the starting value of |
|
602 |
#' the temporal sequence at which densities are to be estimated (in years). |
|
603 |
#' @param to A length-one [`numeric`] vector specifying the end value of the |
|
604 |
#' temporal sequence at which densities are to be estimated (in cal BP years). |
|
605 |
#' @param by A length-one [`numeric`] vector specifying the increment of |
|
606 |
#' the temporal sequence at which densities are to be estimated (in years). |
|
607 |
#' @param n An [`integer`] specifying the number of item to choose randomly. |
|
608 |
#' @param verbose A [`logical`] scalar: should extra information be reported? |
|
609 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
610 |
#' @param ... Currently not used. |
|
611 |
#' @return |
|
612 |
#' A [`ProxyRecord-class`] object. |
|
613 |
#' @note |
|
614 |
#' This function is currently *experimental*. |
|
615 |
#' @references |
|
616 |
#' Boers, N., Goswami, B. & Ghil, M. (2017). A Complete Representation of |
|
617 |
#' Uncertainties in Layer-Counted Paleoclimatic Archives. *Climate of the |
|
618 |
#' Past*, 13(9): 1169-1180. \doi{10.5194/cp-13-1169-2017}. |
|
619 |
#' @example inst/examples/ex-proxy.R |
|
620 |
#' @author N. Frerebeau |
|
621 |
#' @family proxy tools |
|
622 |
#' @docType methods |
|
623 |
#' @aliases proxy_ensemble-method |
|
624 |
setGeneric( |
|
625 |
name = "proxy_ensemble", |
|
626 |
def = function(positions, ...) standardGeneric("proxy_ensemble"), |
|
627 |
valueClass = "ProxyRecord" |
|
628 |
) |
|
629 | ||
630 |
#' Plot Layer-Counted Proxy Records Uncertainties |
|
631 |
#' |
|
632 |
#' @param x A [`ProxyRecord-class`] object. |
|
633 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
634 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
635 |
#' @param iqr A [`logical`] scalar: should the mean and IQR be displayed? |
|
636 |
#' @param xlab,ylab A [`character`] string giving a label for the x and y axis. |
|
637 |
#' @param col A list of colors such as that generated by [grDevices::hcl.colors()]. |
|
638 |
#' @param col.mean,col.iqr A specification for the line colors. Only used if |
|
639 |
#' `iqr` is `TRUE`. |
|
640 |
#' @param lty.mean,lty.iqr A specification for the line types. Only used if |
|
641 |
#' `iqr` is `TRUE`. |
|
642 |
#' @param lwd.mean,lwd.iqr A specification for the line widths. Only used if |
|
643 |
#' `iqr` is `TRUE`. |
|
644 |
#' @param ... Further parameters to be passed to [graphics::image()]. |
|
645 |
#' @return |
|
646 |
#' `plot()` is called it for its side-effects: it results in a graphic |
|
647 |
#' being displayed. Invisibly returns `x`. |
|
648 |
#' @example inst/examples/ex-proxy.R |
|
649 |
#' @author N. Frerebeau |
|
650 |
#' @docType methods |
|
651 |
#' @family proxy tools |
|
652 |
#' @name proxy_plot |
|
653 |
#' @rdname proxy_plot |
|
654 |
NULL |
|
655 | ||
656 |
# Isotopes ===================================================================== |
|
657 |
#' Geological Model Age from Lead Isotope Analysis |
|
658 |
#' |
|
659 |
#' Compute geological model age (T) and U/Pb (mu) and Th/U (kappa) ratios from |
|
660 |
#' lead isotopic measurements. |
|
661 |
#' @param x A [`numeric`] vector of 206Pb/204Pb ratios. If `y` and `z` are |
|
662 |
#' missing, must be a [`list`] (or a [`data.frame`]) with `numeric` components |
|
663 |
#' (columns) `x`, `y` and `z`. |
|
664 |
#' @param y A [`numeric`] vector of 207Pb/204Pb ratios. If missing, an attempt |
|
665 |
#' is made to interpret `x` in a suitable way. |
|
666 |
#' @param z A [`numeric`] vector of 208Pb/204Pb ratios. If missing, an attempt |
|
667 |
#' is made to interpret `x` in a suitable way. |
|
668 |
#' @param t0 A [`numeric`] value giving the time of the second stage of the |
|
669 |
#' reference model. |
|
670 |
#' @param x_star A [`numeric`] value giving the 206Pb/204Pb ratio at |
|
671 |
#' \eqn{t = 0}. |
|
672 |
#' @param y_star A [`numeric`] value giving the 207Pb/204Pb ratio at |
|
673 |
#' \eqn{t = 0}. |
|
674 |
#' @param z_star A [`numeric`] value giving the 208Pb/204Pb ratio at |
|
675 |
#' \eqn{t = 0}. |
|
676 |
#' @param mu A [`numeric`] value giving the 238U/204Pb ratio of the |
|
677 |
#' reference model. |
|
678 |
#' @param kappa A [`numeric`] value giving the 232Th/238U ratio of the |
|
679 |
#' reference model. |
|
680 |
#' @param th232 A [`numeric`] value giving the decay constants of 232Th. |
|
681 |
#' @param u238 A [`numeric`] value giving the decay constants of 238U. |
|
682 |
#' @param u235 A [`numeric`] value giving the decay constants of 235U. |
|
683 |
#' @param u238_235 A [`numeric`] value giving the actual 238U/235U ratio. |
|
684 |
#' @param tolerance A [`numeric`] value specifying the tolerance (stopping |
|
685 |
#' criteria for the Newton–Raphson method). |
|
686 |
#' @param stop An [`integer`] giving the stopping rule (i.e. maximum number of |
|
687 |
#' iterations) to avoid infinite loop. |
|
688 |
#' @param ... Currently not used. |
|
689 |
#' @note |
|
690 |
#' Reference values from Albarede & Juteau (1984). |
|
691 |
#' @return |
|
692 |
#' A four columns [`data.frame`]: |
|
693 |
#' \describe{ |
|
694 |
#' \item{`age`}{Geological model age (in Ma).} |
|
695 |
#' \item{`mu`}{238U/204Pb ratio.} |
|
696 |
#' \item{`kappa`}{232Th/238U ratio.} |
|
697 |
#' \item{`residual`}{Newton loop residual.} |
|
698 |
#' } |
|
699 |
#' @references |
|
700 |
#' Albarède, F., Desaulty, A.-M. & Blichert-Toft, J. (2012). A Geological |
|
701 |
#' Perspective on the Use of Pb Isotopes in Archaeometry. *Archaeometry*, 54: |
|
702 |
#' 853-867. \doi{10.1111/j.1475-4754.2011.00653.x}. |
|
703 |
#' |
|
704 |
#' Albarède, F. & Juteau, M. (1984). Unscrambling the Lead Model Ages. |
|
705 |
#' *Geochimica et Cosmochimica Acta*, 48(1): 207-12. |
|
706 |
#' \doi{10.1016/0016-7037(84)90364-8}. |
|
707 |
#' |
|
708 |
#' Allègre, C. (2005). *Géologie isotopique*. Belin sup. Paris: Belin. |
|
709 |
#' @example inst/examples/ex-lia.R |
|
710 |
#' @author N. Frerebeau, F. Albarede (original Matlab code) |
|
711 |
#' @docType methods |
|
712 |
#' @family isotope analysis |
|
713 |
#' @export |
|
714 |
setGeneric( |
|
715 |
name = "pb_age", |
|
716 |
def = function(x, y, z, ...) standardGeneric("pb_age"), |
|
717 |
valueClass = "data.frame" |
|
718 |
) |
|
719 | ||
720 |
# Statistics =================================================================== |
|
721 |
#' Quantiles of a Density Estimate |
|
722 |
#' |
|
723 |
#' @param x A [`CalibratedAges-class`] object. |
|
724 |
#' @param probs A [`numeric`] vector of probabilities with values in |
|
725 |
#' \eqn{[0,1]}. |
|
726 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
727 |
#' computation proceeds? |
|
728 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
729 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
730 |
#' @param ... Currently not used. |
|
731 |
#' @return |
|
732 |
#' A `numeric` [`matrix`] containing the quantiles. |
|
733 |
#' @example inst/examples/ex-14c-statistics.R |
|
734 |
#' @author N. Frerebeau |
|
735 |
#' @docType methods |
|
736 |
#' @family statistics |
|
737 |
#' @name quantile |
|
738 |
#' @rdname quantile |
|
739 |
NULL |
|
740 | ||
741 |
#' Mean |
|
742 |
#' |
|
743 |
#' @param x A [`CalibratedAges-class`] object. |
|
744 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
745 |
#' computation proceeds? |
|
746 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
747 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
748 |
#' @param ... Currently not used. |
|
749 |
#' @return A [`numeric`] vector. |
|
750 |
#' @example inst/examples/ex-14c-statistics.R |
|
751 |
#' @author N. Frerebeau |
|
752 |
#' @docType methods |
|
753 |
#' @family statistics |
|
754 |
#' @name mean |
|
755 |
#' @rdname mean |
|
756 |
NULL |
|
757 | ||
758 |
#' Median |
|
759 |
#' |
|
760 |
#' @param x A [`CalibratedAges-class`] object. |
|
761 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
762 |
#' computation proceeds? |
|
763 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
764 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
765 |
#' @param ... Currently not used. |
|
766 |
#' @return A [`numeric`] vector. |
|
767 |
#' @example inst/examples/ex-14c-statistics.R |
|
768 |
#' @author N. Frerebeau |
|
769 |
#' @docType methods |
|
770 |
#' @family statistics |
|
771 |
#' @name median |
|
772 |
#' @rdname median |
|
773 |
NULL |
|
774 | ||
775 |
# Summary ====================================================================== |
|
776 |
#' Data Description |
|
777 |
#' |
|
778 |
#' @param x A [`CalibratedAges-class`] object. |
|
779 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
780 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
781 |
#' calendar (see [aion::calendar()]). |
|
782 |
#' @param ... Further parameters to be passed to [cat()]. |
|
783 |
#' @return |
|
784 |
#' `describe()` is called for its side-effects. Invisibly returns `x`. |
|
785 |
#' @references |
|
786 |
#' Millard, A. R. (2014). Conventions for Reporting Radiocarbon Determinations. |
|
787 |
#' *Radiocarbon*, 56(2): 555-559. \doi{10.2458/56.17455}. |
|
788 |
#' @example inst/examples/ex-describe.R |
|
789 |
#' @author N. Frerebeau |
|
790 |
#' @family summary |
|
791 |
#' @docType methods |
|
792 |
#' @rdname describe |
|
793 |
#' @name describe |
|
794 |
NULL |
1 |
# 14C SPD |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname c14_spd |
|
7 |
#' @aliases c14_spd,CalibratedAges-method |
|
8 |
setMethod( |
|
9 |
f = "c14_spd", |
|
10 |
signature = "CalibratedAges", |
|
11 |
definition = function(object, normalize_date = FALSE, normalize_spd = FALSE) { |
|
12 |
## Check |
|
13 | 1x |
c14_validate(object) |
14 | ||
15 | 1x |
dens <- t(object[, , 1, drop = TRUE]) |
16 | ! |
if (normalize_date) dens <- dens / rowSums(dens, na.rm = TRUE) |
17 | 1x |
spd <- colSums(dens, na.rm = TRUE) |
18 | ! |
if (normalize_spd) spd <- spd / sum(spd, na.rm = TRUE) |
19 | ||
20 | 1x |
time_series <- aion::series( |
21 | 1x |
object = spd, |
22 | 1x |
time = aion::time(object, calendar = NULL) |
23 |
) |
|
24 | 1x |
.CalibratedSPD(time_series) |
25 |
} |
|
26 |
) |
1 |
# 14C CALIBRATION CHECK |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' Check Calibrated Radiocarbon Dates |
|
6 |
#' |
|
7 |
#' @param object A [`CalibratedAges-class`] object. |
|
8 |
#' @param verbose A [`logical`] scalar: should extra information be reported? |
|
9 |
#' @return |
|
10 |
#' `c14_validate()` is called it for its side-effects: it prints |
|
11 |
#' [warning messages][warnings()] if calibrated ages are (partially) out of |
|
12 |
#' calibration range. Invisibly returns `x`. |
|
13 |
#' @example inst/examples/ex-14c-calibrate.R |
|
14 |
#' @author N. Frerebeau |
|
15 |
#' @keywords internal |
|
16 |
c14_validate <- function(object, verbose = getOption("ananke.verbose")) { |
|
17 | 9x |
status <- object@status |
18 | 9x |
lab <- labels(object) |
19 | ||
20 | 9x |
if (isTRUE(verbose)) { |
21 | 4x |
if (any(status == 1L)) { |
22 | 2x |
is_out <- which(status == 1L) |
23 | 2x |
warn <- print_out(lab[is_out], maybe = FALSE) |
24 | 2x |
for (w in warn) warning(w, call. = FALSE) |
25 |
} |
|
26 | 4x |
if (any(status == 2L)) { |
27 | 2x |
is_out <- which(status == 2L) |
28 | 2x |
warn <- print_out(lab[is_out], maybe = TRUE) |
29 | 2x |
for (w in warn) warning(w, call. = FALSE) |
30 |
} |
|
31 |
} |
|
32 | ||
33 | 9x |
invisible(object) |
34 |
} |
|
35 | ||
36 |
print_out <- function(label, maybe = FALSE) { |
|
37 | 4x |
if (maybe) { |
38 | 2x |
status <- tr_("Date %s may extent out of calibration range.") |
39 |
} else { |
|
40 | 2x |
status <- tr_("Date %s is out of calibration range.") |
41 |
} |
|
42 | 4x |
sprintf(status, dQuote(label)) |
43 |
} |
1 |
# GEOLOGICAL MODEL AGE |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname pb_age |
|
7 |
#' @aliases pb_age,numeric,numeric,numeric-method |
|
8 |
setMethod( |
|
9 |
f = "pb_age", |
|
10 |
signature = c(x = "numeric", y = "numeric", z = "numeric"), |
|
11 |
definition = function(x, y, z, t0 = 3.8, |
|
12 |
x_star = 18.75, y_star = 15.63, z_star = 38.86, |
|
13 |
mu = 9.66, kappa = 3.90, th232 = 0.049475, |
|
14 |
u238 = 0.155125, u235 = 0.98485, u238_235 = 137.79, |
|
15 |
tolerance = sqrt(.Machine$double.eps), |
|
16 |
stop = 100) { |
|
17 |
## Validation |
|
18 | 2x |
n <- length(x) |
19 | 2x |
arkhe::assert_length(y, n) |
20 | 2x |
arkhe::assert_length(z, n) |
21 | ||
22 | 2x |
x0 <- x_star - mu * (exp(u238 * t0) - 1) # 206Pb/204Pb at t0 |
23 | 2x |
y0 <- y_star - mu / u238_235 * (exp(u235 * t0) - 1) # 207Pb/204Pb at t0 |
24 | 2x |
z0 <- z_star - mu * kappa * (exp(th232 * t0) - 1) # 208Pb/204Pb at t0 |
25 | ||
26 | 2x |
t_model <- vector(mode = "numeric", length = n) |
27 | 2x |
f_x <- vector(mode = "numeric", length = n) |
28 | 2x |
for (i in seq_along(t_model)) { |
29 | 6x |
tt <- 0 |
30 | 6x |
f <- 1 |
31 | ||
32 | 6x |
iter <- 0 |
33 | 6x |
while (abs(f) > tolerance) { # Newton loop |
34 | 30x |
slope <- (y[i] - y0) / (x[i] - x0) |
35 | 30x |
u <- exp(u235 * t0) - exp(u235 * tt) |
36 | 30x |
v <- exp(u238 * t0) - exp(u238 * tt) |
37 | 30x |
uprime <- -u235 * exp(u235 * tt) |
38 | 30x |
vprime <- -u238 * exp(u238 * tt) |
39 | ||
40 | 30x |
f <- u / v - slope * u238_235 |
41 | 30x |
df <- (1 / v) * (uprime - u / v * vprime) # df/dtt |
42 | 30x |
dtt <- f / df # Newton-Raphson increment |
43 | 30x |
tt <- tt - dtt |
44 | ||
45 |
# Loop counter |
|
46 | 30x |
iter <- iter + 1 |
47 | 30x |
if (iter >= stop) { |
48 | ! |
msg <- tr_("Convergence not reached (possible infinite loop).") |
49 | ! |
warning(msg, call. = FALSE) |
50 | ! |
break |
51 |
} |
|
52 |
} |
|
53 | ||
54 | 6x |
t_model[i] <- tt |
55 | 6x |
f_x[i] <- f # Residual (should be zero) |
56 |
} |
|
57 | ||
58 | 2x |
mu_i <- (x - x0) / (exp(u238 * t0) - exp(u238 * t_model)) |
59 | 2x |
kappa_i <- (z - z0) / (exp(th232 * t0) - exp(th232 * t_model)) / mu_i |
60 | ||
61 | 2x |
data.frame( |
62 | 2x |
age = t_model * 1000, # Use Ma instead of Ga |
63 | 2x |
mu = mu_i, |
64 | 2x |
kappa = kappa_i, |
65 | 2x |
residual = f_x |
66 |
) |
|
67 |
} |
|
68 |
) |
|
69 | ||
70 |
#' @export |
|
71 |
#' @rdname pb_age |
|
72 |
#' @aliases pb_age,list,missing,missing-method |
|
73 |
setMethod( |
|
74 |
f = "pb_age", |
|
75 |
signature = c(x = "list", y = "missing", z = "missing"), |
|
76 |
definition = function(x, t0 = 3.8, |
|
77 |
x_star = 18.75, y_star = 15.63, z_star = 38.86, |
|
78 |
mu = 9.66, kappa = 3.90, th232 = 0.049475, |
|
79 |
u238 = 0.155125, u235 = 0.98485, u238_235 = 137.79, |
|
80 |
tolerance = sqrt(.Machine$double.eps), stop = 100) { |
|
81 |
## Validation |
|
82 | 3x |
x <- grDevices::xyz.coords(x) |
83 | 2x |
methods::callGeneric(x = x$x, y = x$y, z = x$z, t0 = t0, |
84 | 2x |
x_star = x_star, y_star = y_star, z_star = z_star, |
85 | 2x |
mu = mu, kappa = kappa, th232 = th232, |
86 | 2x |
u238 = u238, u235 = u235, u238_235 = u238_235, |
87 | 2x |
tolerance = tolerance, stop = stop) |
88 |
} |
|
89 |
) |
1 |
# STATISTICS |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Quantile ===================================================================== |
|
6 |
#' Quantiles of a Density Estimate |
|
7 |
#' |
|
8 |
#' @param x A [`numeric`] vector giving the n coordinates of the points where |
|
9 |
#' the density is estimated. |
|
10 |
#' @param y A `numeric` [`matrix`] of density estimates (each column is a |
|
11 |
#' density estimate). |
|
12 |
#' @param probs A [`numeric`] vector of probabilities with values in |
|
13 |
#' \eqn{[0,1]}. |
|
14 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
15 |
#' computation proceeds? |
|
16 |
#' @param ... Currently not used. |
|
17 |
#' @return |
|
18 |
#' A `numeric` [`matrix`] containing the quantiles. |
|
19 |
#' @keywords internal |
|
20 |
#' @noRd |
|
21 |
quantile_density <- function(x, y, probs = seq(0, 1, 0.25), na.rm = FALSE, ...) { |
|
22 | 2x |
eps <- 100 * .Machine$double.eps |
23 | 2x |
if (anyNA(probs) | any(probs < -eps | probs > 1 + eps)) |
24 | ! |
stop(sprintf("%s outside [0,1]", sQuote("probs"))) |
25 | ||
26 | 2x |
q <- apply( |
27 | 2x |
X = y, |
28 | 2x |
MARGIN = 2, |
29 | 2x |
FUN = function(y, x, probs, na.rm) { |
30 | 4x |
np <- length(probs) |
31 | 4x |
qs <- rep(NA_real_, np) |
32 | 4x |
if (na.rm) { |
33 | ! |
i <- !is.na(x) & !is.na(y) |
34 | ! |
x <- x[i] |
35 | ! |
y <- y[i] |
36 |
} |
|
37 | 4x |
if (np > 0) { |
38 | 4x |
nn <- length(x) |
39 | 4x |
Fx <- cumsum(y * c(0, diff(x))) |
40 | 4x |
Fx <- Fx / Fx[nn] |
41 | 4x |
for (j in seq_len(np)) { |
42 | 12x |
ii <- min(which(Fx >= probs[j])) |
43 | 12x |
if (!is.na(ii) && ii >= 1 && ii <= nn) qs[j] <- x[ii] |
44 |
} |
|
45 | 4x |
qs |
46 |
} |
|
47 |
}, |
|
48 | 2x |
x = x, |
49 | 2x |
probs = probs, |
50 | 2x |
na.rm = na.rm |
51 |
) |
|
52 | ||
53 | 2x |
if (!is.null(dim(q))) { |
54 | 1x |
q <- t(q) |
55 | 1x |
colnames(q) <- paste0(round(probs * 100, digits = 0), "%") |
56 |
} |
|
57 | 2x |
q |
58 |
} |
|
59 | ||
60 |
#' @export |
|
61 |
#' @method quantile CalibratedAges |
|
62 |
quantile.CalibratedAges <- function(x, probs = seq(0, 1, 0.25), na.rm = FALSE, |
|
63 |
..., calendar = get_calendar()) { |
|
64 | 1x |
quantile_density(x = aion::time(x, calendar = calendar), y = x, |
65 | 1x |
probs = probs, na.rm = na.rm, ...) |
66 |
} |
|
67 | ||
68 |
#' @export |
|
69 |
#' @rdname quantile |
|
70 |
#' @aliases quantile,CalibratedAges,missing-method |
|
71 |
setMethod("quantile", c(x = "CalibratedAges"), quantile.CalibratedAges) |
|
72 | ||
73 |
#' @export |
|
74 |
#' @method quantile ProxyRecord |
|
75 |
quantile.ProxyRecord <- function(x, probs = seq(0, 1, 0.25), na.rm = FALSE, ...) { |
|
76 | ! |
quantile_density(x = x@proxy, y = t(x@density), |
77 | ! |
probs = probs, na.rm = na.rm, ...) |
78 |
} |
|
79 | ||
80 |
#' @export |
|
81 |
#' @rdname quantile |
|
82 |
#' @aliases quantile,ProxyRecord,missing-method |
|
83 |
setMethod("quantile", c(x = "ProxyRecord"), quantile.ProxyRecord) |
|
84 | ||
85 |
# Median ======================================================================= |
|
86 |
#' @export |
|
87 |
#' @method median CalibratedAges |
|
88 |
median.CalibratedAges <- function(x, na.rm = FALSE, ..., |
|
89 |
calendar = get_calendar()) { |
|
90 | 1x |
quantile_density(x = aion::time(x, calendar = calendar), y = x, |
91 | 1x |
probs = 0.5, na.rm = na.rm, ...) |
92 |
} |
|
93 | ||
94 |
#' @export |
|
95 |
#' @rdname median |
|
96 |
#' @aliases median,CalibratedAges,missing-method |
|
97 |
setMethod("median", c(x = "CalibratedAges"), median.CalibratedAges) |
|
98 | ||
99 |
# Mean ========================================================================= |
|
100 |
#' Mean of a Density Estimate |
|
101 |
#' |
|
102 |
#' @param x A [`numeric`] vector giving the n coordinates of the points where |
|
103 |
#' the density is estimated. |
|
104 |
#' @param y A `numeric` [`matrix`] of density estimates (each column is a |
|
105 |
#' density estimate). |
|
106 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
107 |
#' computation proceeds? |
|
108 |
#' @param ... Currently not used. |
|
109 |
#' @return A [`numeric`] vector. |
|
110 |
#' @keywords internal |
|
111 |
#' @noRd |
|
112 |
mean_density <- function(x, y, na.rm = FALSE, ...) { |
|
113 | 1x |
apply( |
114 | 1x |
X = y, |
115 | 1x |
MARGIN = 2, |
116 | 1x |
FUN = function(w, x, na.rm) { |
117 | 2x |
if (na.rm) { |
118 | ! |
i <- !is.na(w) & !is.na(x) |
119 | ! |
x <- x[i] |
120 | ! |
w <- w[i] |
121 |
} |
|
122 | 2x |
stats::weighted.mean(x = x, w = w) |
123 |
}, |
|
124 | 1x |
x = x, |
125 | 1x |
na.rm = na.rm |
126 |
) |
|
127 |
} |
|
128 | ||
129 |
#' @export |
|
130 |
#' @method mean CalibratedAges |
|
131 |
mean.CalibratedAges <- function(x, na.rm = FALSE, ..., |
|
132 |
calendar = get_calendar()) { |
|
133 | 1x |
mean_density(x = aion::time(x, calendar = calendar), y = x, |
134 | 1x |
calendar = calendar) |
135 |
} |
|
136 | ||
137 |
#' @export |
|
138 |
#' @rdname mean |
|
139 |
#' @aliases mean,CalibratedAges,missing-method |
|
140 |
setMethod("mean", c(x = "CalibratedAges"), mean.CalibratedAges) |
|
141 | ||
142 |
#' @export |
|
143 |
#' @method mean ProxyRecord |
|
144 |
mean.ProxyRecord <- function(x, na.rm = FALSE, ...) { |
|
145 | ! |
mean_density(x = x@proxy, y = t(x@density), na.rm = na.rm, ...) |
146 |
} |
|
147 | ||
148 |
#' @export |
|
149 |
#' @rdname mean |
|
150 |
#' @aliases mean,ProxyRecord,missing-method |
|
151 |
setMethod("mean", c(x = "ProxyRecord"), mean.ProxyRecord) |
1 |
# INTERVAL ESTIMATION |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# HDR ========================================================================== |
|
6 |
#' @export |
|
7 |
#' @rdname interval_hdr |
|
8 |
#' @aliases interval_hdr,CalibratedAges,missing-method |
|
9 |
setMethod( |
|
10 |
f = "interval_hdr", |
|
11 |
signature = c(x = "CalibratedAges", y = "missing"), |
|
12 |
definition = function(x, level = 0.954, ...) { |
|
13 |
## Check |
|
14 | 4x |
c14_validate(x) |
15 | ||
16 | 4x |
hdr <- apply( |
17 | 4x |
X = x, |
18 | 4x |
MARGIN = 2, |
19 | 4x |
FUN = function(y, x, level, ...) { |
20 | ! |
if (all(is.na(y))) return(NULL) |
21 | 5x |
arkhe::interval_hdr(x, as.numeric(y), level, ...) |
22 |
}, |
|
23 | 4x |
x = aion::time(x, calendar = NULL), |
24 | 4x |
level = level, |
25 | 4x |
simplify = FALSE |
26 |
) |
|
27 | 4x |
n <- vapply(X = hdr, FUN = nrow, FUN.VALUE = integer(1)) |
28 | 4x |
lab <- rep(labels(x), n) |
29 | ||
30 | 4x |
hdr <- do.call(rbind, hdr) |
31 | 4x |
.CalibratedIntervals( |
32 | 4x |
.Id = lab, |
33 | 4x |
.Start = aion::as_fixed(hdr[, 1]), |
34 | 4x |
.End = aion::as_fixed(hdr[, 2]), |
35 | 4x |
p = unname(hdr[, 3]) |
36 |
) |
|
37 |
} |
|
38 |
) |
|
39 | ||
40 |
# Credible ===================================================================== |
|
41 |
#' @export |
|
42 |
#' @rdname interval_credible |
|
43 |
#' @aliases interval_credible,CalibratedAges,missing-method |
|
44 |
setMethod( |
|
45 |
f = "interval_credible", |
|
46 |
signature = c(x = "CalibratedAges"), |
|
47 |
definition = function(x, level = 0.954, n = 100, ...) { |
|
48 |
## Check |
|
49 | ! |
c14_validate(x) |
50 | ||
51 | ! |
spl <- c14_sample(x, n = n, calendar = NULL) |
52 | ! |
crd <- apply( |
53 | ! |
X = spl, |
54 | ! |
MARGIN = 2, |
55 | ! |
FUN = interval_credible, |
56 | ! |
level = level, |
57 | ! |
simplify = FALSE |
58 |
) |
|
59 | ||
60 | ! |
crd <- do.call(rbind, crd) |
61 | ! |
.CalibratedIntervals( |
62 | ! |
.Id = labels(x), |
63 | ! |
.Start = aion::as_fixed(crd[, 1]), |
64 | ! |
.End = aion::as_fixed(crd[, 2]), |
65 | ! |
p = unname(crd[, 3]) |
66 |
) |
|
67 |
} |
|
68 |
) |
1 |
# MUTATORS |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Get ========================================================================== |
|
6 |
#' @export |
|
7 |
#' @method labels CalibratedAges |
|
8 |
labels.CalibratedAges <- function(object, ...) { |
|
9 | 14x |
colnames(object) %||% paste0("X", NCOL(object)) |
10 |
} |
|
11 | ||
12 |
#' @export |
|
13 |
#' @rdname labels |
|
14 |
#' @aliases labels,CalibratedAges-method |
|
15 |
setMethod("labels", "CalibratedAges", labels.CalibratedAges) |
1 |
# SAMPLE 14C |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname c14_sample |
|
7 |
#' @aliases c14_sample,CalibratedAges-method |
|
8 |
setMethod( |
|
9 |
f = "c14_sample", |
|
10 |
signature = "CalibratedAges", |
|
11 |
definition = function(object, n = 100, calendar = get_calendar()) { |
|
12 | 1x |
apply( |
13 | 1x |
X = object, |
14 | 1x |
MARGIN = 2, |
15 | 1x |
FUN = function(prob, size, x) { |
16 | 2x |
sample(x, size = size, replace = TRUE, prob = prob) |
17 |
}, |
|
18 | 1x |
x = aion::time(object, calendar = calendar), |
19 | 1x |
size = n |
20 |
) |
|
21 |
} |
|
22 |
) |
1 |
# HELPERS |
|
2 | ||
3 |
## https://michaelchirico.github.io/potools/articles/developers.html |
|
4 |
tr_ <- function(...) { |
|
5 | 4x |
enc2utf8(gettext(paste0(...), domain = "R-ananke")) |
6 |
} |
|
7 | ||
8 |
#' Plotting Dimensions of Character Strings |
|
9 |
#' |
|
10 |
#' Convert string length in inch to number of (margin) lines. |
|
11 |
#' @param x A [`character`] vector of string whose length is to be calculated. |
|
12 |
#' @param ... Further parameter to be passed to [graphics::strwidth()]`, such as |
|
13 |
#' `cex`. |
|
14 |
#' @return |
|
15 |
#' A [`numeric`] vector (maximum string width in units of margin lines). |
|
16 |
#' @note For internal use only. |
|
17 |
#' @family graphic tools |
|
18 |
#' @keywords internal |
|
19 |
#' @noRd |
|
20 |
inch2line <- function(x, ...) { |
|
21 | ! |
(max(graphics::strwidth(x, units = "inch", ...)) / |
22 | ! |
graphics::par("cin")[2] + graphics::par("mgp")[2]) * graphics::par("cex") |
23 |
} |