1 |
# PLOT |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Plot ========================================================================= |
|
6 |
#' @export |
|
7 |
#' @method plot TimeIntervals |
|
8 |
plot.TimeIntervals <- function(x, calendar = get_calendar(), groups = NULL, |
|
9 |
sort = TRUE, decreasing = FALSE, |
|
10 |
xlab = NULL, ylab = NULL, |
|
11 |
main = NULL, sub = NULL, |
|
12 |
ann = graphics::par("ann"), axes = TRUE, |
|
13 |
frame.plot = axes, |
|
14 |
panel.first = NULL, panel.last = NULL, ...) { |
|
15 |
## Save calendar for further use, e.g. year_axis() |
|
16 | 4x |
assign("last_calendar", value = function(...) calendar, envir = the) |
17 | ||
18 |
## Get data |
|
19 | 4x |
lab <- labels(x) |
20 | 4x |
int <- as.data.frame(x, calendar = calendar) |
21 | 4x |
k <- nrow(int) |
22 | 4x |
if (is.null(groups)) groups <- rep("", k) |
23 | 4x |
arkhe::assert_length(groups, k) |
24 | ||
25 |
## Graphical parameters |
|
26 | 4x |
dots <- list(...) |
27 | 4x |
col <- make_par(dots, "col", k) |
28 | 4x |
lwd <- make_par(dots, "lwd", k) |
29 | 4x |
lty <- make_par(dots, "lty", k) |
30 | ||
31 |
## Sort and split |
|
32 | 4x |
if (sort) { |
33 | 4x |
i <- order(groups, start(x), end(x), decreasing = decreasing) |
34 |
} else { |
|
35 | ! |
i <- order(groups, decreasing = decreasing) |
36 |
} |
|
37 | 4x |
int <- int[i, , drop = FALSE] |
38 | 4x |
lab <- lab[i] |
39 | 4x |
f <- factor(x = lab, levels = unique(lab), ordered = TRUE) |
40 | 4x |
int <- split(x = int, f = f) |
41 | 4x |
col <- split(x = col[i], f = f) |
42 | 4x |
lwd <- split(x = lwd[i], f = f) |
43 | 4x |
lty <- split(x = lty[i], f = f) |
44 | 4x |
n <- length(int) |
45 | ||
46 |
## Open new window |
|
47 | 4x |
grDevices::dev.hold() |
48 | 4x |
on.exit(grDevices::dev.flush(), add = TRUE) |
49 | 4x |
graphics::plot.new() |
50 | ||
51 |
## Set plotting coordinates |
|
52 | 4x |
xlim <- xlim(x, calendar = calendar, finite = TRUE) |
53 | 4x |
ylim <- c(1, n) |
54 | 4x |
graphics::plot.window(xlim = xlim, ylim = ylim) |
55 | ||
56 |
## Evaluate pre-plot expressions |
|
57 | 4x |
panel.first |
58 | ||
59 |
## Plot |
|
60 | 4x |
for (i in seq_len(n)) { |
61 | 48x |
x0 <- int[[i]]$start |
62 | 48x |
x1 <- int[[i]]$end |
63 | ||
64 |
## Fix infinite boundaries |
|
65 | 48x |
x0[is.infinite(x0)] <- graphics::par("usr")[[1L]] |
66 | 48x |
x1[is.infinite(x1)] <- graphics::par("usr")[[2L]] |
67 | ||
68 |
## Draw segments |
|
69 | 48x |
graphics::segments(x0 = x0, x1 = x1, y0 = i, y1 = i, |
70 | 48x |
col = col[[i]], lty = lty[[i]], lwd = lwd[[i]], lend = 1) |
71 |
} |
|
72 | ||
73 |
## Evaluate post-plot and pre-axis expressions |
|
74 | 4x |
panel.last |
75 | ||
76 |
## Construct Axis |
|
77 | 4x |
if (axes) { |
78 | 4x |
year_axis(side = 1, format = TRUE, calendar = calendar) |
79 | 4x |
graphics::axis(side = 2, at = seq_len(n), labels = names(int), |
80 | 4x |
lty = 0, las = 1) |
81 |
} |
|
82 | ||
83 |
## Plot frame |
|
84 | 4x |
if (frame.plot) { |
85 | 4x |
graphics::box() |
86 |
} |
|
87 | ||
88 |
## Add annotation |
|
89 | 4x |
if (ann) { |
90 | 4x |
if (is.null(calendar)) { |
91 | 1x |
cal_lab <- expression(italic("rata die")) |
92 |
} else { |
|
93 | 3x |
cal_lab <- format(calendar) |
94 |
} |
|
95 | 4x |
xlab <- xlab %||% cal_lab |
96 | 4x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab) |
97 |
} |
|
98 | ||
99 | 4x |
invisible(x) |
100 |
} |
|
101 | ||
102 |
#' @export |
|
103 |
#' @rdname plot |
|
104 |
#' @aliases plot,TimeIntervals,missing-method |
|
105 |
setMethod("plot", c(x = "TimeIntervals", y = "missing"), plot.TimeIntervals) |
|
106 | ||
107 |
#' @export |
|
108 |
#' @method plot TimeSeries |
|
109 |
plot.TimeSeries <- function(x, facet = c("multiple", "single"), |
|
110 |
calendar = get_calendar(), |
|
111 |
panel = graphics::lines, flip = FALSE, ncol = NULL, |
|
112 |
xlab = NULL, ylab = NULL, |
|
113 |
main = NULL, sub = NULL, |
|
114 |
ann = graphics::par("ann"), axes = TRUE, |
|
115 |
frame.plot = axes, |
|
116 |
panel.first = NULL, panel.last = NULL, ...) { |
|
117 |
## Validation |
|
118 | 9x |
facet <- match.arg(facet, several.ok = FALSE) |
119 | ||
120 |
## Save calendar for further use, e.g. year_axis() |
|
121 | 9x |
assign("last_calendar", value = function(...) calendar, envir = the) |
122 | ||
123 | 9x |
n <- dim(x)[2L] |
124 | ||
125 | 9x |
if (facet == "multiple" && n > 1) { |
126 | 5x |
.plot_multiple(x, calendar = calendar, panel = panel, y_flip = flip, |
127 | 5x |
n_col = ncol, xlab = xlab, ylab = ylab, |
128 | 5x |
main = main, sub = sub, ann = ann, axes = axes, |
129 | 5x |
frame.plot = frame.plot, panel.first = panel.first, |
130 | 5x |
panel.last = panel.last, ...) |
131 |
} else { |
|
132 | 4x |
.plot_single(x, calendar = calendar, panel = panel, |
133 | 4x |
xlab = xlab, ylab = ylab, |
134 | 4x |
main = main, sub = sub, |
135 | 4x |
ann = ann, axes = axes, |
136 | 4x |
frame.plot = frame.plot, panel.first = panel.first, |
137 | 4x |
panel.last = panel.last, ...) |
138 |
} |
|
139 | ||
140 | 9x |
invisible(x) |
141 |
} |
|
142 | ||
143 |
#' @export |
|
144 |
#' @rdname plot |
|
145 |
#' @aliases plot,TimeSeries,missing-method |
|
146 |
setMethod("plot", c(x = "TimeSeries", y = "missing"), plot.TimeSeries) |
|
147 | ||
148 |
#' Single Panel Plot |
|
149 |
#' |
|
150 |
#' @param x A [`TimeSeries-class`] object. |
|
151 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
152 |
#' (see [calendar()]). |
|
153 |
#' @param panel A [`function`] in the form `function(x, y, ...)` |
|
154 |
#' which gives the action to be carried out in each panel of the display. |
|
155 |
#' The default is [graphics::lines()]. |
|
156 |
#' @param xlim,ylim A length-two [`numeric`] vector specifying the the x and y |
|
157 |
#' limits. |
|
158 |
#' @param main A [`character`] string giving a main title for the plot. |
|
159 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
160 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
161 |
#' and y axis labels) appear on the plot? |
|
162 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
163 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
164 |
#' plot? |
|
165 |
#' @param panel.first An an `expression` to be evaluated after the plot axes are |
|
166 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
167 |
#' background grids. |
|
168 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
169 |
#' place but before the axes, title and box are added. |
|
170 |
#' @param ... Further parameters to be passed to `panel` |
|
171 |
#' (e.g. [graphical parameters][graphics::par]). |
|
172 |
#' @return |
|
173 |
#' Called for its side-effects: it results in a graphic being displayed. |
|
174 |
#' Invisibly returns `x`. |
|
175 |
#' @keywords internal |
|
176 |
#' @noRd |
|
177 |
.plot_single <- function(x, calendar, panel = graphics::lines, |
|
178 |
xlab = NULL, ylab = NULL, |
|
179 |
xlim = NULL, ylim = NULL, |
|
180 |
main = NULL, sub = NULL, |
|
181 |
ann = graphics::par("ann"), axes = TRUE, |
|
182 |
frame.plot = axes, |
|
183 |
panel.first = NULL, panel.last = NULL, ...) { |
|
184 | 34x |
n_series <- dim(x)[2L] |
185 | 34x |
n_dim <- dim(x)[3L] |
186 | ||
187 |
## Graphical parameters |
|
188 | 34x |
dots <- list(...) |
189 | 34x |
col <- make_par(dots, "col", n = n_dim) |
190 | 34x |
bg <- make_par(dots, "bg", n = n_dim) |
191 | 34x |
pch <- make_par(dots, "pch", n = n_dim) |
192 | 34x |
cex <- make_par(dots, "cex", n = n_dim) |
193 | 34x |
lwd <- make_par(dots, "lwd", n = n_dim) |
194 | 34x |
lty <- make_par(dots, "lty", n = n_dim) |
195 | ||
196 |
## Open new window |
|
197 | 34x |
grDevices::dev.hold() |
198 | 34x |
on.exit(grDevices::dev.flush(), add = TRUE) |
199 | 34x |
graphics::plot.new() |
200 | ||
201 |
## Set plotting coordinates |
|
202 | 34x |
years <- time(x, calendar = calendar) |
203 | 34x |
xlim <- xlim %||% xlim(x, calendar = calendar) |
204 | 34x |
ylim <- ylim %||% range(x, na.rm = TRUE) |
205 | 34x |
graphics::plot.window(xlim = xlim, ylim = ylim) |
206 | ||
207 |
## Evaluate pre-plot expressions |
|
208 | 34x |
panel.first |
209 | ||
210 |
## Plot |
|
211 | 34x |
for (j in seq_len(n_series)) { |
212 | 39x |
for (k in seq_len(n_dim)) { |
213 | 39x |
params <- list(col = col[k], bg = bg[k], pch = pch[k], |
214 | 39x |
cex = cex[k], lwd = lwd[k], lty = lty[k]) |
215 | 39x |
dots <- utils::modifyList(dots, params) |
216 | 39x |
args <- c(list(x = years, y = x[, j = j, k = k, drop = TRUE]), dots) |
217 | 39x |
do.call(panel, args) |
218 |
} |
|
219 |
} |
|
220 | ||
221 |
## Evaluate post-plot and pre-axis expressions |
|
222 | 34x |
panel.last |
223 | ||
224 |
## Construct Axis |
|
225 | 34x |
if (axes) { |
226 | 1x |
year_axis(side = 1, format = TRUE, calendar = calendar) |
227 | 1x |
graphics::axis(side = 2, las = 1) |
228 |
} |
|
229 | ||
230 |
## Plot frame |
|
231 | 34x |
if (frame.plot) { |
232 | 31x |
graphics::box() |
233 |
} |
|
234 | ||
235 |
## Add annotation |
|
236 | 34x |
if (ann) { |
237 | 4x |
if (is.null(calendar)) { |
238 | ! |
cal_lab <- expression(italic("rata die")) |
239 |
} else { |
|
240 | 4x |
cal_lab <- format(calendar) |
241 |
} |
|
242 | 4x |
xlab <- xlab %||% cal_lab |
243 | 4x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab) |
244 |
} |
|
245 | ||
246 | 34x |
invisible(x) |
247 |
} |
|
248 | ||
249 |
#' Multiple Panels Plot |
|
250 |
#' |
|
251 |
#' @param x A [`TimeSeries-class`] object. |
|
252 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
253 |
#' (see [calendar()]). |
|
254 |
#' @param panel A [`function`] in the form `function(x, y, ...)` |
|
255 |
#' which gives the action to be carried out in each panel of the display. |
|
256 |
#' The default is [graphics::lines()]. |
|
257 |
#' @param y_flip A [`logical`] scalar: should the y-axis (ticks and numbering) |
|
258 |
#' be flipped from side 2 (left) to 4 (right) from series to series? |
|
259 |
#' @param y_fixed A [`logical`] scalar: should the y-scale be shared across |
|
260 |
#' all series? |
|
261 |
#' @param ncol An [`integer`] specifying the number of columns to use. |
|
262 |
#' Defaults to 1 for up to 4 series, otherwise to 2. |
|
263 |
#' @param main A [`character`] string giving a main title for the plot. |
|
264 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
265 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
266 |
#' and y axis labels) appear on the plot? |
|
267 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
268 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
269 |
#' plot? |
|
270 |
#' @param panel.first An an `expression` to be evaluated after the plot axes are |
|
271 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
272 |
#' background grids. |
|
273 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
274 |
#' place but before the axes, title and box are added. |
|
275 |
#' @param ... Further parameters to be passed to `panel` |
|
276 |
#' (e.g. [graphical parameters][graphics::par]). |
|
277 |
#' @return |
|
278 |
#' Called for its side-effects: it results in a graphic being displayed. |
|
279 |
#' Invisibly returns `x`. |
|
280 |
#' @keywords internal |
|
281 |
#' @noRd |
|
282 |
.plot_multiple <- function(x, calendar, panel = graphics::lines, |
|
283 |
y_flip = TRUE, y_fixed = FALSE, n_col = NULL, |
|
284 |
xlab = NULL, ylab = NULL, |
|
285 |
main = NULL, sub = NULL, |
|
286 |
ann = graphics::par("ann"), axes = TRUE, |
|
287 |
frame.plot = axes, |
|
288 |
panel.first = NULL, panel.last = NULL, ...) { |
|
289 | ||
290 | 5x |
panel <- match.fun(panel) |
291 | 5x |
n <- dim(x)[2L] |
292 | 5x |
m <- dim(x)[3L] |
293 | 5x |
n_seq <- seq_len(n) |
294 | 5x |
m_seq <- seq_len(m) |
295 | 4x |
if (is.null(n_col)) n_col <- if (n > 4) 2 else 1 |
296 | 5x |
n_row <- ceiling(n / n_col) |
297 | ||
298 |
## Graphical parameters |
|
299 |
## Save and restore |
|
300 | 5x |
old_par <- graphics::par( |
301 | 5x |
mar = c(0, 5.1, 0, if (y_flip) 5.1 else 2.1), |
302 | 5x |
oma = c(6, 0, 5, 0), |
303 | 5x |
mfcol = c(n_row, n_col) |
304 |
) |
|
305 | 5x |
on.exit(graphics::par(old_par)) |
306 | ||
307 | 5x |
dots <- list(...) |
308 | 5x |
cex.lab <- make_par(dots, "cex.lab") |
309 | 5x |
col.lab <- make_par(dots, "col.lab") |
310 | 5x |
font.lab <- make_par(dots, "font.lab") |
311 | 5x |
cex.axis <- make_par(dots, "cex.axis") |
312 | 5x |
col.axis <- make_par(dots, "col.axis") |
313 | 5x |
font.axis <- make_par(dots, "font.axis") |
314 | 5x |
cex.main <- make_par(dots, "cex.main") |
315 | 5x |
font.main <- make_par(dots, "font.main") |
316 | 5x |
col.main <- make_par(dots, "col.main") |
317 | ||
318 | 5x |
years <- time(x, calendar = calendar) |
319 | 5x |
xlim <- xlim(x, calendar = calendar) |
320 | 5x |
ylim <- if (y_fixed) range(x, na.rm = TRUE) else NULL |
321 | 5x |
ylabs <- ylab %||% labels(x) %||% paste("Series", n_seq, sep = " ") |
322 | 5x |
for (j in n_seq) { |
323 |
## Plot |
|
324 | 30x |
xj <- x[, j, , drop = FALSE] |
325 | 30x |
.plot_single(xj, calendar = calendar, panel = panel, |
326 | 30x |
xlim = xlim, ylim = ylim, |
327 | 30x |
main = NULL, sub = NULL, ann = FALSE, axes = FALSE, |
328 | 30x |
frame.plot = frame.plot, |
329 | 30x |
panel.first = panel.first, panel.last = panel.last, ...) |
330 | ||
331 |
## Construct Axis |
|
332 | 30x |
xaxt <- make_par(dots, "xaxt") |
333 | 30x |
yaxt <- make_par(dots, "yaxt") |
334 | 30x |
do_x <- (j %% n_row == 0 || j == n) |
335 | 30x |
y_side <- if (j %% 2 || !y_flip) 2 else 4 |
336 | 30x |
if (axes) { |
337 | 30x |
if (do_x && xaxt != "n") { |
338 | 9x |
year_axis(side = 1, format = TRUE, calendar = calendar, |
339 | 9x |
xpd = NA, cex.axis = cex.axis, |
340 | 9x |
col.axis = col.axis, font.axis = font.axis) |
341 |
} |
|
342 | 30x |
if (yaxt != "n") { |
343 | 30x |
graphics::axis(side = y_side, xpd = NA, cex.axis = cex.axis, |
344 | 30x |
col.axis = col.axis, font.axis = font.axis, las = 1) |
345 |
} |
|
346 |
} |
|
347 | ||
348 |
## Add annotation |
|
349 | 30x |
if (ann) { |
350 | 30x |
if (do_x) { |
351 | 9x |
cal_lab <- if (is.null(calendar)) expression(italic("rata die")) else format(calendar) |
352 | 9x |
xlab <- xlab %||% cal_lab |
353 | 9x |
graphics::mtext(xlab, side = 1, line = 3, cex = cex.lab, col = col.lab, |
354 | 9x |
font = font.lab) |
355 |
} |
|
356 | 30x |
graphics::mtext(ylabs[[j]], side = y_side, line = 3, cex = cex.lab, |
357 | 30x |
col = col.lab, font = font.lab) |
358 |
} |
|
359 |
} |
|
360 | ||
361 |
## Add annotation |
|
362 | 5x |
if (ann) { |
363 | 5x |
graphics::par(mfcol = c(1, 1)) |
364 | 5x |
graphics::mtext(main, side = 3, line = 3, cex = cex.main, font = font.main, |
365 | 5x |
col = col.main) |
366 |
} |
|
367 | ||
368 | 5x |
invisible(x) |
369 |
} |
|
370 | ||
371 |
#' Compute x Limits |
|
372 |
#' |
|
373 |
#' Computes x limits for a time series according to a given calendar. |
|
374 |
#' This ensures that the x axis is always in chronological order. |
|
375 |
#' @param x A [`TimeSeries-class`] object. |
|
376 |
#' @param calendar A [`TimeScale-class`] object. |
|
377 |
#' @param finite A [`logical`] scalar: should non-finite elements be omitted? |
|
378 |
#' @return A length-two [`numeric`] vector. |
|
379 |
#' @keywords internal |
|
380 |
#' @noRd |
|
381 |
xlim <- function(x, calendar, finite = FALSE) { |
|
382 | 9x |
if (methods::is(x, "TimeSeries")) x <- time(x, calendar = NULL) |
383 | 4x |
if (methods::is(x, "TimeIntervals")) x <- c(start(x, calendar = NULL), end(x, calendar = NULL)) |
384 | 13x |
x <- range(x, finite = finite) |
385 | 2x |
if (is.null(calendar)) return(x) |
386 | 11x |
as_year(x, calendar = calendar) |
387 |
} |
|
388 | ||
389 |
# Image ======================================================================== |
|
390 |
#' @export |
|
391 |
#' @method image TimeSeries |
|
392 |
image.TimeSeries <- function(x, calendar = get_calendar(), k = 1, ...) { |
|
393 |
## Save calendar for further use, e.g. year_axis() |
|
394 | 1x |
assign("last_calendar", value = function(...) calendar, envir = the) |
395 | ||
396 |
## Get data |
|
397 | 1x |
n <- seq_len(NCOL(x)) |
398 | 1x |
samples <- labels(x) %||% paste0("S1", n) |
399 | 1x |
years <- time(x, calendar = NULL) |
400 | ||
401 |
## Graphical parameters |
|
402 | 1x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis") |
403 | 1x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis") |
404 | 1x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis") |
405 | ||
406 |
## Save and restore |
|
407 | 1x |
mar <- graphics::par("mar") |
408 | 1x |
mar[2] <- inch2line(samples, cex = cex.axis) + 0.5 |
409 | 1x |
old_par <- graphics::par(mar = mar) |
410 | 1x |
on.exit(graphics::par(old_par)) |
411 | ||
412 |
## Plot |
|
413 | 1x |
z <- x[, , k = k, drop = TRUE] |
414 | 1x |
graphics::image(x = years, y = n, z = z, |
415 | 1x |
xlab = format(calendar), ylab = "", |
416 | 1x |
xaxt = "n", yaxt = "n", ...) |
417 | ||
418 |
## Construct axes |
|
419 | 1x |
at <- as_fixed(graphics::axTicks(side = 1)) |
420 | 1x |
at <- pretty(at, calendar = calendar) |
421 | 1x |
lab <- format(at, label = FALSE, calendar = calendar) |
422 | 1x |
graphics::axis(side = 1, at = at, labels = lab) |
423 | 1x |
graphics::axis(side = 2, at = n, labels = samples, |
424 | 1x |
cex.axis = cex.axis, las = 1, |
425 | 1x |
col.axis = col.axis, font.axis = font.axis) |
426 | ||
427 | 1x |
invisible(x) |
428 |
} |
|
429 | ||
430 |
#' @export |
|
431 |
#' @rdname image |
|
432 |
#' @aliases image,TimeSeries-method |
|
433 |
setMethod("image", c(x = "TimeSeries"), image.TimeSeries) |
1 |
# SHOW |
|
2 | ||
3 |
# Show ========================================================================= |
|
4 |
setMethod( |
|
5 |
f = "show", |
|
6 |
signature = "TimeScale", |
|
7 |
definition = function(object) { |
|
8 | 2x |
cal_name <- calendar_name(object) |
9 | 2x |
cal_label <- calendar_label(object) |
10 | 2x |
has_name <- length(cal_name) == 1 && cal_name != "" |
11 | 2x |
has_label <- length(cal_label) == 1 && cal_label != "" |
12 | ||
13 | 2x |
era <- "" |
14 | 2x |
if (has_name && has_label) { |
15 | 1x |
era <- sprintf("%s (%s): ", cal_name, cal_label) |
16 |
} |
|
17 | ||
18 | 2x |
if (calendar_direction(object) > 0) { |
19 | 2x |
msg <- tr_("%s%s counted forwards from %g") |
20 |
} else { |
|
21 | ! |
msg <- tr_("%s%s counted backwards from %g") |
22 |
} |
|
23 | 2x |
msg <- sprintf(msg, era, calendar_unit(object), calendar_epoch(object)) |
24 | 2x |
cat(trimws(msg), sep = "\n") |
25 |
} |
|
26 |
) |
|
27 | ||
28 |
setMethod( |
|
29 |
f = "show", |
|
30 |
signature = "RataDie", |
|
31 |
definition = function(object) { |
|
32 | 1x |
msg <- tr_("Rata die: number of days since 01-01-01 (Gregorian)") |
33 | 1x |
cat(msg, sep = "\n") |
34 | 1x |
methods::callGeneric(object@.Data) |
35 |
} |
|
36 |
) |
|
37 | ||
38 |
setMethod( |
|
39 |
f = "show", |
|
40 |
signature = "TimeSeries", |
|
41 |
definition = function(object) { |
|
42 | 1x |
n <- dim(object) |
43 | 1x |
k <- n[[2]] + n[[3]] - 1 |
44 | 1x |
start <- format(as_fixed(start(object))) |
45 | 1x |
end <- format(as_fixed(end(object))) |
46 | 1x |
msg <- ngettext(k, "%d x %d x %d time series observed between %s and %s", |
47 | 1x |
"%d x %d x %d time series observed between %s and %s") |
48 | 1x |
msg <- sprintf(msg, n[[1L]], n[[2L]], n[[3L]], start, end) |
49 | 1x |
cat(msg, sep = "\n") |
50 |
} |
|
51 |
) |
|
52 | ||
53 |
setMethod( |
|
54 |
f = "show", |
|
55 |
signature = "TimeIntervals", |
|
56 |
definition = function(object) { |
|
57 | ! |
n <- length(object) |
58 | ! |
start <- format(as_fixed(min(start(object)))) |
59 | ! |
end <- format(as_fixed(max(end(object)))) |
60 | ! |
msg <- ngettext(n, "%d time interval observed between %s and %s", |
61 | ! |
"%d time intervals observed between %s and %s") |
62 | ! |
msg <- sprintf(msg, n, start, end) |
63 | ! |
cat(msg, sep = "\n") |
64 |
} |
|
65 |
) |
1 |
# CONVERT |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname convert |
|
7 |
#' @aliases convert,character,character-method |
|
8 |
setMethod( |
|
9 |
f = "convert", |
|
10 |
signature = c(from = "character", to = "character"), |
|
11 |
definition = function(from, to) { |
|
12 | 2x |
methods::callGeneric(from = calendar(from), to = calendar(to)) |
13 |
} |
|
14 |
) |
|
15 | ||
16 |
#' @export |
|
17 |
#' @rdname convert |
|
18 |
#' @aliases convert,TimeScale,TimeScale-method |
|
19 |
setMethod( |
|
20 |
f = "convert", |
|
21 |
signature = c(from = "TimeScale", to = "TimeScale"), |
|
22 |
definition = function(from, to) { |
|
23 |
## TODO: validation |
|
24 | ||
25 | 2x |
fun <- function(x) { |
26 | 2x |
a <- fixed(x, month = 01, day = 01, calendar = from) |
27 | 2x |
b <- as_year(a, calendar = to, decimal = TRUE) |
28 | 2x |
return(b) |
29 |
} |
|
30 | ||
31 | 2x |
return(fun) |
32 |
} |
|
33 |
) |
1 |
# TIME |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @method start TimeSeries |
|
7 |
start.TimeSeries <- function(x, calendar = NULL, ...) { |
|
8 | 12x |
z <- min(x@.Time) |
9 | 8x |
if (is.null(calendar)) return(z) |
10 | 4x |
as_year(z, calendar = calendar, decimal = TRUE) |
11 |
} |
|
12 | ||
13 |
#' @export |
|
14 |
#' @rdname start |
|
15 |
#' @aliases start,TimeSeries-method |
|
16 |
setMethod("start", "TimeSeries", start.TimeSeries) |
|
17 | ||
18 |
#' @export |
|
19 |
#' @method start TimeIntervals |
|
20 |
start.TimeIntervals <- function(x, calendar = NULL, ...) { |
|
21 | 20x |
z <- x@.Start |
22 | 9x |
if (is.null(calendar)) return(z) |
23 | 11x |
as_year(z, calendar = calendar, decimal = TRUE) |
24 |
} |
|
25 | ||
26 |
#' @export |
|
27 |
#' @rdname start |
|
28 |
#' @aliases start,TimeIntervals-method |
|
29 |
setMethod("start", "TimeIntervals", start.TimeIntervals) |
|
30 | ||
31 |
#' @export |
|
32 |
#' @method end TimeSeries |
|
33 |
end.TimeSeries <- function(x, calendar = NULL, ...) { |
|
34 | 12x |
z <- max(x@.Time) |
35 | 8x |
if (is.null(calendar)) return(z) |
36 | 4x |
as_year(z, calendar = calendar, decimal = TRUE) |
37 |
} |
|
38 | ||
39 |
#' @export |
|
40 |
#' @rdname start |
|
41 |
#' @aliases end,TimeSeries-method |
|
42 |
setMethod("end", "TimeSeries", end.TimeSeries) |
|
43 | ||
44 |
#' @export |
|
45 |
#' @method end TimeIntervals |
|
46 |
end.TimeIntervals <- function(x, calendar = NULL, ...) { |
|
47 | 20x |
z <- x@.End |
48 | 9x |
if (is.null(calendar)) return(z) |
49 | 11x |
as_year(z, calendar = calendar, decimal = TRUE) |
50 |
} |
|
51 | ||
52 |
#' @export |
|
53 |
#' @rdname start |
|
54 |
#' @aliases end,TimeIntervals-method |
|
55 |
setMethod("end", "TimeIntervals", end.TimeIntervals) |
|
56 | ||
57 |
#' @export |
|
58 |
#' @method time TimeSeries |
|
59 |
time.TimeSeries <- function(x, calendar = NULL, ...) { |
|
60 | 60x |
z <- x@.Time |
61 | 25x |
if (is.null(calendar)) return(z) |
62 | 35x |
as_year(z, calendar = calendar, decimal = TRUE) |
63 |
} |
|
64 | ||
65 |
#' @export |
|
66 |
#' @rdname time |
|
67 |
#' @aliases time,TimeSeries-method |
|
68 |
setMethod("time", "TimeSeries", time.TimeSeries) |
|
69 | ||
70 |
#' @export |
|
71 |
#' @method frequency TimeSeries |
|
72 |
frequency.TimeSeries <- function(x, ...) { |
|
73 | 1x |
mean(abs(1 / diff(time(x)))) |
74 |
} |
|
75 | ||
76 |
#' @export |
|
77 |
#' @rdname time |
|
78 |
#' @aliases frequency,TimeSeries-method |
|
79 |
setMethod("frequency", "TimeSeries", frequency.TimeSeries) |
1 |
# SUBSET |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Extract ====================================================================== |
|
6 |
## [ --------------------------------------------------------------------------- |
|
7 |
#' @export |
|
8 |
#' @rdname subset |
|
9 |
#' @aliases [,RataDie-method |
|
10 |
setMethod( |
|
11 |
f = "[", |
|
12 |
signature = c(x = "RataDie"), |
|
13 |
function(x, i) { |
|
14 | 273x |
z <- methods::callNextMethod() # Method for `numeric` |
15 | 273x |
methods::initialize(x, z) |
16 |
} |
|
17 |
) |
|
18 | ||
19 |
#' @export |
|
20 |
#' @rdname subset |
|
21 |
#' @aliases [,TimeIntervals-method |
|
22 |
setMethod( |
|
23 |
f = "[", |
|
24 |
signature = c(x = "TimeIntervals"), |
|
25 |
function(x, i) { |
|
26 | ! |
id <- x@.Id[i] |
27 | ! |
start <- x@.Start[i] |
28 | ! |
end <- x@.End[i] |
29 | ! |
methods::initialize(x, .Id = id, .Start = start, .End = end) |
30 |
} |
|
31 |
) |
|
32 | ||
33 |
#' @export |
|
34 |
#' @rdname subset |
|
35 |
#' @aliases [,TimeSeries-method |
|
36 |
setMethod( |
|
37 |
f = "[", |
|
38 |
signature = c(x = "TimeSeries"), |
|
39 |
function(x, i, j, k, drop = FALSE) { |
|
40 | 77x |
z <- x@.Data |
41 | 77x |
time <- x@.Time |
42 | ||
43 | 77x |
z <- z[i, j, k, drop = drop] |
44 | 42x |
if (isTRUE(drop)) return(z) |
45 | ||
46 | 35x |
if (!missing(i)) { |
47 | ! |
if (is.character(i)) i <- match(i, dimnames(x)[1L]) |
48 | 4x |
time <- time[i] |
49 |
} |
|
50 | ||
51 | 35x |
methods::initialize(x, z, .Time = time) |
52 |
} |
|
53 |
) |
|
54 | ||
55 |
# Window ======================================================================= |
|
56 |
#' @export |
|
57 |
#' @method window TimeSeries |
|
58 |
window.TimeSeries <- function(x, start = NULL, end = NULL, ...) { |
|
59 | 1x |
if (is.null(start)) start <- start(x) |
60 | 1x |
if (is.null(end)) end <- end(x) |
61 | 3x |
years <- time(x) |
62 | ||
63 | 3x |
i <- which(years >= start & years <= end) |
64 | 3x |
x[i, , , drop = FALSE] |
65 |
} |
|
66 | ||
67 |
#' @export |
|
68 |
#' @rdname window |
|
69 |
#' @aliases window,TimeSeries-method |
|
70 |
setMethod("window", "TimeSeries", window.TimeSeries) |
1 |
# YEAR |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Decimal years ================================================================ |
|
6 |
#' @export |
|
7 |
#' @rdname as_decimal |
|
8 |
#' @aliases as_decimal,numeric,numeric,numeric,GregorianCalendar-method |
|
9 |
setMethod( |
|
10 |
f = "as_decimal", |
|
11 |
signature = c(year = "numeric", month = "numeric", day = "numeric", calendar = "GregorianCalendar"), |
|
12 |
definition = function(year, month, day, calendar) { |
|
13 |
## Shift origin |
|
14 | 3x |
year <- (year - calendar_epoch(calendar)) * calendar_direction(calendar) |
15 | ||
16 | 3x |
.as_decimal(year, month, day, calendar) |
17 |
} |
|
18 |
) |
|
19 | ||
20 |
#' @export |
|
21 |
#' @rdname as_decimal |
|
22 |
#' @aliases as_decimal,numeric,numeric,numeric,JulianCalendar-method |
|
23 |
setMethod( |
|
24 |
f = "as_decimal", |
|
25 |
signature = c(year = "numeric", month = "numeric", day = "numeric", calendar = "JulianCalendar"), |
|
26 |
definition = function(year, month, day, calendar) { |
|
27 | 1x |
.as_decimal(year, month, day, calendar) |
28 |
} |
|
29 |
) |
|
30 | ||
31 |
.as_decimal <- function(year, month, day, calendar) { |
|
32 |
## Year length in days |
|
33 | 4x |
start <- fixed(year, 01, 01, calendar = calendar) |
34 | 4x |
end <- fixed(year, 12, 31, calendar = calendar) |
35 | 4x |
total <- end - start + 1 |
36 | ||
37 |
## Elapsed time |
|
38 | 4x |
date <- fixed(year, month, day, calendar = calendar) |
39 | 4x |
sofar <- date - start |
40 | ||
41 | 4x |
unclass(year + sofar / total) |
42 |
} |
|
43 | ||
44 |
# Leap year ==================================================================== |
|
45 |
is_julian_leap_year <- function(year) { |
|
46 | 43x |
year <- floor(year) # Drop decimal part (if any) |
47 | 43x |
leap <- year %% 4 == 3 |
48 | 43x |
leap[year > 0] <- year[year > 0] %% 4 == 0 |
49 | 43x |
leap |
50 |
} |
|
51 | ||
52 |
is_gregorian_leap_year <- function(year) { |
|
53 | 419x |
year <- floor(year) # Drop decimal part (if any) |
54 | 419x |
((year %% 4) == 0) & |
55 | 419x |
(year %% 400 != 100) & |
56 | 419x |
(year %% 400 != 200) & |
57 | 419x |
(year %% 400 != 300) |
58 |
} |
1 |
# TIME SERIES |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# array ======================================================================== |
|
6 |
#' @export |
|
7 |
#' @rdname series |
|
8 |
#' @aliases series,array,RataDie,missing-method |
|
9 |
setMethod( |
|
10 |
f = "series", |
|
11 |
signature = c(object = "array", time = "RataDie", calendar = "missing"), |
|
12 |
definition = function(object, time, names = NULL) { |
|
13 |
## Validation |
|
14 | 20x |
arkhe::assert_length(time, NROW(object)) |
15 | ||
16 |
## Set the names of the series |
|
17 | 20x |
n <- dim(object)[2L] |
18 | 20x |
if (!is.null(names)) { |
19 | 2x |
arkhe::assert_length(names, n) |
20 | 2x |
dimnames(object)[[2L]] <- names |
21 |
} |
|
22 | 20x |
if (is.null(dimnames(object)[[2L]])) { |
23 | 15x |
dimnames(object)[[2L]] <- paste0("S", seq_len(n)) |
24 |
} |
|
25 | ||
26 |
## Chronological order |
|
27 | 20x |
i <- order(time, decreasing = FALSE) |
28 | 20x |
time <- time[i] |
29 | 20x |
object <- object[i, , , drop = FALSE] |
30 | ||
31 | 20x |
.TimeSeries(object, .Time = time) |
32 |
} |
|
33 |
) |
|
34 | ||
35 |
#' @export |
|
36 |
#' @rdname series |
|
37 |
#' @aliases series,array,numeric,TimeScale-method |
|
38 |
setMethod( |
|
39 |
f = "series", |
|
40 |
signature = c(object = "array", time = "numeric", calendar = "TimeScale"), |
|
41 |
definition = function(object, time, calendar, scale = 1, names = NULL) { |
|
42 | 11x |
if (methods::is(time, "RataDie")) { |
43 | 1x |
msg <- tr_("%s is already expressed in rata die: %s is ignored.") |
44 | 1x |
warning(sprintf(msg, sQuote("time"), sQuote("calendar")), call. = FALSE) |
45 |
} else { |
|
46 | 10x |
time <- fixed(time, calendar = calendar, scale = scale) |
47 |
} |
|
48 | 11x |
methods::callGeneric(object = object, time = time, names = names) |
49 |
} |
|
50 |
) |
|
51 | ||
52 |
# matrix ======================================================================= |
|
53 |
#' @export |
|
54 |
#' @rdname series |
|
55 |
#' @aliases series,matrix,numeric,TimeScale-method |
|
56 |
setMethod( |
|
57 |
f = "series", |
|
58 |
signature = c(object = "matrix", time = "numeric", calendar = "TimeScale"), |
|
59 |
definition = function(object, time, calendar, scale = 1, names = NULL) { |
|
60 | 10x |
x <- array(object, dim = c(dim(object), 1)) |
61 | 10x |
rownames(x) <- rownames(object) |
62 | 10x |
colnames(x) <- colnames(object) |
63 | 10x |
methods::callGeneric(object = x, time = time, calendar = calendar, |
64 | 10x |
scale = scale, names = names) |
65 |
} |
|
66 |
) |
|
67 | ||
68 |
#' @export |
|
69 |
#' @rdname series |
|
70 |
#' @aliases series,matrix,RataDie,missing-method |
|
71 |
setMethod( |
|
72 |
f = "series", |
|
73 |
signature = c(object = "matrix", time = "RataDie", calendar = "missing"), |
|
74 |
definition = function(object, time, names = NULL) { |
|
75 | 4x |
x <- array(object, dim = c(dim(object), 1)) |
76 | 4x |
colnames(x) <- colnames(object) |
77 | 4x |
methods::callGeneric(object = x, time = time, names = names) |
78 |
} |
|
79 |
) |
|
80 | ||
81 |
# numeric ====================================================================== |
|
82 |
#' @export |
|
83 |
#' @rdname series |
|
84 |
#' @aliases series,numeric,numeric,TimeScale-method |
|
85 |
setMethod( |
|
86 |
f = "series", |
|
87 |
signature = c(object = "numeric", time = "numeric", calendar = "TimeScale"), |
|
88 |
definition = function(object, time, calendar, scale = 1, names = NULL) { |
|
89 | 1x |
object <- array(data = object, dim = c(length(object), 1, 1)) |
90 | 1x |
methods::callGeneric(object = object, time = time, calendar = calendar, |
91 | 1x |
scale = scale, names = names) |
92 |
} |
|
93 |
) |
|
94 | ||
95 |
#' @export |
|
96 |
#' @rdname series |
|
97 |
#' @aliases series,numeric,RataDie,missing-method |
|
98 |
setMethod( |
|
99 |
f = "series", |
|
100 |
signature = c(object = "numeric", time = "RataDie", calendar = "missing"), |
|
101 |
definition = function(object, time, names = NULL) { |
|
102 | 5x |
object <- array(data = object, dim = c(length(object), 1, 1)) |
103 | 5x |
methods::callGeneric(object = object, time = time, names = names) |
104 |
} |
|
105 |
) |
|
106 | ||
107 |
# data.frame =================================================================== |
|
108 |
#' @export |
|
109 |
#' @rdname series |
|
110 |
#' @aliases series,data.frame,numeric,TimeScale-method |
|
111 |
setMethod( |
|
112 |
f = "series", |
|
113 |
signature = c(object = "data.frame", time = "numeric", calendar = "TimeScale"), |
|
114 |
definition = function(object, time, calendar, scale = 1, names = NULL) { |
|
115 | 1x |
object <- data.matrix(object) |
116 | 1x |
methods::callGeneric(object = object, time = time, calendar = calendar, |
117 | 1x |
scale = scale, names = names) |
118 |
} |
|
119 |
) |
|
120 | ||
121 |
#' @export |
|
122 |
#' @rdname series |
|
123 |
#' @aliases series,data.frame,RataDie,missing-method |
|
124 |
setMethod( |
|
125 |
f = "series", |
|
126 |
signature = c(object = "data.frame", time = "RataDie", calendar = "missing"), |
|
127 |
definition = function(object, time, names = NULL) { |
|
128 | 1x |
object <- data.matrix(object) |
129 | 1x |
methods::callGeneric(object = object, time = time, names = names) |
130 |
} |
|
131 |
) |
1 |
# JULINA CALENDAR |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Fixed from Julian ============================================================ |
|
6 |
#' @export |
|
7 |
#' @rdname fixed |
|
8 |
#' @aliases fixed,numeric,missing,missing,JulianCalendar-method |
|
9 |
setMethod( |
|
10 |
f = "fixed", |
|
11 |
signature = c(year = "numeric", month = "missing", day = "missing", calendar = "JulianCalendar"), |
|
12 |
definition = function(year, calendar, scale = 1) { |
|
13 |
## Rescale to years (if not already) |
|
14 | 6x |
year <- year * scale |
15 | ||
16 | 6x |
rd <- fixed(year, 01, 01, calendar = calendar) |
17 | ||
18 | 5x |
is_leap <- which(is_julian_leap_year(year)) |
19 | 5x |
rd[is_leap] <- ceiling(rd[is_leap]) # WHY ??? |
20 | 5x |
rd |
21 |
} |
|
22 |
) |
|
23 | ||
24 |
#' @export |
|
25 |
#' @rdname fixed |
|
26 |
#' @aliases fixed,numeric,numeric,numeric,JulianCalendar-method |
|
27 |
setMethod( |
|
28 |
f = "fixed", |
|
29 |
signature = c(year = "numeric", month = "numeric", day = "numeric", calendar = "JulianCalendar"), |
|
30 |
definition = function(year, month, day, calendar) { |
|
31 |
## Validation |
|
32 | 36x |
if (any(year == 0)) { |
33 | 1x |
stop(tr_("There is no year zero in the Julian calendar."), call. = FALSE) |
34 |
} |
|
35 | ||
36 |
## Correct for 28- or 29-day Feb |
|
37 | 35x |
correction <- rep(-2, length(year)) |
38 | 35x |
correction[which(is_julian_leap_year(year))] <- -1 |
39 | 35x |
correction[month <= 2] <- 0 |
40 | ||
41 |
## There is no year 0 on the Julian calendar |
|
42 | 35x |
year[year < 0] <- year[year < 0] + 1 |
43 | ||
44 | 35x |
rd <- calendar_fixed(calendar) - 1 + # Days before start of calendar |
45 | 35x |
365 * (year - 1) + # Ordinary days since epoch |
46 | 35x |
(year - 1) %/% 4 + # Leap days since epoch |
47 | 35x |
(367 * month - 362) %/% 12 + # Days in prior months this year assuming 30-day Feb |
48 | 35x |
correction + # Correct for 28- or 29-day Feb |
49 | 35x |
day # Days so far this month. |
50 | ||
51 |
## Fix infinite values |
|
52 | 35x |
rd[is.infinite(year)] <- year[is.infinite(year)] |
53 | ||
54 | 35x |
.RataDie(rd) |
55 |
} |
|
56 |
) |
|
57 | ||
58 |
# Julian from fixed ============================================================ |
|
59 |
#' @export |
|
60 |
#' @rdname as_year |
|
61 |
#' @aliases as_year,numeric,JulianCalendar-method |
|
62 |
setMethod( |
|
63 |
f = "as_year", |
|
64 |
signature = c(object = "numeric", calendar = "JulianCalendar"), |
|
65 |
definition = function(object, calendar, decimal = FALSE, ...) { |
|
66 | 21x |
d0 <- object - calendar_fixed(calendar) |
67 | 21x |
year <- (4 * d0 + 1464) %/% 1461 |
68 | ||
69 |
## There is no year 0 on the Julian calendar |
|
70 | 21x |
year[year <= 0] <- year[year <= 0] - 1 |
71 | ||
72 | 21x |
if (isTRUE(decimal)) { |
73 |
## Year length in days |
|
74 | 8x |
start <- fixed(year, 01, 01, calendar = calendar) |
75 | 8x |
end <- fixed(year, 12, 31, calendar = calendar) |
76 | 8x |
total <- end - start + 1 |
77 | ||
78 |
## Elapsed time |
|
79 | 8x |
sofar <- object - start |
80 | ||
81 | 8x |
year <- year + sofar / total |
82 |
} |
|
83 | ||
84 |
## Fix infinite values |
|
85 | 21x |
year[is.infinite(object)] <- object[is.infinite(object)] |
86 | ||
87 | 21x |
unclass(year) |
88 |
} |
|
89 |
) |
|
90 | ||
91 |
#' @export |
|
92 |
#' @rdname as_date |
|
93 |
#' @aliases as_date,numeric,JulianCalendar-method |
|
94 |
setMethod( |
|
95 |
f = "as_date", |
|
96 |
signature = c(object = "numeric", calendar = "JulianCalendar"), |
|
97 |
definition = function(object, calendar) { |
|
98 | 3x |
year <- as_year(object, calendar = calendar, decimal = FALSE) |
99 | 3x |
prior_days <- object - fixed(year, 01, 01, calendar = calendar) |
100 | ||
101 | 3x |
correction <- rep(2, length(object)) |
102 | 3x |
correction[object < fixed(year, 03, 01, calendar = calendar)] <- 0 |
103 | 3x |
correction[is_julian_leap_year(year)] <- 1 |
104 | ||
105 | 3x |
month <- (12 * (prior_days + correction) + 373) %/% 367 |
106 | 3x |
day <- object - fixed(year, month, 01, calendar = calendar) + 1 |
107 | ||
108 | 3x |
data.frame( |
109 | 3x |
year = unclass(year), |
110 | 3x |
month = unclass(month), |
111 | 3x |
day = unclass(day) |
112 |
) |
|
113 |
} |
|
114 |
) |
|
115 | ||
116 |
# Era ========================================================================== |
|
117 |
#' @export |
|
118 |
#' @rdname fixed_julian |
|
119 |
fixed_from_julian <- function(year, month, day) { |
|
120 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = J()) |
121 | 1x |
else fixed(year, month, day, calendar = J()) |
122 |
} |
|
123 | ||
124 |
#' @export |
|
125 |
#' @rdname fixed_julian |
|
126 |
fixed_to_julian <- function(object) { |
|
127 | 1x |
as_year(object, calendar = J()) |
128 |
} |
1 |
# TIME SCALE |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname calendar |
|
7 |
#' @aliases calendar,character-method |
|
8 |
setMethod( |
|
9 |
f = "calendar", |
|
10 |
signature = "character", |
|
11 |
definition = function(object) { |
|
12 |
switch ( |
|
13 | 52x |
tolower(object), |
14 | 7x |
bp = BP(), |
15 | ! |
b2k = b2k(), |
16 | ! |
bc = BC(), |
17 | 12x |
bce = BCE(), |
18 | 2x |
ad = AD(), |
19 | 29x |
ce = CE(), |
20 | 1x |
julian = J(), |
21 | 1x |
stop(sprintf(tr_("Unknown calendar: %s"), object), call. = FALSE) |
22 |
) |
|
23 |
} |
|
24 |
) |
|
25 | ||
26 |
#' @export |
|
27 |
#' @rdname gregorian |
|
28 |
BP <- function(...) { |
|
29 | 18x |
.GregorianCalendar( |
30 | 18x |
label = tr_("BP"), |
31 | 18x |
name = tr_("Before Present"), |
32 | 18x |
epoch = 1950, |
33 | 18x |
direction = -1L |
34 |
) |
|
35 |
} |
|
36 | ||
37 |
#' @export |
|
38 |
#' @rdname gregorian |
|
39 |
b2k <- function(...) { |
|
40 | 5x |
.GregorianCalendar( |
41 | 5x |
label = tr_("b2k"), |
42 | 5x |
name = tr_("Before 2000"), |
43 | 5x |
epoch = 2000, |
44 | 5x |
direction = -1L |
45 |
) |
|
46 |
} |
|
47 | ||
48 |
#' @export |
|
49 |
#' @rdname gregorian |
|
50 |
BC <- function(...) { |
|
51 | 2x |
.GregorianCalendar( |
52 | 2x |
label = tr_("BC"), |
53 | 2x |
name = tr_("Before Christ"), |
54 | 2x |
direction = -1L |
55 |
) |
|
56 |
} |
|
57 | ||
58 |
#' @export |
|
59 |
#' @rdname gregorian |
|
60 |
BCE <- function(...) { |
|
61 | 21x |
.GregorianCalendar( |
62 | 21x |
label = tr_("BCE"), |
63 | 21x |
name = tr_("Before Common Era"), |
64 | 21x |
direction = -1L |
65 |
) |
|
66 |
} |
|
67 | ||
68 |
#' @export |
|
69 |
#' @rdname gregorian |
|
70 |
AD <- function(...) { |
|
71 | 19x |
.GregorianCalendar( |
72 | 19x |
label = tr_("AD"), |
73 | 19x |
name = tr_("Anno Domini") |
74 |
) |
|
75 |
} |
|
76 | ||
77 |
#' @export |
|
78 |
#' @rdname gregorian |
|
79 |
CE <- function(...) { |
|
80 | 79x |
.GregorianCalendar( |
81 | 79x |
label = tr_("CE"), |
82 | 79x |
name = tr_("Common Era") |
83 |
) |
|
84 |
} |
|
85 | ||
86 |
#' @export |
|
87 |
#' @rdname julian |
|
88 |
J <- function(...) { |
|
89 | 16x |
.JulianCalendar( |
90 | 16x |
label = "", |
91 | 16x |
name = "" |
92 |
) |
|
93 |
} |
|
94 | ||
95 |
# Default calendar ============================================================= |
|
96 |
the <- new.env(parent = emptyenv()) |
|
97 |
the$default_calendar <- function(...) calendar("CE") |
|
98 |
the$last_calendar <- function(...) return(NULL) |
|
99 | ||
100 |
#' @export |
|
101 |
#' @rdname get_calendar |
|
102 |
get_calendar <- function(which = c("default", "current")) { |
|
103 | 33x |
which <- match.arg(which, several.ok = FALSE) |
104 | 33x |
which_calendar <- switch( |
105 | 33x |
which, |
106 | 33x |
default = "default_calendar", |
107 | 33x |
current = "last_calendar" |
108 |
) |
|
109 | ||
110 | 33x |
if (!exists(which_calendar, envir = the)) { |
111 | ! |
stop(tr_("Unspecified calendar."), call. = FALSE) |
112 |
} |
|
113 | ||
114 | 33x |
cal <- get(which_calendar, envir = the) |
115 | 33x |
if (!is.null(cal()) && !is_calendar(cal())) { |
116 | ! |
stop(tr_("Invalid calendar."), call. = FALSE) |
117 |
} |
|
118 | 33x |
return(cal()) |
119 |
} |
|
120 | ||
121 |
#' @export |
|
122 |
#' @rdname get_calendar |
|
123 |
set_calendar <- function(x, which = c("default", "current")) { |
|
124 | 1x |
if (missing(x)) x <- "CE" |
125 | 2x |
which <- match.arg(which, several.ok = FALSE) |
126 | 2x |
which_calendar <- switch( |
127 | 2x |
which, |
128 | 2x |
default = "default_calendar", |
129 | 2x |
current = "last_calendar" |
130 |
) |
|
131 | ||
132 | 2x |
cal <- function(...) calendar(x) |
133 | 2x |
assign(which_calendar, value = cal, envir = the) |
134 | 2x |
invisible(cal()) |
135 |
} |
|
136 | ||
137 |
# Predicates =================================================================== |
|
138 |
#' Is an Object a Calendar? |
|
139 |
#' |
|
140 |
#' Test inheritance relationships between an object and a calendar class. |
|
141 |
#' @param object Any \R object. |
|
142 |
#' @return |
|
143 |
#' A [`logical`] scalar. |
|
144 |
#' @author N. Frerebeau |
|
145 |
#' @docType methods |
|
146 |
#' @family calendar tools |
|
147 |
#' @export |
|
148 |
is_calendar <- function(object) { |
|
149 | 31x |
methods::is(object, "TimeScale") |
150 |
} |
|
151 | ||
152 |
#' @export |
|
153 |
#' @rdname is_calendar |
|
154 |
is_gregorian <- function(object) { |
|
155 | 23x |
methods::is(object, "GregorianCalendar") |
156 |
} |
|
157 | ||
158 |
#' @export |
|
159 |
#' @rdname is_calendar |
|
160 |
is_julian <- function(object) { |
|
161 | 7x |
methods::is(object, "JulianCalendar") |
162 |
} |
|
163 | ||
164 |
# Mutators ===================================================================== |
|
165 |
## Getters --------------------------------------------------------------------- |
|
166 |
#' @export |
|
167 |
#' @rdname calendar_get |
|
168 |
#' @aliases calendar_label,TimeScale-method |
|
169 |
setMethod( |
|
170 |
f = "calendar_label", |
|
171 |
signature = "TimeScale", |
|
172 | 30x |
definition = function(object) object@label |
173 |
) |
|
174 | ||
175 |
#' @export |
|
176 |
#' @rdname calendar_get |
|
177 |
#' @aliases calendar_name,TimeScale-method |
|
178 |
setMethod( |
|
179 |
f = "calendar_name", |
|
180 |
signature = "TimeScale", |
|
181 | 4x |
definition = function(object) object@name |
182 |
) |
|
183 | ||
184 |
#' @export |
|
185 |
#' @rdname calendar_get |
|
186 |
#' @aliases calendar_unit,TimeScale-method |
|
187 |
setMethod( |
|
188 |
f = "calendar_unit", |
|
189 |
signature = "TimeScale", |
|
190 |
definition = function(object) { |
|
191 | 16x |
if (is_gregorian(object)) return(tr_("Gregorian years")) |
192 | 5x |
if (is_julian(object)) return(tr_("Julian years")) |
193 | ! |
return(tr_("Undefined")) |
194 |
} |
|
195 |
) |
|
196 | ||
197 |
#' @export |
|
198 |
#' @rdname calendar_get |
|
199 |
#' @aliases calendar_epoch,TimeScale-method |
|
200 |
setMethod( |
|
201 |
f = "calendar_epoch", |
|
202 |
signature = "TimeScale", |
|
203 | 497x |
definition = function(object) object@epoch |
204 |
) |
|
205 | ||
206 |
#' @export |
|
207 |
#' @rdname calendar_get |
|
208 |
#' @aliases calendar_fixed,TimeScale-method |
|
209 |
setMethod( |
|
210 |
f = "calendar_fixed", |
|
211 |
signature = "TimeScale", |
|
212 | 548x |
definition = function(object) object@fixed |
213 |
) |
|
214 | ||
215 |
#' @export |
|
216 |
#' @rdname calendar_get |
|
217 |
#' @aliases calendar_direction,TimeScale-method |
|
218 |
setMethod( |
|
219 |
f = "calendar_direction", |
|
220 |
signature = "TimeScale", |
|
221 | 510x |
definition = function(object) sign(object@direction) |
222 |
) |
|
223 | ||
224 |
#' @export |
|
225 |
#' @rdname calendar_get |
|
226 |
#' @aliases calendar_direction,NULL-method |
|
227 |
setMethod( |
|
228 |
f = "calendar_direction", |
|
229 |
signature = "NULL", |
|
230 | 1x |
definition = function(object) 1L |
231 |
) |
|
232 | ||
233 |
#' @export |
|
234 |
#' @rdname calendar_get |
|
235 |
#' @aliases calendar_year,TimeScale-method |
|
236 |
setMethod( |
|
237 |
f = "calendar_year", |
|
238 |
signature = "TimeScale", |
|
239 | 2x |
definition = function(object) object@year |
240 |
) |
1 |
# GENERIC METHODS |
|
2 |
#' @include AllClasses.R |
|
3 |
NULL |
|
4 | ||
5 |
# Tools ======================================================================== |
|
6 |
## Mutators -------------------------------------------------------------------- |
|
7 |
# Get or Set Parts of an Object |
|
8 |
# |
|
9 |
# Getters and setters to extract or replace parts of an object. |
|
10 |
# @param x An object from which to get or set element(s). |
|
11 |
# @param value A possible value for the element(s) of `x`. |
|
12 |
# @return |
|
13 |
# An object of the same sort as `x` with the new values assigned. |
|
14 |
# @example inst/examples/ex-mutator.R |
|
15 |
# @author N. Frerebeau |
|
16 |
# @docType methods |
|
17 |
# @family mutators |
|
18 |
# @name mutators |
|
19 |
# @rdname mutators |
|
20 |
# @aliases get set |
|
21 |
# NULL |
|
22 | ||
23 |
#' Labels |
|
24 |
#' |
|
25 |
#' Find a suitable set of labels from an object. |
|
26 |
#' @param object An \R object. |
|
27 |
#' @param ... Currently not used. |
|
28 |
#' @return |
|
29 |
#' A [`character`] vector. |
|
30 |
#' @author N. Frerebeau |
|
31 |
#' @docType methods |
|
32 |
#' @family mutators |
|
33 |
#' @name labels |
|
34 |
#' @rdname labels |
|
35 |
NULL |
|
36 | ||
37 |
#' Length |
|
38 |
#' |
|
39 |
#' Get the length of an object. |
|
40 |
#' @param x An \R object. |
|
41 |
#' @return |
|
42 |
#' A length-one [`integer`] vector. |
|
43 |
#' @author N. Frerebeau |
|
44 |
#' @docType methods |
|
45 |
#' @family mutators |
|
46 |
#' @name length |
|
47 |
#' @rdname length |
|
48 |
NULL |
|
49 | ||
50 |
## Subset ---------------------------------------------------------------------- |
|
51 |
#' Extract or Replace Parts of an Object |
|
52 |
#' |
|
53 |
#' Operators acting on objects to extract or replace parts. |
|
54 |
#' @param x An object from which to extract element(s) or in which to replace |
|
55 |
#' element(s). |
|
56 |
#' @param i,j,k Indices specifying elements to extract or replace. |
|
57 |
#' @param drop A [`logical`] scalar: should the result be coerced to |
|
58 |
#' the lowest possible dimension? This only works for extracting elements, |
|
59 |
#' not for the replacement. |
|
60 |
# @param value A possible value for the element(s) of `x`. |
|
61 |
# @param ... Currently not used. |
|
62 |
#' @return |
|
63 |
#' A subsetted object. |
|
64 |
# @example inst/examples/ex-subset.R |
|
65 |
#' @author N. Frerebeau |
|
66 |
#' @docType methods |
|
67 |
#' @family mutators |
|
68 |
#' @name subset |
|
69 |
#' @rdname subset |
|
70 |
NULL |
|
71 | ||
72 |
## Coerce ---------------------------------------------------------------------- |
|
73 |
#' Coerce to a Data Frame |
|
74 |
#' |
|
75 |
#' @param x A [`TimeSeries-class`] or a [`TimeIntervals-class`] object. |
|
76 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
77 |
#' (see [calendar()]). If `NULL` (the default), *rata die* are returned. |
|
78 |
#' @param ... Further parameters to be passed to [data.frame()]. |
|
79 |
#' @return |
|
80 |
#' A [`data.frame`]. |
|
81 |
#' @example inst/examples/ex-series.R |
|
82 |
#' @author N. Frerebeau |
|
83 |
#' @docType methods |
|
84 |
#' @family mutators |
|
85 |
#' @name as.data.frame |
|
86 |
#' @rdname as.data.frame |
|
87 |
NULL |
|
88 | ||
89 |
# Calendars ==================================================================== |
|
90 |
#' Calendar |
|
91 |
#' |
|
92 |
#' @param object A [`character`] string specifying the abbreviated label of |
|
93 |
#' the time scale (see details). |
|
94 |
#' @details |
|
95 |
#' The following time scales are available: |
|
96 |
#' |
|
97 |
#' \tabular{lll}{ |
|
98 |
#' **label** \tab **era** \tab **calendar** \cr |
|
99 |
#' `BP` \tab Before Present \tab Gregorian \cr |
|
100 |
#' `BC` \tab Before Christ \tab Gregorian \cr |
|
101 |
#' `BCE` \tab Before Common Era \tab Gregorian \cr |
|
102 |
#' `AD` \tab Anno Domini \tab Gregorian \cr |
|
103 |
#' `CE` \tab Common Era \tab Gregorian \cr |
|
104 |
#' `b2k` \tab Years before 2000 \tab Gregorian \cr |
|
105 |
#' `julian` \tab \tab Julian \cr |
|
106 |
#' } |
|
107 |
#' @return |
|
108 |
#' A [`TimeScale-class`] object. |
|
109 |
#' @note |
|
110 |
#' Inspired by [era::era()] by Joe Roe. |
|
111 |
#' @example inst/examples/ex-calendar.R |
|
112 |
#' @author N. Frerebeau |
|
113 |
#' @docType methods |
|
114 |
#' @family calendar tools |
|
115 |
#' @aliases calendar-method |
|
116 |
setGeneric( |
|
117 |
name = "calendar", |
|
118 |
def = function(object) standardGeneric("calendar"), |
|
119 |
valueClass = "TimeScale" |
|
120 |
) |
|
121 | ||
122 |
#' Gregorian Calendar |
|
123 |
#' |
|
124 |
#' @param ... Currently not used. |
|
125 |
#' @return |
|
126 |
#' A [`GregorianCalendar-class`] object. |
|
127 |
#' @example inst/examples/ex-calendar.R |
|
128 |
#' @seealso [calendar()] |
|
129 |
#' @author N. Frerebeau |
|
130 |
#' @docType methods |
|
131 |
#' @family calendar tools |
|
132 |
#' @name gregorian |
|
133 |
#' @rdname gregorian |
|
134 |
NULL |
|
135 | ||
136 |
#' Julian Calendar |
|
137 |
#' |
|
138 |
#' @param ... Currently not used. |
|
139 |
#' @return |
|
140 |
#' A [`JulianCalendar-class`] object. |
|
141 |
#' @example inst/examples/ex-calendar.R |
|
142 |
#' @seealso [calendar()] |
|
143 |
#' @author N. Frerebeau |
|
144 |
#' @docType methods |
|
145 |
#' @family calendar tools |
|
146 |
#' @name julian |
|
147 |
#' @rdname julian |
|
148 |
NULL |
|
149 | ||
150 |
#' Get or Set the Default Calendar |
|
151 |
#' |
|
152 |
#' @param x A [`character`] string specifying the abbreviated label of |
|
153 |
#' the time scale (see [calendar()]) or an object from which to extract the |
|
154 |
#' time scale. |
|
155 |
#' @param which A [`character`] string specifying the calendar to be set. |
|
156 |
#' It must be one of "`default`" or "`current`". Note that "`current`" is |
|
157 |
#' automatically set by [plot()] or [image()] and should not be changed |
|
158 |
#' manually. |
|
159 |
#' @return |
|
160 |
#' A [`TimeScale-class`] object. |
|
161 |
#' @example inst/examples/ex-calendar.R |
|
162 |
#' @author N. Frerebeau |
|
163 |
#' @docType methods |
|
164 |
#' @family calendar tools |
|
165 |
#' @name get_calendar |
|
166 |
#' @rdname get_calendar |
|
167 |
NULL |
|
168 | ||
169 |
#' Calendar Parameters |
|
170 |
#' |
|
171 |
#' @param object A [`TimeScale-class`] object. |
|
172 |
#' @return |
|
173 |
#' * `calendar_label()` returns a [`character`] string giving the |
|
174 |
#' abbreviated label of the time scale. |
|
175 |
#' * `calendar_name()` returns a [`character`] string giving the name of |
|
176 |
#' the time scale. |
|
177 |
#' * `calendar_unit()` returns a [`character`] string giving the unit of |
|
178 |
#' the calendar. |
|
179 |
#' * `calendar_fixed()` returns a length-one [`numeric`] vector giving the |
|
180 |
#' reference date of the calendar (in *rata die*). |
|
181 |
#' * `calendar_epoch()` returns a length-one [`numeric`] vector giving the |
|
182 |
#' epoch year from which years are counted (starting date of the calendar, |
|
183 |
#' in years). |
|
184 |
#' * `calendar_direction()` returns a length-one [`integer`] vector specifying |
|
185 |
#' if years are counted backwards (\eqn{-1}) or forwards (\eqn{1}) from |
|
186 |
#' `epoch`. Only the [sign][sign()] of `calendar_direction()` is relevant. |
|
187 |
#' * `calendar_year()` returns a length-one [`numeric`] vector giving the |
|
188 |
#' average length of the year in solar days. |
|
189 |
#' @example inst/examples/ex-calendar.R |
|
190 |
#' @author N. Frerebeau |
|
191 |
#' @docType methods |
|
192 |
#' @family calendar tools |
|
193 |
#' @name calendar_get |
|
194 |
#' @rdname calendar_get |
|
195 |
NULL |
|
196 | ||
197 |
#' @rdname calendar_get |
|
198 |
#' @aliases calendar_label-method |
|
199 |
setGeneric( |
|
200 |
name = "calendar_label", |
|
201 | 30x |
def = function(object) standardGeneric("calendar_label") |
202 |
) |
|
203 | ||
204 |
#' @rdname calendar_get |
|
205 |
#' @aliases calendar_name-method |
|
206 |
setGeneric( |
|
207 |
name = "calendar_name", |
|
208 | 4x |
def = function(object) standardGeneric("calendar_name") |
209 |
) |
|
210 | ||
211 |
#' @rdname calendar_get |
|
212 |
#' @aliases calendar_unit-method |
|
213 |
setGeneric( |
|
214 |
name = "calendar_unit", |
|
215 | 21x |
def = function(object) standardGeneric("calendar_unit") |
216 |
) |
|
217 | ||
218 |
#' @rdname calendar_get |
|
219 |
#' @aliases calendar_epoch-method |
|
220 |
setGeneric( |
|
221 |
name = "calendar_epoch", |
|
222 | 497x |
def = function(object) standardGeneric("calendar_epoch") |
223 |
) |
|
224 | ||
225 |
#' @rdname calendar_get |
|
226 |
#' @aliases calendar_fixed-method |
|
227 |
setGeneric( |
|
228 |
name = "calendar_fixed", |
|
229 | 548x |
def = function(object) standardGeneric("calendar_fixed") |
230 |
) |
|
231 | ||
232 |
#' @rdname calendar_get |
|
233 |
#' @aliases calendar_direction-method |
|
234 |
setGeneric( |
|
235 |
name = "calendar_direction", |
|
236 | 511x |
def = function(object) standardGeneric("calendar_direction") |
237 |
) |
|
238 | ||
239 |
#' @rdname calendar_get |
|
240 |
#' @aliases calendar_year-method |
|
241 |
setGeneric( |
|
242 |
name = "calendar_year", |
|
243 | 2x |
def = function(object) standardGeneric("calendar_year") |
244 |
) |
|
245 | ||
246 |
# @rdname calendar_get |
|
247 |
# @aliases calendar_fixed-method |
|
248 |
# setGeneric( |
|
249 |
# name = "calendar_fixed", |
|
250 |
# def = function(object) standardGeneric("calendar_fixed") |
|
251 |
# ) |
|
252 | ||
253 |
# @rdname calendar_get |
|
254 |
# @aliases calendar_year-method |
|
255 |
# setGeneric( |
|
256 |
# name = "calendar_year", |
|
257 |
# def = function(object) standardGeneric("calendar_year") |
|
258 |
# ) |
|
259 | ||
260 |
#' Calendar Converter |
|
261 |
#' |
|
262 |
#' Interconverts dates in a variety of calendars. |
|
263 |
#' @param from A [`TimeScale-class`] object describing the source calendar. |
|
264 |
#' @param to A [`TimeScale-class`] object describing the target calendar. |
|
265 |
#' @param ... Currently not used. |
|
266 |
#' @return |
|
267 |
#' A [`function`] that when called with a single numeric argument (factional |
|
268 |
#' years) converts years from one calendar to another. |
|
269 |
#' @example inst/examples/ex-convert.R |
|
270 |
#' @author N. Frerebeau |
|
271 |
#' @docType methods |
|
272 |
#' @family calendar tools |
|
273 |
#' @aliases convert-method |
|
274 |
setGeneric( |
|
275 |
name = "convert", |
|
276 | 4x |
def = function(from, to, ...) standardGeneric("convert") |
277 |
) |
|
278 | ||
279 |
# Fixed Dates ================================================================== |
|
280 |
#' *Rata Die* (Fixed Date) |
|
281 |
#' |
|
282 |
#' @param year A [`numeric`] vector of years. If `month` and `day` are missing, |
|
283 |
#' decimal years are expected. |
|
284 |
#' @param month A [`numeric`] vector of months. |
|
285 |
#' @param day A [`numeric`] vector of days. |
|
286 |
#' @param calendar A [`TimeScale-class`] object specifying the calendar of |
|
287 |
#' `year`, `month` and `day` (see [calendar()]). |
|
288 |
#' @param scale A length-one [`integer`] vector specifying the number of years |
|
289 |
#' represented by one unit. It should be a power of 10 (i.e. 1000 means ka). |
|
290 |
#' @param ... Currently not used. |
|
291 |
#' @details |
|
292 |
#' *Rata die* are represented as the number of days since 01-01-01 (Gregorian), |
|
293 |
#' with negative values for earlier dates. |
|
294 |
#' @return |
|
295 |
#' A [`RataDie-class`] object. |
|
296 |
#' @example inst/examples/ex-fixed.R |
|
297 |
#' @references |
|
298 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
299 |
#' The Ultimate Edition*. Cambridge University Press. |
|
300 |
#' \doi{10.1017/9781107415058}. |
|
301 |
#' @author N. Frerebeau |
|
302 |
#' @docType methods |
|
303 |
#' @family fixed date tools |
|
304 |
#' @aliases fixed-method |
|
305 |
setGeneric( |
|
306 |
name = "fixed", |
|
307 |
def = function(year, month, day, calendar, ...) standardGeneric("fixed"), |
|
308 |
valueClass = "RataDie" |
|
309 |
) |
|
310 | ||
311 |
#' Coerce to *Rata Die* |
|
312 |
#' |
|
313 |
#' @param from A [`numeric`] vector of *rata die*. |
|
314 |
#' @return |
|
315 |
#' A [`RataDie-class`] object. |
|
316 |
#' @example inst/examples/ex-fixed.R |
|
317 |
#' @references |
|
318 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
319 |
#' The Ultimate Edition*. Cambridge University Press. |
|
320 |
#' \doi{10.1017/9781107415058}. |
|
321 |
#' @author N. Frerebeau |
|
322 |
#' @docType methods |
|
323 |
#' @family fixed date tools |
|
324 |
#' @aliases as_fixed-method |
|
325 |
setGeneric( |
|
326 |
name = "as_fixed", |
|
327 |
def = function(from) standardGeneric("as_fixed"), |
|
328 |
valueClass = "RataDie" |
|
329 |
) |
|
330 | ||
331 |
#' Year Conversion from *Rata Die* |
|
332 |
#' |
|
333 |
#' @param object A [`RataDie-class`] object (see [fixed()]). |
|
334 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
335 |
#' (see [calendar()]). |
|
336 |
#' @param decimal A [`logical`] scalar: should decimal years be returned? |
|
337 |
#' If `FALSE`, the decimal part is dropped. |
|
338 |
#' @param ... Currently not used. |
|
339 |
#' @return |
|
340 |
#' A [`numeric`] vector of (decimal) years. |
|
341 |
#' @example inst/examples/ex-fixed.R |
|
342 |
#' @references |
|
343 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
344 |
#' The Ultimate Edition*. Cambridge University Press. |
|
345 |
#' \doi{10.1017/9781107415058}. |
|
346 |
#' @author N. Frerebeau |
|
347 |
#' @docType methods |
|
348 |
#' @family fixed date tools |
|
349 |
#' @aliases as_year-method |
|
350 |
setGeneric( |
|
351 |
name = "as_year", |
|
352 | 163x |
def = function(object, calendar, ...) standardGeneric("as_year") |
353 |
) |
|
354 | ||
355 |
#' *Rata Die* Conversion to and from Gregorian Years |
|
356 |
#' |
|
357 |
#' Convenient functions for conversion from and to *rata die* for a given |
|
358 |
#' Gregorian era. |
|
359 |
#' @inheritParams fixed |
|
360 |
#' @inheritParams as_year |
|
361 |
#' @return |
|
362 |
#' * `fixed_from_*()` returns a [`RataDie-class`] object. |
|
363 |
#' * `fixed_to_*()` returns a [`numeric`] vector of Gregorian years. |
|
364 |
#' @example inst/examples/ex-fixed.R |
|
365 |
#' @details |
|
366 |
#' The astronomical notation is used for Gregorian years (there *is* a year 0). |
|
367 |
#' @references |
|
368 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
369 |
#' The Ultimate Edition*. Cambridge University Press. |
|
370 |
#' \doi{10.1017/9781107415058}. |
|
371 |
#' @author N. Frerebeau |
|
372 |
#' @docType methods |
|
373 |
#' @family fixed date tools |
|
374 |
#' @name fixed_gregorian |
|
375 |
#' @rdname fixed_gregorian |
|
376 |
NULL |
|
377 | ||
378 |
#' *Rata Die* Conversion to and from Julian Years |
|
379 |
#' |
|
380 |
#' Convenient functions for conversion from and to *rata die*. |
|
381 |
#' @inheritParams fixed |
|
382 |
#' @inheritParams as_year |
|
383 |
#' @return |
|
384 |
#' * `fixed_from_julian()` returns a [`RataDie-class`] object. |
|
385 |
#' * `fixed_to_julian()` returns a [`numeric`] vector of Julian years. |
|
386 |
#' @example inst/examples/ex-fixed.R |
|
387 |
#' @references |
|
388 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
389 |
#' The Ultimate Edition*. Cambridge University Press. |
|
390 |
#' \doi{10.1017/9781107415058}. |
|
391 |
#' @author N. Frerebeau |
|
392 |
#' @docType methods |
|
393 |
#' @family fixed date tools |
|
394 |
#' @name fixed_julian |
|
395 |
#' @rdname fixed_julian |
|
396 |
NULL |
|
397 | ||
398 |
#' Date Conversion from *Rata Die* |
|
399 |
#' |
|
400 |
#' @param object A [`RataDie-class`] object (see [fixed()]). |
|
401 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
402 |
#' (see [calendar()]). |
|
403 |
#' @return |
|
404 |
#' A [`numeric`] vector of (decimal) years. |
|
405 |
#' @example inst/examples/ex-fixed.R |
|
406 |
#' @references |
|
407 |
#' Reingold, E. M. and Dershowitz, N. (2018). *Calendrical Calculations: |
|
408 |
#' The Ultimate Edition*. Cambridge University Press. |
|
409 |
#' \doi{10.1017/9781107415058}. |
|
410 |
#' @author N. Frerebeau |
|
411 |
#' @docType methods |
|
412 |
#' @family fixed date tools |
|
413 |
#' @aliases as_date-method |
|
414 |
setGeneric( |
|
415 |
name = "as_date", |
|
416 |
def = function(object, calendar) standardGeneric("as_date"), |
|
417 |
valueClass = "data.frame" |
|
418 |
) |
|
419 | ||
420 |
#' Converts a Date to a Decimal of its Year |
|
421 |
#' |
|
422 |
#' @param year A [`numeric`] vector of years. If `month` and `day` are missing, |
|
423 |
#' decimal years are expected. |
|
424 |
#' @param month A [`numeric`] vector of months. |
|
425 |
#' @param day A [`numeric`] vector of days. |
|
426 |
#' @param calendar A [`TimeScale-class`] object specifying the calendar of |
|
427 |
#' `year`, `month` and `day` (see [calendar()]). |
|
428 |
#' @return |
|
429 |
#' A [`numeric`] vector of (ecimal years. |
|
430 |
#' @example inst/examples/ex-fixed.R |
|
431 |
#' @author N. Frerebeau |
|
432 |
#' @docType methods |
|
433 |
#' @family fixed date tools |
|
434 |
#' @aliases as_decimal-method |
|
435 |
setGeneric( |
|
436 |
name = "as_decimal", |
|
437 | 4x |
def = function(year, month, day, calendar) standardGeneric("as_decimal") |
438 |
) |
|
439 | ||
440 |
#' Date Conversion to Character |
|
441 |
#' |
|
442 |
#' @param x A [`RataDie-class`] object. |
|
443 |
#' @param prefix A [`character`] string specifying the prefix. |
|
444 |
#' It should be one of "`a`", "`ka`", "`Ma`" or "`Ga`". |
|
445 |
#' If `TRUE`, a good guess for an appropriate format is made. |
|
446 |
#' @param label A [`logical`] scalar: should the label of the calendar be |
|
447 |
#' displayed? |
|
448 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
449 |
#' (see [calendar()]). |
|
450 |
#' @param ... Currently not used. |
|
451 |
#' @return |
|
452 |
#' A [`character`] vector representing the date. |
|
453 |
#' @example inst/examples/ex-fixed.R |
|
454 |
#' @author N. Frerebeau |
|
455 |
#' @docType methods |
|
456 |
#' @family fixed date tools |
|
457 |
#' @name format |
|
458 |
#' @rdname format |
|
459 |
NULL |
|
460 | ||
461 |
#' Pretty Breakpoints |
|
462 |
#' |
|
463 |
#' @param x A [`RataDie-class`] object. |
|
464 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
465 |
#' (see [calendar()]). |
|
466 |
#' @param ... Further parameters to be passed to [base::pretty()]. |
|
467 |
#' @details |
|
468 |
#' `pretty()` computes a vector of increasing numbers which are "pretty" in |
|
469 |
#' decimal notation of `calendar`. Pretty breakpoints are then converted to |
|
470 |
#' *rata die*. |
|
471 |
#' @return |
|
472 |
#' A [`RataDie-class`] object. |
|
473 |
#' @docType methods |
|
474 |
#' @family fixed date tools |
|
475 |
#' @name pretty |
|
476 |
#' @rdname pretty |
|
477 |
NULL |
|
478 | ||
479 |
#' Arithmetic Operators |
|
480 |
#' |
|
481 |
#' Operators performing arithmetic operations. |
|
482 |
#' @param e1,e2 A [`RataDie-class`] object or a [`numeric`] vector. |
|
483 |
#' @details |
|
484 |
#' *Rata die* will be converted to a plain `numeric` vector if a computation no |
|
485 |
#' longer makes sense in temporal terms. |
|
486 |
#' @return |
|
487 |
#' A [`logical`] vector. |
|
488 |
#' @example inst/examples/ex-arith.R |
|
489 |
#' @author N. Frerebeau |
|
490 |
#' @docType methods |
|
491 |
#' @family fixed date tools |
|
492 |
#' @name arithmetic |
|
493 |
#' @rdname arithmetic |
|
494 |
NULL |
|
495 | ||
496 |
# Time Series ================================================================== |
|
497 |
#' Create Time Series |
|
498 |
#' |
|
499 |
#' @param object A [`numeric`] `vector`, `matrix` or `array` of the observed |
|
500 |
#' time-series values. A [`data.frame`] will be coerced to a `numeric` `matrix` |
|
501 |
#' via [data.matrix()]. |
|
502 |
#' @param time A [`numeric`] vector of (decimal) years or a [`RataDie-class`] |
|
503 |
#' object (see [fixed()]). |
|
504 |
#' @param calendar A [`TimeScale-class`] object specifying the calendar of |
|
505 |
#' `time` (see [calendar()]). If missing, `time` must be a [`RataDie-class`] |
|
506 |
#' object. |
|
507 |
#' @param scale A length-one [`numeric`] vector specifying the number of years |
|
508 |
#' represented by one unit. It should be a power of 10 (i.e. 1000 means ka). |
|
509 |
#' @param names A [`character`] string specifying the names of the time |
|
510 |
#' series. |
|
511 |
#' @param ... Currently not used. |
|
512 |
#' @details |
|
513 |
#' Data will be sorted in chronological order. |
|
514 |
#' @return |
|
515 |
#' A [`TimeSeries-class`] object. |
|
516 |
#' @example inst/examples/ex-series.R |
|
517 |
#' @author N. Frerebeau |
|
518 |
#' @docType methods |
|
519 |
#' @family time series |
|
520 |
#' @aliases series-method |
|
521 |
setGeneric( |
|
522 |
name = "series", |
|
523 |
def = function(object, time, calendar, ...) standardGeneric("series"), |
|
524 |
valueClass = "TimeSeries" |
|
525 |
) |
|
526 | ||
527 |
# Time Intervals =============================================================== |
|
528 |
#' Create Time Intervals |
|
529 |
#' |
|
530 |
#' An Interval is elapsed time in seconds between two specific years. |
|
531 |
#' @param start A [`numeric`] vector of (decimal) years or a [`RataDie-class`] |
|
532 |
#' object (see [fixed()]) giving the beginning of the time intervals. |
|
533 |
#' @param end A [`numeric`] vector of (decimal) years or a [`RataDie-class`] |
|
534 |
#' object (see [fixed()]) giving the end of the time intervals. |
|
535 |
#' @param calendar A [`TimeScale-class`] object specifying the calendar of |
|
536 |
#' `time` (see [calendar()]). If missing, `time` must be a [`RataDie-class`] |
|
537 |
#' object. |
|
538 |
#' @param scale A length-one [`numeric`] vector specifying the number of years |
|
539 |
#' represented by one unit. It should be a power of 10 (i.e. 1000 means ka). |
|
540 |
#' @param names A [`character`] string specifying the names of the time |
|
541 |
#' series. |
|
542 |
#' @param ... Currently not used. |
|
543 |
#' @return |
|
544 |
#' A [`TimeIntervals-class`] object. |
|
545 |
#' @example inst/examples/ex-intervals.R |
|
546 |
#' @author N. Frerebeau |
|
547 |
#' @docType methods |
|
548 |
#' @family time intervals |
|
549 |
#' @aliases intervals-method |
|
550 |
setGeneric( |
|
551 |
name = "intervals", |
|
552 |
def = function(start, end, calendar, ...) standardGeneric("intervals"), |
|
553 |
valueClass = "TimeIntervals" |
|
554 |
) |
|
555 | ||
556 |
# Chronological Reasoning ====================================================== |
|
557 |
#' Time Overlap |
|
558 |
#' |
|
559 |
#' Computes the length of overlap of time intervals. |
|
560 |
#' @param x A [`TimeIntervals-class`] object. |
|
561 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
562 |
#' (see [calendar()]). If `NULL` (the default), *rata die* are returned. |
|
563 |
#' @param aggregate A [`logical`] scalar: should disjoint intervals referring to |
|
564 |
#' the same event be aggregated? |
|
565 |
#' @param ... Currently not used. |
|
566 |
#' @details |
|
567 |
#' The overlap of two time intervals is a difference between the minimum value |
|
568 |
#' of the two upper boundaries and the maximum value of the two lower |
|
569 |
#' boundaries, plus 1. |
|
570 |
#' @return |
|
571 |
#' A symmetric `numeric` [`matrix`] of years. |
|
572 |
#' @example inst/examples/ex-intervals.R |
|
573 |
#' @author N. Frerebeau |
|
574 |
#' @docType methods |
|
575 |
#' @family chronological reasoning tools |
|
576 |
#' @aliases overlap-method |
|
577 |
setGeneric( |
|
578 |
name = "overlap", |
|
579 | 3x |
def = function(x, ...) standardGeneric("overlap") |
580 |
) |
|
581 | ||
582 |
# Tools ======================================================================== |
|
583 |
#' Terminal Times |
|
584 |
#' |
|
585 |
#' Get the times the first and last observations were taken. |
|
586 |
#' @param x A [`TimeSeries-class`] object. |
|
587 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
588 |
#' (see [calendar()]). If `NULL` (the default), *rata die* are returned. |
|
589 |
#' @param ... Currently not used. |
|
590 |
#' @return |
|
591 |
#' A [`numeric`] vector of decimal years (if `calendar` is not `NULL`). |
|
592 |
#' @example inst/examples/ex-series.R |
|
593 |
#' @author N. Frerebeau |
|
594 |
#' @docType methods |
|
595 |
#' @family tools |
|
596 |
#' @aliases start-method end-method |
|
597 |
#' @name start |
|
598 |
#' @rdname start |
|
599 |
NULL |
|
600 | ||
601 |
#' Sampling Times |
|
602 |
#' |
|
603 |
#' Get the sampling times: |
|
604 |
#' * `time()` creates the vector of times at which a time series was sampled. |
|
605 |
#' * `frequency()` returns the mean number of samples per unit time. |
|
606 |
#' @param x A [`TimeSeries-class`] object. |
|
607 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
608 |
#' (see [calendar()]). If `NULL` (the default), *rata die* are returned. |
|
609 |
#' @param ... Currently not used. |
|
610 |
#' @return |
|
611 |
#' A [`numeric`] vector of decimal years (if `calendar` is not `NULL`). |
|
612 |
#' @example inst/examples/ex-series.R |
|
613 |
#' @author N. Frerebeau |
|
614 |
#' @docType methods |
|
615 |
#' @family tools |
|
616 |
#' @aliases time-method frequency-method |
|
617 |
#' @name time |
|
618 |
#' @rdname time |
|
619 |
NULL |
|
620 | ||
621 |
#' Time Windows |
|
622 |
#' |
|
623 |
#' Extracts the subset of the object `x` observed between the times `start` and |
|
624 |
#' `end` (expressed in *rata die*). |
|
625 |
#' @param x A [`TimeSeries-class`] object. |
|
626 |
#' @param start A length-one [`numeric`] vector specifying the start time of the |
|
627 |
#' period of interest. |
|
628 |
#' @param end A length-one [`numeric`] vector specifying the end time of the |
|
629 |
#' period of interest. |
|
630 |
#' @param ... Currently not used. |
|
631 |
#' @return |
|
632 |
#' A [`TimeSeries-class`] object. |
|
633 |
#' @example inst/examples/ex-window.R |
|
634 |
#' @author N. Frerebeau |
|
635 |
#' @docType methods |
|
636 |
#' @family tools |
|
637 |
#' @aliases window-method |
|
638 |
#' @name window |
|
639 |
#' @rdname window |
|
640 |
NULL |
|
641 | ||
642 |
#' Duration |
|
643 |
#' |
|
644 |
#' Get the duration of time series or intervals. |
|
645 |
#' @param x A [`TimeSeries-class`] or a [`TimeIntervals-class`] object. |
|
646 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
647 |
#' (see [calendar()]). If `NULL` (the default), *rata die* are returned. |
|
648 |
#' @param ... Currently not used. |
|
649 |
#' @return |
|
650 |
#' A [`numeric`] vector of years. |
|
651 |
#' @example inst/examples/ex-duration.R |
|
652 |
#' @author N. Frerebeau |
|
653 |
#' @docType methods |
|
654 |
#' @family tools |
|
655 |
#' @aliases span-method |
|
656 |
setGeneric( |
|
657 |
name = "span", |
|
658 | 8x |
def = function(x, ...) standardGeneric("span") |
659 |
) |
|
660 | ||
661 |
# Plot ========================================================================= |
|
662 |
#' Plot Time Series and Time Intervals |
|
663 |
#' |
|
664 |
#' @param x A [`TimeSeries-class`] or a [`TimeIntervals-class`] object. |
|
665 |
#' @param facet A [`character`] string specifying whether the series should be |
|
666 |
#' plotted separately (with a common time axis) or on a single plot? |
|
667 |
#' It must be one of "`multiple`" or "`single`". Any unambiguous substring can |
|
668 |
#' be given. |
|
669 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
670 |
#' (see [calendar()]). |
|
671 |
#' @param groups A [`character`] vector specifying the group each interval |
|
672 |
#' belongs to. |
|
673 |
#' @param sort A [`logical`] scalar: should the data be sorted in chronological |
|
674 |
#' order? |
|
675 |
#' @param decreasing A [`logical`] scalar: should the sort order be decreasing? |
|
676 |
#' Only used if `sort` is `TRUE`. |
|
677 |
#' @param panel A [`function`] in the form `function(x, y, ...)` |
|
678 |
#' which gives the action to be carried out in each panel of the display. |
|
679 |
#' The default is [graphics::lines()]. |
|
680 |
#' @param flip A [`logical`] scalar: should the y-axis (ticks and numbering) be |
|
681 |
#' flipped from side 2 (left) to 4 (right) from series to series when `facet` |
|
682 |
#' is "`multiple`"? |
|
683 |
#' @param ncol An [`integer`] specifying the number of columns to use when |
|
684 |
#' `facet` is "`multiple`". Defaults to 1 for up to 4 series, otherwise to 2. |
|
685 |
#' @param xlab,ylab A [`character`] vector giving the x and y axis labels. |
|
686 |
#' @param main A [`character`] string giving a main title for the plot. |
|
687 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
688 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
689 |
#' and y axis labels) appear on the plot? |
|
690 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
691 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
692 |
#' plot? |
|
693 |
#' @param panel.first An `expression` to be evaluated after the plot axes are |
|
694 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
695 |
#' background grids. |
|
696 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
697 |
#' place but before the axes, title and box are added. |
|
698 |
#' @param ... Further parameters to be passed to `panel` |
|
699 |
#' (e.g. [graphical parameters][graphics::par]). |
|
700 |
#' @return |
|
701 |
#' `plot()` is called for its side-effects: it results in a graphic |
|
702 |
#' being displayed. Invisibly returns `x`. |
|
703 |
#' @example inst/examples/ex-plot.R |
|
704 |
#' @seealso [graphics::plot()] |
|
705 |
#' @author N. Frerebeau |
|
706 |
#' @docType methods |
|
707 |
#' @family plotting tools |
|
708 |
#' @name plot |
|
709 |
#' @rdname plot |
|
710 |
NULL |
|
711 | ||
712 |
#' Heat Map |
|
713 |
#' |
|
714 |
#' @param x A [`TimeSeries-class`] object. |
|
715 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
716 |
#' (see [calendar()]). |
|
717 |
#' @param k An [`integer`] specifying the slice of `x` along the third |
|
718 |
#' dimension to be plotted. |
|
719 |
#' @param ... Further parameters to be passed to [graphics::image()]. |
|
720 |
#' @return |
|
721 |
#' `image()` is called for its side-effects: it results in a graphic |
|
722 |
#' being displayed. Invisibly returns `x`. |
|
723 |
#' @example inst/examples/ex-image.R |
|
724 |
#' @seealso [graphics::image()] |
|
725 |
#' @author N. Frerebeau |
|
726 |
#' @docType methods |
|
727 |
#' @family plotting tools |
|
728 |
#' @name image |
|
729 |
#' @rdname image |
|
730 |
NULL |
|
731 | ||
732 |
#' Time Series Plotting Functions |
|
733 |
#' |
|
734 |
#' @param side An [`integer`] specifying which side of the plot the axis is to |
|
735 |
#' be drawn on. The axis is placed as follows: 1=below, 2=left, 3=above and |
|
736 |
#' 4=right. |
|
737 |
#' @param at A [`numeric`] vector giving the points at which tick-marks are to |
|
738 |
#' be drawn. If `NULL`, tickmark locations are computed. |
|
739 |
#' @param format A [`character`] string specifying the prefix. |
|
740 |
#' It should be one of "`a`", "`ka`", "`Ma`" or "`Ga`". |
|
741 |
#' If `TRUE`, a good guess for an appropriate format is made. |
|
742 |
#' @param labels A [`logical`] scalar specifying whether annotations are to be |
|
743 |
#' made at the tickmarks, or a vector of [`character`] strings to be placed at |
|
744 |
#' the tickpoints. |
|
745 |
#' @param calendar A [`TimeScale-class`] object specifying the target calendar |
|
746 |
#' (see [calendar()]). |
|
747 |
#' @param current_calendar A [`TimeScale-class`] object specifying the calendar |
|
748 |
#' used by the last call to [plot()]. |
|
749 |
#' @param ... Further parameters to be passed to [graphics::axis()]. |
|
750 |
#' (e.g. [graphical parameters][graphics::par]). |
|
751 |
#' @return |
|
752 |
#' `year_axis()` is called it for its side-effects. |
|
753 |
#' @example inst/examples/ex-axis.R |
|
754 |
#' @author N. Frerebeau |
|
755 |
#' @docType methods |
|
756 |
#' @family plotting tools |
|
757 |
#' @name year_axis |
|
758 |
#' @rdname year_axis |
|
759 |
NULL |
1 |
# GREGORIAN CALENDAR |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Fixed from Gregorian ========================================================= |
|
6 |
#' @export |
|
7 |
#' @rdname fixed |
|
8 |
#' @aliases fixed,numeric,missing,missing,GregorianCalendar-method |
|
9 |
setMethod( |
|
10 |
f = "fixed", |
|
11 |
signature = c(year = "numeric", month = "missing", day = "missing", calendar = "GregorianCalendar"), |
|
12 |
definition = function(year, calendar, scale = 1) { |
|
13 |
## Rescale to years (if not already) |
|
14 | 62x |
year <- year * scale |
15 | ||
16 | 62x |
rd <- fixed(year, 01, 01, calendar = calendar) |
17 | ||
18 | 62x |
is_leap <- which(is_gregorian_leap_year(year)) |
19 | 62x |
rd[is_leap] <- ceiling(rd[is_leap]) # WHY ??? |
20 | 62x |
rd |
21 |
} |
|
22 |
) |
|
23 | ||
24 |
#' @export |
|
25 |
#' @rdname fixed |
|
26 |
#' @aliases fixed,numeric,numeric,numeric,GregorianCalendar-method |
|
27 |
setMethod( |
|
28 |
f = "fixed", |
|
29 |
signature = c(year = "numeric", month = "numeric", day = "numeric", calendar = "GregorianCalendar"), |
|
30 |
definition = function(year, month, day, calendar) { |
|
31 |
## Recycle |
|
32 | 348x |
n <- length(year) |
33 | 348x |
if (n > 1) { |
34 | 262x |
if (length(month) == 1) month <- rep(month, n) |
35 | 264x |
if (length(day) == 1) day <- rep(day, n) |
36 |
} |
|
37 | ||
38 |
## Switch origin |
|
39 | 348x |
year <- (year - calendar_epoch(calendar)) * calendar_direction(calendar) |
40 | ||
41 |
## Correct for 28- or 29-day Feb |
|
42 | 348x |
correction <- rep(-2, length(year)) |
43 | 348x |
correction[is_gregorian_leap_year(year)] <- -1 |
44 | 348x |
correction[month <= 2] <- 0 |
45 | ||
46 | 348x |
rd <- calendar_fixed(calendar) - 1 + # Days before start of calendar |
47 | 348x |
365 * (year - 1) + # Ordinary days since epoch |
48 | 348x |
(year - 1) %/% 4 - # Julian leap days since epoch minus... |
49 | 348x |
(year - 1) %/% 100 + # ...century years since epoch plus... |
50 | 348x |
(year - 1) %/% 400 + # ...years since epoch divisible by 400 |
51 | 348x |
(367 * month - 362) %/% 12 + # Days in prior months this year assuming 30-day Feb |
52 | 348x |
correction + # Correct for 28- or 29-day Feb |
53 | 348x |
day # Days so far this month. |
54 | ||
55 |
## Fix infinite values |
|
56 | 348x |
rd[is.infinite(year)] <- year[is.infinite(year)] |
57 | ||
58 | 348x |
.RataDie(rd) |
59 |
} |
|
60 |
) |
|
61 |
# Gregorian from fixed ========================================================= |
|
62 |
#' @export |
|
63 |
#' @rdname as_year |
|
64 |
#' @aliases as_year,numeric,GregorianCalendar-method |
|
65 |
setMethod( |
|
66 |
f = "as_year", |
|
67 |
signature = c(object = "numeric", calendar = "GregorianCalendar"), |
|
68 |
definition = function(object, calendar, decimal = TRUE, ...) { |
|
69 | 142x |
d0 <- object - calendar_fixed(calendar) |
70 | 142x |
n400 <- d0 %/% 146097 |
71 | 142x |
d1 <- d0 %% 146097 |
72 | 142x |
n100 <- d1 %/% 36524 |
73 | 142x |
d2 <- d1 %% 36524 |
74 | 142x |
n4 <- d2 %/% 1461 |
75 | 142x |
d3 <- d2 %% 1461 |
76 | 142x |
n1 <- d3 %/% 365 |
77 | ||
78 | 142x |
year <- 400 * n400 + 100 * n100 + 4 * n4 + n1 |
79 | 142x |
year <- ifelse(n100 == 4 | n1 == 4, year, year + 1) |
80 | ||
81 |
## Shift origin |
|
82 | 142x |
year <- (year - calendar_epoch(calendar)) * calendar_direction(calendar) |
83 | ||
84 | 142x |
if (isTRUE(decimal)) { |
85 |
## Year length in days |
|
86 | 116x |
start <- fixed(year, 01, 01, calendar = calendar) |
87 | 116x |
end <- fixed(year, 12, 31, calendar = calendar) |
88 | 116x |
total <- end - start + 1 |
89 | ||
90 |
## Elapsed time |
|
91 | 116x |
sofar <- object - start |
92 | ||
93 | 116x |
year <- year + sofar / total |
94 |
} |
|
95 | ||
96 |
## Fix infinite values |
|
97 | 142x |
year[is.infinite(object)] <- object[is.infinite(object)] |
98 | ||
99 | 142x |
year |
100 |
} |
|
101 |
) |
|
102 | ||
103 |
#' @export |
|
104 |
#' @rdname as_date |
|
105 |
#' @aliases as_date,numeric,GregorianCalendar-method |
|
106 |
setMethod( |
|
107 |
f = "as_date", |
|
108 |
signature = c(object = "numeric", calendar = "GregorianCalendar"), |
|
109 |
definition = function(object, calendar) { |
|
110 | 9x |
year <- as_year(object, calendar = calendar, decimal = FALSE) |
111 | 9x |
prior_days <- object - fixed(year, 01, 01, calendar = calendar) |
112 | ||
113 | 9x |
correction <- rep(2, length(object)) |
114 | 9x |
correction[object < fixed(year, 03, 01, calendar = calendar)] <- 0 |
115 | 9x |
correction[is_gregorian_leap_year(year)] <- 1 |
116 | ||
117 | 9x |
month <- (12 * (prior_days + correction) + 373) %/% 367 |
118 | 9x |
day <- object - fixed(year, month, 01, calendar = calendar) + 1 |
119 | ||
120 | 9x |
data.frame( |
121 | 9x |
year = as.numeric(year), |
122 | 9x |
month = as.numeric(month), |
123 | 9x |
day = as.numeric(day) |
124 |
) |
|
125 |
} |
|
126 |
) |
|
127 | ||
128 |
# Era ========================================================================== |
|
129 |
#' @export |
|
130 |
#' @rdname fixed_gregorian |
|
131 |
fixed_from_BP <- function(year, month, day) { |
|
132 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = BP()) |
133 | ! |
else fixed(year, month, day, calendar = BP()) |
134 |
} |
|
135 |
#' @export |
|
136 |
#' @rdname fixed_gregorian |
|
137 |
fixed_to_BP <- function(object) { |
|
138 | 1x |
as_year(object, calendar = BP(), decimal = TRUE) |
139 |
} |
|
140 | ||
141 |
#' @export |
|
142 |
#' @rdname fixed_gregorian |
|
143 |
fixed_from_BC <- function(year, month, day) { |
|
144 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = BC()) |
145 | ! |
else fixed(year, month, day, calendar = BC()) |
146 |
} |
|
147 |
#' @export |
|
148 |
#' @rdname fixed_gregorian |
|
149 |
fixed_to_BC <- function(object) { |
|
150 | 1x |
as_year(object, calendar = BC(), decimal = TRUE) |
151 |
} |
|
152 | ||
153 |
#' @export |
|
154 |
#' @rdname fixed_gregorian |
|
155 |
fixed_from_BCE <- function(year, month, day) { |
|
156 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = BCE()) |
157 | ! |
else fixed(year, month, day, calendar = BCE()) |
158 |
} |
|
159 |
#' @export |
|
160 |
#' @rdname fixed_gregorian |
|
161 |
fixed_to_BCE <- function(object) { |
|
162 | 2x |
as_year(object, calendar = BCE(), decimal = TRUE) |
163 |
} |
|
164 | ||
165 |
#' @export |
|
166 |
#' @rdname fixed_gregorian |
|
167 |
fixed_from_AD <- function(year, month, day) { |
|
168 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = AD()) |
169 | 15x |
else fixed(year, month, day, calendar = AD()) |
170 |
} |
|
171 |
#' @export |
|
172 |
#' @rdname fixed_gregorian |
|
173 |
fixed_to_AD <- function(object) { |
|
174 | 1x |
as_year(object, calendar = AD(), decimal = TRUE) |
175 |
} |
|
176 | ||
177 |
#' @export |
|
178 |
#' @rdname fixed_gregorian |
|
179 |
fixed_from_CE <- function(year, month, day) { |
|
180 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = CE()) |
181 | ! |
else fixed(year, month, day, calendar = CE()) |
182 |
} |
|
183 |
#' @export |
|
184 |
#' @rdname fixed_gregorian |
|
185 |
fixed_to_CE <- function(object) { |
|
186 | 1x |
as_year(object, calendar = CE(), decimal = TRUE) |
187 |
} |
|
188 | ||
189 |
#' @export |
|
190 |
#' @rdname fixed_gregorian |
|
191 |
fixed_from_b2k <- function(year, month, day) { |
|
192 | ! |
if (missing(month) || missing(day)) fixed(year, calendar = b2k()) |
193 | ! |
else fixed(year, month, day, calendar = b2k()) |
194 |
} |
|
195 |
#' @export |
|
196 |
#' @rdname fixed_gregorian |
|
197 |
fixed_to_b2k <- function(object) { |
|
198 | 1x |
as_year(object, calendar = b2k(), decimal = TRUE) |
199 |
} |
1 |
# OPERATORS |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# "+", "-", "*", "^", "%%", "%/%", "/" |
|
6 |
#' @export |
|
7 |
#' @rdname arithmetic |
|
8 |
#' @aliases Arith,RataDie,RataDie-method |
|
9 |
setMethod( |
|
10 |
f = "Arith", |
|
11 |
signature = c(e1 = "RataDie", e2 = "RataDie"), |
|
12 |
definition = function(e1, e2) { |
|
13 | 394x |
z <- methods::callGeneric(e1@.Data, e2@.Data) |
14 |
switch( |
|
15 | 394x |
.Generic[[1]], |
16 | 2x |
`+` = return(.RataDie(z)), |
17 | 263x |
`-` = return(.RataDie(z)), |
18 | 129x |
return(z) |
19 |
) |
|
20 |
} |
|
21 |
) |
|
22 | ||
23 |
#' @export |
|
24 |
#' @rdname arithmetic |
|
25 |
#' @aliases Arith,numeric,RataDie-method |
|
26 |
setMethod( |
|
27 |
f = "Arith", |
|
28 |
signature = c(e1 = "numeric", e2 = "RataDie"), |
|
29 |
definition = function(e1, e2) { |
|
30 | 54x |
z <- methods::callGeneric(e1, e2@.Data) |
31 |
switch( |
|
32 | 54x |
.Generic[[1]], |
33 | 1x |
`+` = return(.RataDie(z)), |
34 | 19x |
`-` = return(.RataDie(z)), |
35 | 33x |
`*` = return(.RataDie(z)), |
36 | 1x |
return(z) |
37 |
) |
|
38 |
} |
|
39 |
) |
|
40 | ||
41 |
#' @export |
|
42 |
#' @rdname arithmetic |
|
43 |
#' @aliases Arith,RataDie,numeric-method |
|
44 |
setMethod( |
|
45 |
f = "Arith", |
|
46 |
signature = c(e1 = "RataDie", e2 = "numeric"), |
|
47 |
definition = function(e1, e2) { |
|
48 | 615x |
z <- methods::callGeneric(e1@.Data, e2) |
49 |
switch( |
|
50 | 615x |
.Generic[[1]], |
51 | 186x |
`+` = return(.RataDie(z)), |
52 | 146x |
`-` = return(.RataDie(z)), |
53 | 1x |
`*` = return(.RataDie(z)), |
54 | 1x |
`/` = return(.RataDie(z)), |
55 | 281x |
return(z) |
56 |
) |
|
57 |
} |
|
58 |
) |
1 |
# FORMAT |
|
2 | ||
3 |
# Format ======================================================================= |
|
4 |
#' @export |
|
5 |
#' @method format TimeScale |
|
6 |
format.TimeScale <- function(x, ...) { |
|
7 | 19x |
msg <- sprintf("%s %s", calendar_unit(x), calendar_label(x)) |
8 | 19x |
trimws(msg) |
9 |
} |
|
10 | ||
11 |
#' @export |
|
12 |
#' @rdname format |
|
13 |
setMethod("format", "TimeScale", format.TimeScale) |
|
14 | ||
15 |
#' @export |
|
16 |
#' @method format RataDie |
|
17 |
format.RataDie <- function(x, prefix = c("a", "ka", "Ma", "Ga"), label = TRUE, |
|
18 |
calendar = get_calendar(), ...) { |
|
19 | ! |
if (is.null(calendar)) return(format(as.numeric(x))) |
20 | 24x |
y <- as_year(x, calendar = calendar) |
21 | ||
22 |
## Scale |
|
23 | 24x |
if (isTRUE(prefix)) { |
24 | 12x |
power <- 10^floor(log10(abs(mean(y, na.rm = TRUE)))) |
25 | 12x |
if (prefix < 10^4) prefix <- "a" |
26 | 1x |
if (power >= 10^4 && power < 10^6) prefix <- "ka" |
27 | ! |
if (power >= 10^6 && power < 10^9) prefix <- "Ma" |
28 | ! |
if (power >= 10^9) prefix <- "Ga" |
29 |
} |
|
30 | 24x |
prefix <- match.arg(prefix, several.ok = FALSE) |
31 | 24x |
power <- switch (prefix, ka = 10^3, Ma = 10^6, Ga = 10^9, 1) |
32 | ||
33 | 24x |
prefix <- if (power > 1) sprintf(" %s", prefix) else "" |
34 | 24x |
label <- if (isTRUE(label)) sprintf(" %s", calendar_label(calendar)) else "" |
35 | 24x |
trimws(sprintf("%g%s%s", y / power, prefix, label)) |
36 |
} |
|
37 | ||
38 |
#' @export |
|
39 |
#' @rdname format |
|
40 |
setMethod("format", "RataDie", format.RataDie) |
1 |
# CLASSES VALIDATION |
|
2 |
#' @include AllClasses.R |
|
3 |
NULL |
|
4 | ||
5 |
# TimeScale ===================================================================== |
|
6 |
setValidity( |
|
7 |
Class = "TimeScale", |
|
8 |
method = function(object) { |
|
9 |
## Get data |
|
10 |
label <- object@label |
|
11 |
name <- object@name |
|
12 |
epoch <- object@epoch |
|
13 |
fixed <- object@fixed |
|
14 |
direction <- object@direction |
|
15 |
year <- object@year |
|
16 | ||
17 |
## Validate |
|
18 |
cnd <- list( |
|
19 |
arkhe::validate(arkhe::assert_length(label, 1)), |
|
20 |
arkhe::validate(arkhe::assert_length(name, 1)), |
|
21 |
arkhe::validate(arkhe::assert_length(epoch, 1)), |
|
22 |
arkhe::validate(arkhe::assert_length(fixed, 1)), |
|
23 |
arkhe::validate(arkhe::assert_length(direction, 1)), |
|
24 |
arkhe::validate(arkhe::assert_length(year, 1)) |
|
25 |
) |
|
26 | ||
27 |
## Return conditions, if any |
|
28 |
arkhe::check_class(object, cnd) |
|
29 |
} |
|
30 |
) |
|
31 | ||
32 |
# Time Series ================================================================== |
|
33 |
# setValidity( |
|
34 |
# Class = "RataDie", |
|
35 |
# method = function(object) { |
|
36 |
# |
|
37 |
# } |
|
38 |
# ) |
|
39 | ||
40 |
setValidity( |
|
41 |
Class = "TimeSeries", |
|
42 |
method = function(object) { |
|
43 |
## Get data |
|
44 |
time <- object@.Time |
|
45 |
m <- nrow(object) |
|
46 | ||
47 |
## Validate |
|
48 |
cnd <- list( |
|
49 |
arkhe::validate(arkhe::assert_type(object, "numeric")), |
|
50 |
arkhe::validate(arkhe::assert_length(time, m)), |
|
51 |
arkhe::validate(arkhe::assert_infinite(time)) |
|
52 |
) |
|
53 | ||
54 |
## Return conditions, if any |
|
55 |
arkhe::check_class(object, cnd) |
|
56 |
} |
|
57 |
) |
|
58 | ||
59 |
setValidity( |
|
60 |
Class = "TimeIntervals", |
|
61 |
method = function(object) { |
|
62 |
## Get data |
|
63 |
names <- object@.Id |
|
64 |
start <- object@.Start |
|
65 |
end <- object@.End |
|
66 |
m <- length(start) |
|
67 | ||
68 |
## Validate |
|
69 |
cnd <- list( |
|
70 |
arkhe::validate(arkhe::assert_length(names, m)), |
|
71 |
arkhe::validate(arkhe::assert_length(end, m)), |
|
72 |
arkhe::validate(arkhe::assert_missing(names)), |
|
73 |
arkhe::validate(arkhe::assert_missing(start)), |
|
74 |
arkhe::validate(arkhe::assert_missing(end)), |
|
75 |
arkhe::validate(assert_ordered(start, end)) |
|
76 |
) |
|
77 | ||
78 |
## Return conditions, if any |
|
79 |
arkhe::check_class(object, cnd) |
|
80 |
} |
|
81 |
) |
|
82 | ||
83 |
assert_ordered <- function(start, end) { |
|
84 | 5x |
arg_start <- deparse(substitute(start)) |
85 | 5x |
arg_end <- deparse(substitute(end)) |
86 | 5x |
if (any(start > end)) { |
87 | 1x |
msg <- sprintf(tr_("%s is later than %s."), sQuote(arg_start), sQuote(arg_end)) |
88 | 1x |
stop(msg) |
89 |
} |
|
90 | 4x |
invisible(NULL) |
91 |
} |
1 |
# AXIS |
|
2 | ||
3 |
# Pretty ======================================================================= |
|
4 |
#' @export |
|
5 |
#' @method pretty RataDie |
|
6 |
pretty.RataDie <- function(x, calendar = get_calendar(), ...) { |
|
7 | ! |
if (is.null(calendar)) return(pretty(as.numeric(x), ...)) |
8 | ||
9 | 17x |
x <- as_year(x, calendar = calendar, decimal = FALSE) |
10 | 17x |
x <- pretty(x, ...) |
11 | 2x |
if (methods::is(calendar, "JulianCalendar")) x[x == 0] <- 1 |
12 | 17x |
fixed(year = x, calendar = calendar) |
13 |
} |
|
14 | ||
15 |
#' @export |
|
16 |
#' @rdname pretty |
|
17 |
setMethod("pretty", "RataDie", pretty.RataDie) |
|
18 | ||
19 |
# Axis ========================================================================= |
|
20 |
#' @export |
|
21 |
#' @rdname year_axis |
|
22 |
year_axis <- function(side, at = NULL, format = c("a", "ka", "Ma", "Ga"), |
|
23 |
labels = TRUE, calendar = get_calendar("current"), |
|
24 |
current_calendar = get_calendar("current"), |
|
25 |
...) { |
|
26 | 19x |
no_at <- missing(at) || is.null(at) || !is.numeric(at) |
27 | 19x |
if (no_at) at <- graphics::axTicks(side = side) |
28 | ||
29 | 19x |
if (!is.logical(labels)) { |
30 | ! |
labels <- labels[keep] |
31 | 19x |
} else if (isTRUE(labels)) { |
32 |
## If last_calendar is NULL, then the last plot was expressed in rata die |
|
33 | 19x |
if (is.null(current_calendar)) { |
34 | 3x |
at <- as_fixed(at) |
35 |
} else { |
|
36 | 2x |
if (methods::is(calendar, "JulianCalendar")) at[at == 0] <- 1 |
37 | 16x |
at <- fixed(at, calendar = current_calendar) |
38 |
} |
|
39 | 19x |
if (!is.null(calendar)) { |
40 | 16x |
at <- pretty(at, calendar = calendar) |
41 | 16x |
labels <- format(at, prefix = format, label = FALSE, calendar = calendar) |
42 | 16x |
if (!is.null(current_calendar)) at <- as_year(at, calendar = current_calendar) |
43 |
} |
|
44 | ! |
} else if (isFALSE(labels)) { |
45 | ! |
labels <- rep("", length(at)) |
46 |
} |
|
47 | ||
48 | 19x |
graphics::axis(side, at = as.numeric(at), labels = labels, ...) |
49 |
} |
1 |
# TIME INTERVALS |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname intervals |
|
7 |
#' @aliases intervals,RataDie,RataDie,missing-method |
|
8 |
setMethod( |
|
9 |
f = "intervals", |
|
10 |
signature = c(start = "RataDie", end = "RataDie", calendar = "missing"), |
|
11 |
definition = function(start, end, names = NULL) { |
|
12 | 5x |
n <- length(start) |
13 | 5x |
arkhe::assert_length(end, n) |
14 | ||
15 |
## Set the names |
|
16 | 5x |
if (is.null(names)) { |
17 | 5x |
names <- paste0("I", seq_len(n)) |
18 |
} else { |
|
19 | ! |
names <- as.character(names) |
20 |
} |
|
21 | 5x |
arkhe::assert_length(names, n) |
22 | ||
23 | 5x |
.TimeIntervals(.Id = names, .Start = start, .End = end) |
24 |
} |
|
25 |
) |
|
26 | ||
27 |
#' @export |
|
28 |
#' @rdname intervals |
|
29 |
#' @aliases intervals,numeric,numeric,TimeScale-method |
|
30 |
setMethod( |
|
31 |
f = "intervals", |
|
32 |
signature = c(start = "numeric", end = "numeric", calendar = "TimeScale"), |
|
33 |
definition = function(start, end, calendar, scale = 1, names = NULL) { |
|
34 |
## Start |
|
35 | 4x |
if (methods::is(start, "RataDie")) { |
36 | 1x |
msg <- "%s is already expressed in rata die: %s is ignored." |
37 | 1x |
warning(sprintf(msg, sQuote("start"), sQuote("calendar")), call. = FALSE) |
38 |
} else { |
|
39 | 3x |
start <- fixed(start, calendar = calendar, scale = scale) |
40 |
} |
|
41 | ||
42 |
## End |
|
43 | 4x |
if (methods::is(end, "RataDie")) { |
44 | 1x |
msg <- tr_("%s is already expressed in rata die: %s is ignored.") |
45 | 1x |
warning(sprintf(msg, sQuote("end"), sQuote("calendar")), call. = FALSE) |
46 |
} else { |
|
47 | 3x |
end <- fixed(end, calendar = calendar, scale = scale) |
48 |
} |
|
49 | ||
50 | 4x |
names <- names %||% names(start) %||% names(end) |
51 | 4x |
methods::callGeneric(start = start, end = end, names = names) |
52 |
} |
|
53 |
) |
1 |
# HELPERS |
|
2 | ||
3 |
## https://michaelchirico.github.io/potools/articles/developers.html |
|
4 |
tr_ <- function(...) { |
|
5 | 317x |
enc2utf8(gettext(paste0(...), domain = "R-aion")) |
6 |
} |
|
7 | ||
8 |
make_par <- function(params, x, n = 1) { |
|
9 | 321x |
p <- params[[x]] %||% graphics::par()[[x]] |
10 | 12x |
if (length(p) == 1 && n > 1) p <- rep(p, length.out = n) |
11 | 321x |
p |
12 |
} |
|
13 | ||
14 |
#' Plotting Dimensions of Character Strings |
|
15 |
#' |
|
16 |
#' Convert string length in inch to number of (margin) lines. |
|
17 |
#' @param x A [`character`] vector of string whose length is to be calculated. |
|
18 |
#' @param ... Further parameter to be passed to [graphics::strwidth()]`, such as |
|
19 |
#' `cex`. |
|
20 |
#' @return |
|
21 |
#' A [`numeric`] vector (maximum string width in units of margin lines). |
|
22 |
#' @note For internal use only. |
|
23 |
#' @family graphic tools |
|
24 |
#' @keywords internal |
|
25 |
#' @noRd |
|
26 |
inch2line <- function(x, ...) { |
|
27 | 1x |
(max(graphics::strwidth(x, units = "inch", ...)) / |
28 | 1x |
graphics::par("cin")[2] + graphics::par("mgp")[2]) * graphics::par("cex") |
29 |
} |
1 |
# MUTATORS |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
# Getters ====================================================================== |
|
6 |
#' @export |
|
7 |
#' @method labels TimeSeries |
|
8 | 6x |
labels.TimeSeries <- function(object, ...) colnames(object) |
9 | ||
10 |
#' @rdname labels |
|
11 |
#' @aliases labels,TimeSeries-method |
|
12 |
setMethod("labels", "TimeSeries", labels.TimeSeries) |
|
13 | ||
14 |
#' @export |
|
15 |
#' @method labels TimeIntervals |
|
16 | 11x |
labels.TimeIntervals <- function(object, ...) object@.Id |
17 | ||
18 |
#' @rdname labels |
|
19 |
#' @aliases labels,TimeIntervals-method |
|
20 |
setMethod("labels", "TimeIntervals", labels.TimeIntervals) |
|
21 | ||
22 |
#' @export |
|
23 |
#' @method length TimeIntervals |
|
24 | 4x |
length.TimeIntervals <- function(x) length(x@.Id) |
25 | ||
26 |
#' @rdname length |
|
27 |
#' @aliases length,TimeIntervals-method |
|
28 |
setMethod("length", "TimeIntervals", length.TimeIntervals) |
1 |
# SPAN |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname span |
|
7 |
#' @aliases span,TimeSeries-method |
|
8 |
setMethod( |
|
9 |
f = "span", |
|
10 |
signature = c(x = "TimeSeries"), |
|
11 |
definition = function(x, calendar = NULL) { |
|
12 | 4x |
z <- end(x, calendar = calendar) - start(x, calendar = calendar) |
13 | 4x |
unclass(z) * calendar_direction(calendar) |
14 |
} |
|
15 |
) |
|
16 | ||
17 |
#' @export |
|
18 |
#' @rdname span |
|
19 |
#' @aliases span,TimeIntervals-method |
|
20 |
setMethod( |
|
21 |
f = "span", |
|
22 |
signature = c(x = "TimeIntervals"), |
|
23 |
definition = function(x, calendar = NULL) { |
|
24 | 4x |
z <- end(x, calendar = calendar) - start(x, calendar = calendar) |
25 | 4x |
unclass(z) * calendar_direction(calendar) |
26 |
} |
|
27 |
) |
1 |
# OVERLAP |
|
2 |
#' @include AllGenerics.R |
|
3 |
NULL |
|
4 | ||
5 |
#' @export |
|
6 |
#' @rdname overlap |
|
7 |
#' @aliases overlap,TimeIntervals-method |
|
8 |
setMethod( |
|
9 |
f = "overlap", |
|
10 |
signature = "TimeIntervals", |
|
11 |
definition = function(x, calendar = NULL, aggregate = TRUE) { |
|
12 | 3x |
labels <- labels(x) |
13 | 3x |
lower <- start(x, calendar = calendar) * calendar_direction(calendar) |
14 | 3x |
upper <- end(x, calendar = calendar) * calendar_direction(calendar) |
15 | 3x |
m <- length(x) |
16 | ||
17 |
## Compute overlap |
|
18 | 3x |
index <- utils::combn( |
19 | 3x |
x = seq_len(m), |
20 | 3x |
m = 2, |
21 | 3x |
FUN = function(x) max(0, min(upper[x]) - max(lower[x]) + 1) |
22 |
) |
|
23 | ||
24 |
## Matrix of results |
|
25 | 3x |
mtx <- matrix(data = upper - lower, nrow = m, ncol = m, dimnames = list(labels, labels)) |
26 | 3x |
mtx[lower.tri(mtx, diag = FALSE)] <- index |
27 | 3x |
mtx <- t(mtx) |
28 | 3x |
mtx[lower.tri(mtx, diag = FALSE)] <- index |
29 | ||
30 |
## Aggregate in case of disjoint intervals referring to the same event |
|
31 | 3x |
if (isTRUE(aggregate)) { |
32 | 3x |
mtx <- t(rowsum(mtx, group = rownames(mtx), reorder = FALSE)) |
33 | 3x |
mtx <- rowsum(mtx, group = rownames(mtx), reorder = FALSE) |
34 |
} |
|
35 | ||
36 | 3x |
mtx |
37 |
} |
|
38 |
) |
1 |
# COERCION |
|
2 |
#' @include AllGenerics.R AllClasses.R |
|
3 |
NULL |
|
4 | ||
5 |
# To RataDie =================================================================== |
|
6 |
#' @export |
|
7 |
#' @rdname as_fixed |
|
8 |
#' @aliases as_fixed,numeric-method |
|
9 |
setMethod( |
|
10 |
f = "as_fixed", |
|
11 |
signature = "numeric", |
|
12 | 7x |
definition = function(from) .RataDie(from) |
13 |
) |
|
14 | ||
15 |
# To data.frame ================================================================ |
|
16 |
#' @export |
|
17 |
#' @method as.data.frame TimeSeries |
|
18 |
as.data.frame.TimeSeries <- function(x, ..., calendar = NULL) { |
|
19 |
## Build a long data frame |
|
20 | 1x |
z <- as.data.frame.table(x, base = list("T", "S", LETTERS)) |
21 | ||
22 |
## Add sampling times |
|
23 | 1x |
z[[1]] <- time(x, calendar = calendar) |
24 | ||
25 |
## Fix colnames |
|
26 | 1x |
colnames(z) <- c("time", "series", "variable", "value") |
27 | ||
28 | 1x |
z |
29 |
} |
|
30 | ||
31 |
#' @export |
|
32 |
#' @describeIn as.data.frame Returns a long [`data.frame`] with the following columns: |
|
33 |
#' \describe{ |
|
34 |
#' \item{`time`}{The (decimal) years at which the time series was sampled.} |
|
35 |
#' \item{`series`}{The name of the time series.} |
|
36 |
#' \item{`variable`}{The name of the variables.} |
|
37 |
#' \item{`value`}{The observed value.} |
|
38 |
#' } |
|
39 |
#' @aliases as.data.frame,TimeSeries-method |
|
40 |
setMethod("as.data.frame", "TimeSeries", as.data.frame.TimeSeries) |
|
41 | ||
42 |
#' @export |
|
43 |
#' @method as.data.frame TimeIntervals |
|
44 |
as.data.frame.TimeIntervals <- function(x, ..., calendar = NULL) { |
|
45 |
## Build a data frame |
|
46 | 4x |
data.frame( |
47 | 4x |
label = labels(x), |
48 | 4x |
start = start(x, calendar = calendar), |
49 | 4x |
end = end(x, calendar = calendar) |
50 |
) |
|
51 |
} |
|
52 | ||
53 |
#' @export |
|
54 |
#' @describeIn as.data.frame Returns a [`data.frame`] with the following columns: |
|
55 |
#' \describe{ |
|
56 |
#' \item{`label`}{The name of the intervals.} |
|
57 |
#' \item{`start`}{The start time of the intervals, in (decimal) years.} |
|
58 |
#' \item{`end`}{The end time of the intervals, in (decimal) years.} |
|
59 |
#' } |
|
60 |
#' @aliases as.data.frame,TimeIntervals-method |
|
61 |
setMethod("as.data.frame", "TimeIntervals", as.data.frame.TimeIntervals) |