extending.Rmd
---
title: "Extending aion"
author: "N. Frerebeau"
date: "`r Sys.Date()`"
output:
rmarkdown::html_vignette:
number_sections: yes
fig_caption: yes
toc: true
bibliography: bibliography.bib
vignette: >
%\VignetteIndexEntry{Extending aion}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
```{r setup}
library(aion)
```
**aion** offers a simple API that can be extended and used by other specialized packages.
The following packages rely on **aion**:
* [**ananke**](https://github.com/tesselle/ananke) (quantitative chronology in archaeology).
* [**kairos**](https://github.com/tesselle/kairos) v2.0 (analysis of chronological patterns from archaeological count data).
* [**ArchaeoPhases**](https://github.com/ArchaeoStat/ArchaeoPhases) v2.0 (post-processing of MCMC simulations for chronological modelling).
# Calendars and Dates
The following example is used to build a simple solar calendar with 365 days each year and no leap-year rule. This is the ancient Egyptian calendar. You will find full details of the calculations and detailed explanations in @reingold2018 (p. 29).
You can define additional calendars by creating S4 classes that inherit from the `TimeScale` class exported by **aion**:
```{r}
## Egyptian calendar
E <- setClass(
Class = "EgyptianCalendar",
prototype = list(
name = "Egyptian",
fixed = -272787,
direction = 1L,
year = 365
),
contains = "TimeScale"
)
```
Once the calendar has been defined, you need to build methods for converting *rata die* to and from this calendar:
```{r}
## Convert Egyptian dates to rata die
## NB: this method MUST return a RataDie object
setMethod(
f = "fixed",
signature = c(
year = "numeric",
month = "numeric",
day = "numeric",
calendar = "EgyptianCalendar"
),
definition = function(year, month, day, calendar) {
rd <- calendar_fixed(calendar) +
365 * (year - 1) +
30 * (month - 1) +
day - 1
as_fixed(rd)
}
)
## Convert rata die to Egyptian dates
## NB: this method MUST return a data.frame
setMethod(
f = "as_date",
signature = c(object = "numeric", calendar = "EgyptianCalendar"),
definition = function(object, calendar) {
day <- object - calendar_fixed(calendar)
year <- day %/% 365 + 1
month <- (day %% 365) %/% 30 + 1
day <- day - 365 * (year - 1) - 30 * (month - 1) + 1
data.frame(year = year, month = month, day = day)
}
)
## Convert rata die to Egyptian years
setMethod(
f = "as_year",
signature = c(object = "numeric", calendar = "EgyptianCalendar"),
definition = function(object, calendar, ...) {
(object - calendar_fixed(calendar)) %/% 365 + 1
}
)
```
Now you can use your calendar:
```{r}
## Create a calendar object
cal <- E()
## Convert 161/7/15 in rata die
fixed(
year = 161,
month = 7,
day = 15,
calendar = cal
)
## Convert -214193 r.d. to an Egyptian date
as_date(-214193, calendar = cal)
```
The definition of new calendars, combined with the Julian and Gregorian calendars already included in **aion**, allows you to build conversion tools:
```{r}
## Build a conversion function from Gregorian CE years to Egyptian years
Gregorian_to_Egyptian <- convert(CE(), E())
## Convert 2023 (Gregorian) to the Egyptian calendar
Gregorian_to_Egyptian(2023)
```
# Time Series
A time series object is simply an $n \times m \times p$ `array`, with $n$ being the number of observations, $m$ being the number of series and with the $p$ columns of the third dimension containing extra variables for each series. This `array` comes with an extra `time` slot that store the observations times expressed in *rata die*. You can create classes that inherits from the `TimeSeries` class.
As an example, you can create a class that represent the results of the calibration of radiocarbon dates (this code comes from the [**ananke**](https://packages.tesselle.org/ananke/) package):
```{r}
.CalibratedAges <- setClass(
Class = "CalibratedAges",
slots = c(
ages = "numeric", # Stores the radiocarbon ages to be calibrated
errors = "numeric", # Store the standard deviation of the radiocarbon ages
curves = "character" # Store the name of the calibration curve
),
contains = "TimeSeries"
)
```
All methods defined in **aion** can then be used on objects belonging to this new class (e.g. `plot()`).
# References