---
title: "Chronological Query Language (CQL)"
output: rmarkdown::html_vignette
bibliography: references.bib
vignette: >
  %\VignetteIndexEntry{Chronological Query Language (CQL)}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

The Chronological Query Language (CQL) is a tool for formally describing chronological models [@Bronk_Ramsey1998-zw].
It is most commonly used to input data for Bayesian radiocarbon calibration in [OxCal](https://c14.arch.ox.ac.uk/oxcal.html) [@Bronk_Ramsey2009-yk].
`stratigraphr` includes an R interface for CQL2, the version used in OxCal v3+.

This vignette describes how to use this interface to generate CQL models in R.

## Overview

* Individual CQL commands (see <https://c14.arch.ox.ac.uk/oxcalhelp/hlp_commands.html>) are implemented as `cql_*` functions.
* Use `cql()` to group together CQL functions or include arbitrary CQL code.
* Execute CQL scripts in OxCal using `write_oxcal()` or the [oxcAAR package](https://CRAN.R-project.org/package=oxcAAR).


## Writing CQL models

```{r setup}
library("stratigraphr")
```

## Generating CQL models from other types of data

Used in the simple way above, `stratigraphr`'s CQL interface offers little benefit over writing CQL directly.
Its real power is in combining `cql()` with other R tools to build models based on other data.

For the following examples, we will use a simple example dataset of radiocarbon dates:

```{r example-data}
library("purrr")
library("dplyr")

dates <- data.frame(
  lab_id = c("ABC-001", "ABC-002", "ABC-003", "ABC-004", "ABC-005"),
  age = c(5050, 5000, 4950, 4900, 4850),
  error = c(30, 30, 30, 30, 30),
  phase = c("Phase 1", "Phase 1", "Phase 1", "Phase 2", "Phase 2")
)
```

### Tabular data

With radiocarbon data in a tabular format, you can take advantage of `dplyr`'s powerful tools for data manipulation to build CQL models programmatically.

For example, use `dplyr::mutate()` to concisely express a table of dates as CQL `R_Date` commands:

```{r r-date}
dates |>
  mutate(r_date = cql_r_date(lab_id, age, error)) |>
  pluck("r_date") |>
  cql()
```

Or use `dplyr::group_by()` and `dplyr::summarise()` to build phase models.
This is a three stage process:

1. Preprocess the dates, e.g. to order phases.
2. Group dates by phase and summarise them with `cql_phase()`.
3. Group phases into a sequence, using `boundaries` to automatically add boundary constraints between them.

```{r phase-model}
dates |>
  group_by(phase) |>
  summarise(cql = cql_phase(phase, cql_r_date(lab_id, age, error))) |>
  arrange(desc(phase)) |>
  summarise(cql = cql_sequence("Example Sequence", cql, boundaries = TRUE)) |>
  pluck("cql") |>
  cql() ->
  example_cql

example_cql
```

### Stratigraphs

...

## Running CQL models

You can run models generated by `cql()` using the desktop or online versions of OxCal by simply copying the output into the program.
Alternatively, use `write_oxcal()` to create a .oxcal file:

```{r write-oxcal}
oxcal_cql <- cql(
  cql_r_date("ABC-001", 9100, 30),
  cql_r_date("ABC-002", 9200, 30),
  cql_r_date("ABC-003", 9300, 30)
)

write_oxcal(oxcal_cql, "cql.oxcal")
```
```{r write-oxcal-cleanup, include=FALSE}
file.remove("cql.oxcal")
```

You can also run OxCal directly through R using the [oxcAAR](https://CRAN.R-project.org/package=oxcAAR) package.
This depends on a local installation of OxCal.
If you already have one installed, you can set the path to the executable using `oxcAAR::setOxcalExecutablePath()`.
Otherwise, use `oxcAAR::quickSetupOxcal()` to download one, for example to a temporary directory:

```{r oxcaar-setup, results=FALSE, message=FALSE}
library("oxcAAR")
quickSetupOxcal(path = tempdir())
```

You can then use `oxcAAR::executeOxcalScript()` to run the CQL script and `oxcAAR::readOxcalOutput()` to read the output back into R.

```{r oxcaar-execute, results=FALSE, message=FALSE}
executeOxcalScript(oxcal_cql) |>
  readOxcalOutput() ->
  oxcal_output
```

You can parse the output with `oxcAAR::parseOxcalOutput()` and visualise it using `oxcAAR`'s built-in plotting functions:

```{r oxcaar-plot, fig.show="hold"}
oxcal_parsed <- oxcAAR::parseOxcalOutput(oxcal_output)
plot(oxcal_parsed)
calcurve_plot(oxcal_parsed)
```

The current CRAN version of oxcAAR (v. 1.0.0) does not read the posterior probabilities produced by a model with Bayesian calibration, so to work with these you need to install the latest development version (`devtools::install_github("ISAAKiel/oxcAAR")`).
With this, `oxcAAR::parseOxcalOutput()` also contains the modelled results in `$posterior_sigma_ranges` and `$posterior_probabilities`.
Again, you can quickly visualise these with the built-in plotting functions:

```{r oxcaar-bayes, eval=FALSE}
# Not run: slow
example_oxcal <- executeOxcalScript(example_cql)
readOxcalOutput(example_oxcal) |>
  parseOxcalOutput() |>
  plot()
```

## References
