currycarbon
A package for simple, fast radiocarbon calibration
https://github.com/nevrome/currycarbon
LTS Haskell 23.1: | 0.3.0.1 |
Stackage Nightly 2024-12-09: | 0.3.0.1 |
Latest on Hackage: | 0.3.0.1 |
currycarbon-0.3.0.1@sha256:e129650de90760d1522484c784c866e112af997dd45bdf35abc2c38ee93b674a,2260
Module documentation for 0.3.0.1
- Currycarbon
- Currycarbon.CLI
- Currycarbon.CalCurves
- Currycarbon.Calibration
- Currycarbon.ParserHelpers
- Currycarbon.Parsers
- Currycarbon.SumCalibration
- Currycarbon.Types
- Currycarbon.Utils
currycarbon
Radiocarbon calibration module written in and for Haskell. Comes with a small CLI app to run calibration on the command line.
Library
The Haskell library is available on Hackage here and on Stackage here.
CLI app
For stable release versions we automatically prepare statically built binaries that can be downloaded and run directly.
You can download them here: [ Linux π₯ | macOS π₯ ]. Older release versions (some with Windows builds) are available here.
So in Linux you can run the following commands to get started:
# download the current stable release binary
wget https://github.com/nevrome/currycarbon/releases/latest/download/currycarbon-Linux
# make it executable
chmod +x currycarbon-Linux
# test it
./currycarbon-Linux "Sample1,4990,30"
currycarbon v0.3.0.1 (UTF-8)
Method: Bchron {distribution = StudentTDist {ndf = 100.0}}
Curve: IntCal20
Calibrating...
CalEXPR: [1] Sample1:4990Β±30BP
Calibrated: 3936BC >> 3794BC > 3757BC < 3662BC << 3654BC
1-sigma: 3794-3707BC, 3666-3662BC
2-sigma: 3936-3874BC, 3804-3697BC, 3684-3654BC
βββ ββββ
ββββββββββββββ
ββββββββββββββ β
ββ ββββββββββββββββ ββ
βββββ ββββββββββββββββ ββββ
βββββββββββ βββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
-3950 βββββββββββ¬ββββββββββββββββ¬βββββββββββββββββ¬ββββββββββ -3640
> > ^ < <
ββββββββββββββββ β
βββββββββββ ββββββββββββββββββ ββββββ
Done.
Usage: currycarbon [--version] [CalEXPRs] [-i|--inputFile FILE]
[--calCurveFile FILE] [--method DSL] [--allowOutside]
[--noInterpolation] [-q|--quiet] [--densityFile FILE]
[--hdrFile FILE]
[[--seed INT] (-n|--nrSamples INT) --samplesFile FILE]
[--calCurveSegFile FILE] [--calCurveMatFile FILE]
Intercept calibration of radiocarbon dates
Available options:
-h,--help Show this help text
--version Show version
CalEXPRs ---
A string to specify "calibration expressions", so
small chronological models for individual events.
These can include uncalibrated radiocarbon ages,
uniform age ranges and operations to combine the
resulting age probability distribution as sums or
products.
The expression language includes the following
functions:
- calExpr(id = STRING, expr = EXPR)
- uncalC14(id = STRING, yearBP = INT, sigma = INT)
- rangeBP(id = STRING, start = INT, stop = INT)
- rangeBCAD(id = STRING, start = INT, stop = INT)
- sum(a = EXPR, b = EXPR)
- product(a = EXPR, b = EXPR)
The order of arguments is fixed, but the argument
names '<arg> =' can be left out. The 'id' arguments
are optional. Some functions can be shortened with
syntactic sugar:
- calExpr(STRING, EXPR) -> id: EXPR
- uncalC14(STRING, INT, INT) -> STRING,INT,INT
- sum(EXPR, EXPR) -> EXPR + EXPR
- product(EXPR, EXPR) -> EXPR * EXPR
Parentheses '()' can be used to specify the
evaluation order within an expression. Multiple
expressions can be chained, separated by ';'.
Examples:
1. Calibrate a single radiocarbon date with a mean
age BP and a one sigma standard deviation:
"3000,30" or "uncalC14(yearBP = 3000, sigma = 30)"
2. Calibrate two radiocarbon dates and sum them:
"(3000,30) + (3100,40)" or
"sum(uncalC14(3000,30), uncalC14(3100,40))"
3. Compile a complex, named expression:
"Ex3: ((3000,30) + (3100,40)) * rangeBP(3200,3000)"
---
-i,--inputFile FILE A file with a list of calibration expressions.
Formatted just as CalEXPRs, but with a new line for
each input expression. CalEXPRs and --inputFile can
be combined and you can provide multiple instances of
--inputFile. Note that syntactic sugar allows to read
simple radiocarbon dates from a headless .csv file
with one sample per row: <sample name>,<mean age
BP>,<one sigma standard deviation>.
--calCurveFile FILE Path to an calibration curve file in '.14c' format.
The calibration curve will be read and used for
calibration. If no file is provided, currycarbon will
use the 'intcal20' curve.
--method DSL The calibration algorithm that should be used:
'<Method>,<Distribution>,<NumberOfDegreesOfFreedom>'.
The default setting is equivalent to
"Bchron,StudentT,100" which copies the algorithm
implemented in the Bchron R package. For the Bchron
algorithm with a normal distribution
("Bchron,Normal") the degrees of freedom argument is
not relevant
Alternatively we implemented "MatrixMult", which
comes without further arguments.
--allowOutside Allow calibrations to run outside the range of the
calibration curve.
--noInterpolation Do not interpolate the calibration curve.
-q,--quiet Suppress the printing of calibration results to the
command line.
--densityFile FILE Path to an output file to store output densities per
CalEXPR and calender year.
--hdrFile FILE Path to an output file to store the high probability
density regions for each CalEXPR.
--seed INT Seed for the random number generator for age
sampling. The default causes currycarbon to fall back
to a random seed. (default: Nothing)
-n,--nrSamples INT Number of age samples to draw per CalEXPR.
--samplesFile FILE Path to an output file to store age samples for each
CalEXPR.
--calCurveSegFile FILE Path to an output file to store the relevant,
interpolated calibration curve segment for the first
(!) input date. This option as well as
--calCurveMatFile are meant for debugging.
--calCurveMatFile FILE Path to an output file which stores the relevant,
interpolated calibration curve segment for the first
(!) input date in a wide matrix format.
For developers who want to edit the code
To install the latest development version you can follow these steps:
- Install the Haskell build tool Stack
- Clone the repository
- Execute
stack install
inside the repository to build the tool and automatically copy the executables to~/.local/bin
(which you may want to add to your path). This will install the compiler and all dependencies into folders that wonβt interfere with any installation you might already have.
Running the golden tests
Because the golden tests can not run on stackage as they are set up now (see the discussion here) I hid them behind an environment variable. You can run them with
CURRY_RUN_GOLDEN=true stack test --pedantic
Just calling stack test --pedantic
without this variable will skip any test with the pattern "Golden"
in their descriptors.
Preparing a new stable release
The Github Actions script in .github/workflows/release.yml
registers a new draft release and automatically builds and uploads currycarbon binaries when a new Git tag with the prefix v*
is pushed.
# locally register a new tag (e.g. 0.3.1)
git tag -a v0.3.1 -m "see CHANGELOG.md"
# push tag
git push origin v0.3.1
In case of a failing build delete the tag and the release draft on Github and then delete the tag locally with
git tag -d v0.3.1
before rerunning the procedure above.
Profiling
stack build --profile
stack exec --profile -- currycarbon "1000,200;2000,200;3000,200;4000,200;5000,200;6000,200;7000,200;8000,200" -q --densityFile /dev/null +RTS -p
stack exec -- currycarbon "1000,200;2000,200;3000,200;4000,200;5000,200;6000,200;7000,200;8000,200" -q --densityFile /dev/null +RTS -s
Changes
- V 0.3.0.1: The golden tests can not run on stackage as it stands, so I hid them behind an environment variable.
- V 0.3.0.0: Major update with multiple breaking changes and new features:
- Added a new mechanism to draw random age samples from a CalPDF (
sampleAgesFromCalPDF :: AgeSamplingConf -> CalPDF -> RandomAgeSample
). This is available from the command line with the optionssamplesFile
,--seed
, and-n
/--nrSamples
. - Added a new concept to the
CalExpr
data type: Age ranges with uniform probability for each year in the range (TimeWindowBP
andTimeWindowBCAD
). - Reworked the encoding and evaluation mechanism for calibration expressions:
- Introduced the
NamedCalExpr
as a wrapper aroundCalExpr
with an identifier, and then adjusted the ID generation forCalPDF
s to prioritize this identifier. - Reworked the CLI DSL to support a standardized configuration language syntax implemented in a new module
ParserHelpers.hs
. This introduces a set of flexible functions (calExpr()
,uncalC14()
,rangeBP()
,rangeBCAD()
,sum()
andproduct()
) which generally complement the previously available syntax and operators. The old syntax is mostly preserved as syntactic sugar for the new, more standardized syntax. Unfortunately this is not entirely seamless: The change breaks some expressions that were valid before (e.g."3000,30 + 3020,50"
). They now require additional parentheses to pass (so e.g."(3000,30) + (3020,50)"
). - Added some unit tests to cover the increasingly complex DSL.
- Introduced the
- Changed the output files from .csv to .tsv and to a more meaningful and consistent set of column names.
- Slightly adjusted the rendering of the pretty, human-focussed command line output.
- Updated and improved the command line documentation.
- Renamed some CLI arguments:
--calibrationCurveFile
->--calCurveFile
--calCurveSegmentFile
->--calCurveSegFile
--calCurveMatrixFile
->--calCurveMatFile
- Changed the CLI behaviour with
--calCurveSegFile
and--calCurveMatFile
: currycarbon now fails with these options if the first sample is not a single, uncalibrated radiocarbon date (souncalC14()
). - Added a simple golden test system with some basic calls to the
currycarbon
CLI tool. - Switched to a new GHC version (v9.4.7) and stackage resolver version (lts-21.17).
- Added a new mechanism to draw random age samples from a CalPDF (
- V 0.2.1.2: Maintenance: Switched to a newer compiler/resolver version, lifted some dependency restrictions, ran stylish-haskell on the entire codebase, updated the github actions, deprecated the haddock documentation for the dev version on GitHub.
- V 0.2.1.1: Lifted some restrictions regarding the upper version bounds of dependencies.
- V 0.2.1.0: Added a mechanism to detect terminal encoding and fall back on a simpler CLI plot if it is not UTF-8.
- V 0.2.0.1: Brought sample names back to default CLI output.
- V 0.2.0.0: Added sum (and product) calibration and made the necessary changes to various interfaces (including CLI) to make this functionality accessible.
- V 0.1.2.0: Added simple summary data (
CalRangeSummary
with calibrated median age + begin and end of 1- and 2-sigma ranges) toCalC14
and the CLI output and plot. The latter got refactored and enhanced in the process.HDR
s are now βorderedβ, so_hdrstart
actually stores the older and_hdrstop
the younger date. - V 0.1.1.0: Complete rewrite of the CLI output handling to avoid a memory leak.
- V 0.1.0.0: Switch to PVP versioning (https://pvp.haskell.org/).
- V 0.24.4: Removed big dependencies bytestring and statistics.
- V 0.24.3: Multiple changes in .cabal to make cabal check happy.
- V 0.24.2: Found and fixed another severe bug in
renderCalCurve
. - V 0.24.1: Fixed a serious bug in
renderCalCurveMatrix
. - V 0.24.0: Introduced more precise data types to distinguish years BP and years BC/AD.
- V 0.23.1: Small changes to the instances of some general types.
- V 0.23.0: Renamed multiple functions to make the naming of operations for parsing, reading, from-file reading, rendering and writing consistent across data types.
- V 0.22.0: Changed the interface of the important
calibrateDates
function with a new config data typeCalibrateDatesConf
. - V 0.21.3: Refactored the calibration curve interpolation.
- V 0.21.2: Introduced doctest and added some tiny examples/tests to try it out.
- V 0.21.1: Split up the calibration module for better readability.
- V 0.21.0: Added a neat CLI density plot for calibrated dates.
- V 0.20.2: Some performance improvements for the calibration of large numbers of dates.
- V 0.20.1: Better (parsing) error handling.
- V 0.20.0: Added an option
--allowOutside
to allow for calibrations to run outside the range of the calibration curve. - V 0.19.0: Added functionality to filter out dates outside of the range of the calibration curve and report an error in this case.
- V 0.18.0: Implemented calibration with a StudentT distribution to mimic Bchron and established that as the new default. Reimplemented the
--method
option of the CLI tool to reflect that change. - V 0.17.0: Changed argument order in the
CalCurve
data type to adjust to the order in.14C
files. - V 0.16.0: Refactoring in the library to simplify and clarify the interface.
- V 0.15.0: Added another calibration algorithm (following the implementation by Andrew Parnell in Bchron) and a method switch for the CLI.
- V 0.14.0: Introduced strictness, which brought a significant increase in performance. See the discussion here: https://old.reddit.com/r/haskell/comments/picjy6/how_could_i_improve_the_performance_of_my/.
- V 0.13.0: Major rewrite with the vector library - includes multiple bugfixes, but is surprisingly slow.
- V 0.12.0: Renamed some core functions.
- V 0.11.0: Made calibration curve interpolation optional and turned it off by default.
- V 0.10.0: Simplified CLI interface by dropping the
calibrate
subcommand (currycarbon
is sufficient now) and by repurposing-q
from--quickOut
to--quiet
. - V 0.9.0: Made
--hdrFile
output a lot more machine-readable. - V 0.8.0: Added option
--calibrationCurveFile
to calibrate with different calibration curves. - V 0.7.2: More documentation, small changes in code layout and renamed CLI module that provides
runCalibrate
. - V 0.7.1: Added type documentation with haddock and replaced the existing types with record types.
- V 0.7.0: Changed the date input interface once more.
- V 0.6.0: Changed the date input interface, because parenthesis can be part of valid lab numbers.
- V 0.5.2: Fixed parallel evaluation (deepseq forced memory-intensive, non-lazy behaviour).
- V 0.5.1: Added github release action (copied from poseidon-hs).
- V 0.5.0: Added file input for dates to calibrate.
- V 0.4.0: Made output calibrated dates negative numbers for BC and positive for AD - and adjusted HDR printing accordingly.
- V 0.3.2: Some optimisation.
- V 0.3.1: Added automatic filling of unknown sample names.
- V 0.3.0: Simplified interface.
- V 0.2.1: Removed ascii plot functionality.
- V 0.2.0: Added parallel processing for the main calibration operation.
- V 0.1.0: First basically working version.