Header menu logo bristlecone

ScriptNotebook

The long-term ecological detective: Holocene ecosystem functioning

Analysis of microfossils and inorganic compounds from lake sediment cores and peat cores can provide rich information on past biodiversity and environmental conditions.

Jeffers et al (2011) identified ...

To get started, we first load and open the Bristlecone library in an F# script file (.fsx):

open Bristlecone
open Bristlecone.Language
open Bristlecone.Time

Then, we may define units of measure that are not SI units (which are included with F#) and are not provided in the Time module of Bristlecone.

[<Measure>] type area
[<Measure>] type indiv // pollen accumulation proxy units -> individuals per area
[<Measure>] type conc  // nitrogen concentration proxy units (e.g., δ15N or %TN, scaled)
[<Measure>] type d15N // proxy measure of nitrogen
[<Measure>] type grain
[<Measure>] type cm

We can then use these units of measure when defining the model system. Before we can write model equations, we need to define the states, parameters, and measures that we need to apply within them.

// States
let N = state<conc> "available_N"         // Reconstructed available N proxy (δ15N or %TN scaled)
let X = state<indiv / area> "population"  // Pollen accumulation proxy for population density
let obsN = measure "observed_N" // After conversion with an alpha conversion factor
let obsPAR = measure<(grain / cm^2) / year> "observed_PAR"

// Core ecological parameters
let λ = parameter "λ" Positive 0.01<conc/year> 1.0<conc/year> // External N input
let γN = parameter "γ[N]" Positive 0.001<1/year> 0.1<1/year> // N loss rate
let r   = parameter "r" Positive 0.001<(indiv/area)/conc> 20.<(indiv/area)/conc> // Intrinsic growth rate
let γX = parameter "γ[X]" Positive 0.01<1/year> 0.2<1/year> // mortality

// Measurement model parameters
let αδ15N = parameter<d15N> "αδ15N" NoConstraints -2.0<d15N> 2.0<d15N>   // intercept for δ15N proxy
let βδ15N = parameter<d15N/conc> "βδ15N" NoConstraints 0.1<d15N/conc> 2.0<d15N/conc>    // slope linking latent N to δ15N

// Likelihood function parameters
let ρ = parameter "ρ" NoConstraints -0.500 0.500
let σx = parameter "σ[x]" Positive 10.<indiv/area> 50.<indiv/area>
let σy = parameter "σ[y]" Positive 0.001<d15N> 0.100<d15N>

In this scenario, we will assess eight hypotheses that relate to the form of dependency between an individual plant taxon and nitrogen availability. To scaffold the hypotheses, we first define a base model that contains the two ordinary differential equations for the two state variables; it takes three pluggable model components as arguments using a standard F# function definition.

let baseModel
    (uptake  : ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)
    (feedback: ModelExpression<indiv/area> -> ModelExpression<conc/year>)
    (density : ModelExpression<indiv/area> -> ModelExpression<1>) =

    // ODEs
    let ``dN/dt``: ModelExpression<conc/year> =
        let uptake, uptakeMult = uptake This (State X)
        P λ
        - uptake * uptakeMult
        - P γN * This<conc>
        + feedback(State X)

    let ``dX/dt``: ModelExpression<(indiv / area)/year> =
        let uptake, _ = uptake (State N) This
        P r * uptake * density This - P γX * This

    // Measure: convert modeled N to proxy comparison scale
    let nToProxy : ModelExpression<d15N> = P αδ15N + P βδ15N * State N
    let nFromProxy : ModelExpression<conc> = (Measure obsN - P αδ15N) / P βδ15N

    // -log likelihood function
    let NLL = ModelLibrary.NegLogLikelihood.BivariateNormal (Require.state X) (Require.measure obsN) σx σy ρ

    Model.empty
    // Add the core ecological ODEs:
    |> Model.addRateEquation X ``dX/dt``
    |> Model.addRateEquation N ``dN/dt``
    |> Model.estimateParameter λ
    |> Model.estimateParameter γN
    |> Model.estimateParameter r
    |> Model.estimateParameter γX
    // Add the conversion from d15N to N availability:
    |> Model.addMeasure obsN nToProxy
    |> Model.initialiseHiddenStateWith N nFromProxy
    |> Model.estimateParameter αδ15N
    |> Model.estimateParameter βδ15N
    // Add the likelihood function:
    |> Model.useLikelihoodFunction NLL
    

In this model, we naively assume that the pollen accumulation rate approximates the individuals of the plant taxon per unit area. However, for nitrogen the use of a measurement model is desirable, at a minimum because raw d15N (permil) does not

Next, we define the three interchangable components that we will plug in. The models as stated in Jeffers (2011) are not truly nested, as some combinations are not ecologically plausable. In this instance, we define two sets of model components; one for N-dependent systems, and one for N-independent systems. The two sets are encoded in a record for each of the three modes below.

Feedback component.

A plant-soil feedback may be enabled or disabled, and is only defined in one mathematical form.

let feedbackMode =

    // Conversion factor (individuals into N)
    let σ  = parameter "α" Positive 0.01<conc/(indiv/area)> 10.<conc/(indiv/area)>

    let none _ = Constant 0.<conc/year>
    let positive (X: ModelExpression<indiv/area>) = P σ * P γX * X

    {|
        NDependent =
            Components.modelComponent "Feedback" [
                Components.subComponent "None" none
                Components.subComponent "Positive feedback" positive
                |> Components.estimateParameter σ
            ]
        NIndependent =
            Components.modelComponent "Feedback" [
                Components.subComponent "Positive feedback" positive
                |> Components.estimateParameter σ
            ]
    |}

N-dependency

We define the N-dependency ("uptake") as a tuple, where the first element is the form of uptake, and the second is a multiplier used to turn on or off the uptake term within the dN/dt equation. This is required because when growth is N-independent, the growth term in dX/dt must be multipled by 1, whereas uptake must be turned off. Three forms of N-dependency are specified: N-independent, linear N-dependency, and saturating N-dependency.

let uptakeMode =

    // Parameters:
    let a = parameter "a" Positive 1e-6<area/(indiv year)> 1e-3<area/(indiv year)> // Uptake rate constant
    let b = parameter "b" Positive 0.5</conc> 2.0</conc> // Half-saturation (MM)

    // If independent, need to substitute 1 into the growth equation instead of 0.
    let independent _ _ =
        Constant 1.<conc/year>, Constant 0.

    // tuple of (uptake rate (0 if none), uptake multiplier)
    let linear (N: ModelExpression<conc>) (X: ModelExpression<indiv/area>) = P a * N * X, Constant 1.
    let michaelisMenten (N: ModelExpression<conc>) (X: ModelExpression<indiv/area>) : ModelExpression<conc/year> * ModelExpression<1> =
        (P a * N * X) / (Constant 1. + (P b * N)), Constant 1.

    {|
        NDependent =
            Components.modelComponent "Uptake" [
                Components.subComponent "Linear" linear
                |> Components.estimateParameter a
                Components.subComponent "Saturating (Michaelis-Menten)" michaelisMenten
                |> Components.estimateParameter a
                |> Components.estimateParameter b
            ]
        NIndependent =
            Components.modelComponent "Uptake" [
                Components.subComponent "Independent" independent
            ]
    |}

Density-dependency

...

let densityMode =

    let K   = parameter "K_growth"   Positive 1.<indiv/area> 1e6<indiv/area>
    let c  = parameter "c_density"  Positive 0.01<area/indiv> 1e-3<area/indiv>

    let logisticDD (X: ModelExpression<indiv/area>) : ModelExpression<1> =
        Constant 1.<1> - X / P K

    let expDD (X: ModelExpression<indiv/area>) : ModelExpression<1> =
        Exponential (-(P c) * X)

    let constant (_: ModelExpression<indiv/area>) : ModelExpression<1> =
        Constant 1.<1>

    {|
        NDepenentGrowth =
            Components.modelComponent "Density" [
                Components.subComponent "Constant" constant
                Components.subComponent "Logistic" logisticDD
                |> Components.estimateParameter K
            ]
        NIndependentGrowth =
            Components.modelComponent "Density" [
                Components.subComponent "Logistic" logisticDD
                |> Components.estimateParameter K
                Components.subComponent "ExpDecay" expDD
                |> Components.estimateParameter c
            ]
    |}

Finally, we can scaffold all of the possible model-component combinations into a set of hypotheses that represents the product of all of the components.

The system is not truly nested, so we create two nested sets and concatenate them together.

let hypothesesDependent =
    Hypotheses.createFromModel baseModel
    |> Hypotheses.apply uptakeMode.NDependent
    |> Hypotheses.apply feedbackMode.NDependent
    |> Hypotheses.apply densityMode.NDepenentGrowth
    |> Hypotheses.compile

let hypothesesIndependent =
    Hypotheses.createFromModel baseModel
    |> Hypotheses.apply uptakeMode.NIndependent
    |> Hypotheses.apply feedbackMode.NIndependent
    |> Hypotheses.apply densityMode.NIndependentGrowth
    |> Hypotheses.compile

let hypotheses =
    List.append hypothesesDependent hypothesesIndependent

The resulting list of hypotheses mirrors the 10 nitrogen-based models presented in Table 1 of Jeffers et al (2011). Bristlecone assigns each model a code based on the components within it. For our 10 models that vary uptake mechanism (UP), feedback (FE), and density-dependence (DE), they are:

for h in hypotheses do
    printfn "%s" h.ReferenceCode

Fitting the models

We can fit the ecological models to data by defining an estimation engine that contains the method that will be applied for model fitting:

let engine: EstimationEngine.EstimationEngine<DatingMethods.Radiocarbon<``cal yr BP``>,float<``cal yr BP``>,year,1> =
    Bristlecone.mkContinuous ()
    |> Bristlecone.withCustomOptimisation ( Optimisation.MonteCarlo.Filzbach.filzbach
           { Optimisation.MonteCarlo.Filzbach.FilzbachSettings.Default with BurnLength = Optimisation.EndConditions.atIteration 200000<iteration> })
    |> Bristlecone.withConditioning Conditioning.NoConditioning
    |> Bristlecone.withSeed 1500 // We are setting a seed for this example - see below
    |> Bristlecone.withTimeConversion DateMode.Conversion.RadiocarbonDates.toYears

let endCond = Optimisation.EndConditions.atIteration 100000<iteration>

Next, we must load in some real data. We leverage FSharp.Data here to read in a csv file containing the raw data.

open FSharp.Data

type PalaeoData = CsvProvider<"data/loch-dubhan/ld.tsv">

let data = PalaeoData.Load "data/loch-dubhan/ld.tsv"

let ts =
    [
        X.Code, data.Rows |> Seq.map(fun r -> float r.Par_betula, DatingMethods.Radiocarbon (float r.``Scaled_age_cumulative (cal yr bp)`` * 1.<Time.``cal yr BP``>)) |> TimeSeries.fromCalibratedRadiocarbonObservations
        obsN.Code, data.Rows |> Seq.map(fun r -> float r.D15N, DatingMethods.Radiocarbon (float r.``Scaled_age_cumulative (cal yr bp)`` * 1.<Time.``cal yr BP``>)) |> TimeSeries.fromCalibratedRadiocarbonObservations
    ] |> Map.ofList

We can run an individual model fit like so:

open Bristlecone.Workflow

module Settings =
    let logger = Logging.Console.logger 1000<iteration>
    let replicates = 3
    let cache = __SOURCE_DIRECTORY__ + "cached/"

let orchestrator = Orchestration.OrchestrationAgent(Settings.logger, System.Environment.ProcessorCount, false)

let runAll () =

    (hypotheses, [ 1 .. Settings.replicates ])
    ||> Seq.map2 (fun h _ ->
        async {
            let result = Bristlecone.fit engine endCond ts h.Model
            Data.EstimationResult.saveAll (fun d -> d.ToString()) Settings.cache "loch-duban" h.ReferenceCode None result
            return result
        }
    )
    |> Seq.iter (Orchestration.OrchestrationMessage.StartWorkPackage >> orchestrator.Post)

runAll ()
Multiple items
module Bristlecone from Bristlecone
<namespacedoc><summary>The core library of Bristlecone, containing model-fitting functions.</summary></namespacedoc>
Main functionality of Bristlecone, including functions to scaffold `ModelSystem`s and for model-fitting (tests and real fits).


--------------------
namespace Bristlecone
module Language from Bristlecone
<summary> An F# Domain Specific Language (DSL) for scripting with Bristlecone. </summary>
module Time from Bristlecone
Multiple items
val Measure: sId: MeasureId<'u> -> ModelExpression<'u>

--------------------
type MeasureAttribute = inherit Attribute new: unit -> MeasureAttribute

--------------------
new: unit -> MeasureAttribute
[<Measure>] type area
[<Measure>] type indiv
[<Measure>] type conc
[<Measure>] type d15N
[<Measure>] type grain
[<Measure>] type cm
val N: StateId<conc>
val state: name: string -> StateId<'u>
val X: StateId<indiv/area>
val obsN: MeasureId<d15N>
val measure: name: string -> MeasureId<'u>
val obsPAR: MeasureId<grain/(cm ^ 2 year)>
[<Measure>] type year
val λ: IncludedParameter<conc/year>
Multiple items
val parameter: code: string -> con: Parameter.Constraint -> lower: float<'u> -> upper: float<'u> -> IncludedParameter<'u>
<summary> Define an estimatable parameter for a Bristlecone model. </summary>

--------------------
[<Measure>] type parameter
val Positive: Parameter.Constraint
val γN: IncludedParameter</year>
val r: IncludedParameter<indiv/(area conc)>
val γX: IncludedParameter</year>
val αδ15N: IncludedParameter<d15N>
val NoConstraints: Parameter.Constraint
val βδ15N: IncludedParameter<d15N/conc>
val ρ: IncludedParameter<1>
val σx: IncludedParameter<indiv/area>
val σy: IncludedParameter<d15N>
val baseModel: uptake: (ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>) -> feedback: (ModelExpression<indiv/area> -> ModelExpression<conc/year>) -> density: (ModelExpression<indiv/area> -> ModelExpression<1>) -> ModelBuilder.ModelBuilder<year>
val uptake: (ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)
type ModelExpression<'u> = private | ME of ModelExpressionUntyped static member (%) : ModelExpression<'u> * ModelExpression<'u> -> ModelExpression<'u> static member ( * ) : ModelExpression<'u1> * ModelExpression<'u2> -> ModelExpression<'u1 'u2> static member (+) : ModelExpression<'u> * ModelExpression<'u> -> ModelExpression<'u> static member (-) : ModelExpression<'u> * ModelExpression<'u> -> ModelExpression<'u> static member (.<) : ModelExpression<'u> * ModelExpression<'u> -> BoolExpression static member (.>) : ModelExpression<'u> * ModelExpression<'u> -> BoolExpression static member (/) : ModelExpression<'u1> * ModelExpression<'u2> -> ModelExpression<'u1/'u2> static member (=.) : ModelExpression<'u> * ModelExpression<'u> -> BoolExpression static member Environment: sid: StateId<'u> -> ModelExpression<'u> static member Exp: ModelExpression<1> -> ModelExpression<1> ...
val feedback: (ModelExpression<indiv/area> -> ModelExpression<conc/year>)
val density: (ModelExpression<indiv/area> -> ModelExpression<1>)
val uptake: ModelExpression<conc/year>
val uptakeMult: ModelExpression<1>
val This<'u> : ModelExpression<'u>
val State: sId: StateId<'u> -> ModelExpression<'u>
val P: name: IncludedParameter<'u> -> ModelExpression<'u>
val nToProxy: ModelExpression<d15N>
val nFromProxy: ModelExpression<conc>
val NLL: ModelSystem.Likelihood<ModelSystem.state>
namespace Bristlecone.ModelLibrary
module NegLogLikelihood from Bristlecone.ModelLibrary
<summary>Negative log likelihood (-logL) functions to represent a variety of distributions and data types.</summary>
<namespacedoc><summary>Pre-built model parts for use in Bristlecone</summary></namespacedoc>
val BivariateNormal: key1: Require.ObsForLikelihood<'u> -> key2: Require.ObsForLikelihood<'v> -> sigmax: IncludedParameter<'u> -> sigmay: IncludedParameter<'v> -> rho: IncludedParameter<1> -> ModelSystem.Likelihood<'w>
module Require from Bristlecone.Language
val state: s: StateId<'u> -> Require.ObsForLikelihood<'u>
val measure: m: MeasureId<'u> -> Require.ObsForLikelihood<'u>
module Model from Bristlecone.Language
<summary> Terms for scaffolding a model system for use with Bristlecone. </summary>
val empty<'time> : ModelBuilder.ModelBuilder<'time>
val addRateEquation: name: StateId<'state> -> expr: ModelExpression<'state/'time> -> mb: ModelBuilder.ModelBuilder<'time> -> ModelBuilder.ModelBuilder<'time>
val estimateParameter: p: IncludedParameter<'u> -> builder: ModelBuilder.ModelBuilder<'time> -> ModelBuilder.ModelBuilder<'time>
val addMeasure: name: MeasureId<'u> -> measure: ModelExpression<'u> -> builder: ModelBuilder.ModelBuilder<'time> -> ModelBuilder.ModelBuilder<'time>
val initialiseHiddenStateWith: name: StateId<'u> -> initialiser: ModelExpression<'u> -> builder: ModelBuilder.ModelBuilder<'time> -> ModelBuilder.ModelBuilder<'time>
val useLikelihoodFunction: likelihoodFn: ModelSystem.Likelihood<ModelSystem.state> -> builder: ModelBuilder.ModelBuilder<'u> -> ModelBuilder.ModelBuilder<'u>
val feedbackMode: {| NDependent: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<conc/year>)>; NIndependent: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<conc/year>)> |}
val σ: IncludedParameter<area conc/indiv>
val none: 'a -> ModelExpression<conc/year>
val Constant: x: float<'u> -> ModelExpression<'u>
val positive: X: ModelExpression<indiv/area> -> ModelExpression<conc/year>
val X: ModelExpression<indiv/area>
module Components from Bristlecone.Language
val modelComponent: name: string -> list: Components.SubComponent<'a> list -> Components.ModelComponent<'a>
val subComponent: name: string -> transform: 'a -> Components.SubComponent<'a>
<summary> Creates a nested component that can be inserted into a base model. </summary>
val estimateParameter: p: IncludedParameter<'u> -> comp: Components.SubComponent<'a> -> Components.SubComponent<'a>
val uptakeMode: {| NDependent: Components.ModelComponent<(ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)>; NIndependent: Components.ModelComponent<(ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)> |}
val a: IncludedParameter<area/(indiv year)>
val b: IncludedParameter</conc>
val independent: 'a -> 'b -> ModelExpression<conc/year> * ModelExpression<1>
val linear: N: ModelExpression<conc> -> X: ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>
val N: ModelExpression<conc>
val michaelisMenten: N: ModelExpression<conc> -> X: ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>
val densityMode: {| NDepenentGrowth: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<1>)>; NIndependentGrowth: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<1>)> |}
val K: IncludedParameter<indiv/area>
val c: IncludedParameter<area/indiv>
val logisticDD: X: ModelExpression<indiv/area> -> ModelExpression<1>
val expDD: X: ModelExpression<indiv/area> -> ModelExpression<1>
val Exponential: expr: ModelExpression<1> -> ModelExpression<1>
val constant: ModelExpression<indiv/area> -> ModelExpression<1>
val hypothesesDependent: Hypotheses.Hypothesis<year> list
module Hypotheses from Bristlecone.Language
<summary>Types to represent a hypothesis, given that a hypothesis is a model system that contains some alternate formulations of certain components.</summary>
val createFromModel: baseModel: ('a -> 'rest) -> Writer.Writer<('a -> 'rest),(Hypotheses.ComponentName * CodedMap<Parameter.Pool.AnyParameter>)> list
val apply: comp: Components.ModelComponent<'a> -> builders: Writer.Writer<('a -> 'rest),(Hypotheses.ComponentName * CodedMap<Parameter.Pool.AnyParameter>)> list -> Writer.Writer<'rest,(Hypotheses.ComponentName * CodedMap<Parameter.Pool.AnyParameter>)> list
anonymous record field NDependent: Components.ModelComponent<(ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)>
anonymous record field NDependent: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<conc/year>)>
anonymous record field NDepenentGrowth: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<1>)>
val compile: builders: Writer.Writer<ModelBuilder.ModelBuilder<'u>,(Hypotheses.ComponentName * CodedMap<Parameter.Pool.AnyParameter>)> list -> Hypotheses.Hypothesis<'u> list
<summary> Compile: run the writer(s), add parameters into the model builder, and wrap in Hypothesis </summary>
val hypothesesIndependent: Hypotheses.Hypothesis<year> list
anonymous record field NIndependent: Components.ModelComponent<(ModelExpression<conc> -> ModelExpression<indiv/area> -> ModelExpression<conc/year> * ModelExpression<1>)>
anonymous record field NIndependent: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<conc/year>)>
anonymous record field NIndependentGrowth: Components.ModelComponent<(ModelExpression<indiv/area> -> ModelExpression<1>)>
val hypotheses: Hypotheses.Hypothesis<year> list
Multiple items
module List from Bristlecone

--------------------
module List from Microsoft.FSharp.Collections

--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T with get member IsEmpty: bool with get member Item: index: int -> 'T with get ...
val append: list1: 'T list -> list2: 'T list -> 'T list
val h: Hypotheses.Hypothesis<year>
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
property Hypotheses.Hypothesis.ReferenceCode: string with get
<summary>Compiles a reference code that may be used to identify (although not necessarily uniquely) this hypothesis</summary>
<returns>A string in the format XX_XXX_YY_YYY... where XX_XXX is a singe component with XX the component and XXX the implementation.</returns>
val engine: EstimationEngine.EstimationEngine<DatingMethods.Radiocarbon<cal yr BP>,float<cal yr BP>,year,1>
module EstimationEngine from Bristlecone
<summary> The estimation engine represents the method used to calculate equations and optimise a likelihood function. The whole estimation engine is tensor-based internally, but may take float-based equations as a legacy option. </summary>
type EstimationEngine<'date,'timespan,'modelTimeUnit,'state> = { TimeHandling: TimeMode OptimiseWith: Optimiser Conditioning: Conditioning<'state> LogTo: WriteOut ToModelTime: ResolutionToModelUnits<'date,'timespan,'modelTimeUnit> InterpolationGlobal: InterpolationMode InterpolationPerVariable: CodedMap<InterpolationMode> Random: Random }
module DatingMethods from Bristlecone.Time
<summary> Contains types representing common dating methods in long term data analysis. </summary>
Multiple items
union case DatingMethods.Radiocarbon.Radiocarbon: float<'u> -> DatingMethods.Radiocarbon<'u>

--------------------
type Radiocarbon<'u> = | Radiocarbon of float<'u> static member (+)<'u> : e1: Radiocarbon<'u0> * e2: float<'u0> -> Radiocarbon<'u0> static member (-)<'u> : e1: Radiocarbon<'u0> * e2: Radiocarbon<'u0> -> float<'u0> static member AddDays: days: int<day> -> date: Radiocarbon<'u> -> Radiocarbon<'u> static member AddMonths: months: int<month> -> date: Radiocarbon<'u> -> Radiocarbon<'u> static member AddYears: date: Radiocarbon<'u> -> years: int<year> -> Radiocarbon<'u> static member FractionalDifference<'u> : isSigned: bool -> d1: Radiocarbon<'u0> -> d2: Radiocarbon<'u0> -> TimeDifference<float<'u0>> static member TotalYearsElapsed<'u> : d1: Radiocarbon<'u0> -> d2: Radiocarbon<'u0> -> float<'u0> static member Unwrap<'u> : Radiocarbon<'u0> -> float<'u0> member Value: float<'u> with get
<summary>Represents a date made by radiocarbon measurement</summary>
Multiple items
val float: value: 'T -> float (requires member op_Explicit)

--------------------
type float = System.Double

--------------------
type float<'Measure> = float
val mkContinuous: unit -> EstimationEngine.EstimationEngine<System.DateTime,System.TimeSpan,year,'u>
<summary>A basic estimation engine for ordinary differential equations, using a Nelder-Mead optimiser.</summary>
val withCustomOptimisation: optim: EstimationEngine.Optimisation.Optimiser -> engine: EstimationEngine.EstimationEngine<'a,'b,'u,'v> -> EstimationEngine.EstimationEngine<'a,'b,'u,'v>
namespace Bristlecone.Optimisation
module MonteCarlo from Bristlecone.Optimisation
<summary> A module containing Monte Carlo Markov Chain (MCMC) methods for optimisation. An introduction to MCMC approaches is provided by [Reali, Priami, and Marchetti (2017)](https://doi.org/10.3389/fams.2017.00006) </summary>
module Filzbach from Bristlecone.Optimisation.MonteCarlo
<summary> An adaptation of the Filzbach method (originally by Drew Purves) </summary>
val filzbach: settings: Optimisation.MonteCarlo.Filzbach.FilzbachSettings -> EstimationEngine.Optimisation.Optimiser
<summary> A Monte Carlo Markov Chain sampler based on the 'Filzbach' algorithm from Microsoft Research Cambridge. </summary>
type FilzbachSettings = { TuneAfterChanges: int MaxScaleChange: float MinScaleChange: float BurnLength: EndCondition } static member Default: FilzbachSettings with get
property Optimisation.MonteCarlo.Filzbach.FilzbachSettings.Default: Optimisation.MonteCarlo.Filzbach.FilzbachSettings with get
module EndConditions from Bristlecone.Optimisation
<summary>Composable end conditions to specify when optimisation routines should end.</summary>
val atIteration: iteration: int<iteration> -> EstimationEngine.Solution list -> currentIteration: int<iteration> -> EstimationEngine.OptimStopReason
<summary> End on or after a minimum number of iterations. </summary>
[<Measure>] type iteration
val withConditioning: c: Conditioning.Conditioning<'u> -> engine: EstimationEngine.EstimationEngine<'a,'b,'v,'u> -> EstimationEngine.EstimationEngine<'a,'b,'v,'u>
<summary> Choose how the start point is chosen when solving the model system </summary>
module Conditioning from Bristlecone
union case Conditioning.Conditioning.NoConditioning: Conditioning.Conditioning<'u>
val withSeed: seed: int -> engine: EstimationEngine.EstimationEngine<'a,'b,'u,'v> -> EstimationEngine.EstimationEngine<'a,'b,'u,'v>
<summary> Use a mersenne twister random number generator with a specific seed. </summary>
val withTimeConversion<'d,'d2,'timespan,'timespan2,'modelTimeUnit,'o1,'o2,'u> : fn: DateMode.Conversion.ResolutionToModelUnits<'d2,'timespan2,'modelTimeUnit> -> engine: EstimationEngine.EstimationEngine<'d,'o1,'o2,'u> -> EstimationEngine.EstimationEngine<'d2,'timespan2,'modelTimeUnit,'u>
module DateMode from Bristlecone.Time
module Conversion from Bristlecone.Time.DateMode
<summary> Conversion functions that translate from one time unit into another. These functions are intended primarily for use in estimation engines when translating from data time to model time. </summary>
module RadiocarbonDates from Bristlecone.Time.DateMode.Conversion
val toYears: from: DateMode.Conversion.ConvertFrom<DatingMethods.Radiocarbon<'u>,float<'u>> -> float<year>
val endCond: EstimationEngine.EndCondition
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
type PalaeoData = CsvProvider<...>
type CsvProvider
<summary>Typed representation of a CSV file.</summary> <param name='Sample'>Location of a CSV sample file or a string containing a sample CSV document.</param> <param name='Separators'>Column delimiter(s). Defaults to <c>,</c>.</param> <param name='InferRows'>Number of rows to use for inference. Defaults to <c>1000</c>. If this is zero, all rows are used.</param> <param name='Schema'>Optional column types, in a comma separated list. Valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c>, <c>string</c>, <c>int?</c>, <c>int64?</c>, <c>bool?</c>, <c>float?</c>, <c>decimal?</c>, <c>date?</c>, <c>datetimeoffset?</c>, <c>timespan?</c>, <c>guid?</c>, <c>int option</c>, <c>int64 option</c>, <c>bool option</c>, <c>float option</c>, <c>decimal option</c>, <c>date option</c>, <c>datetimeoffset option</c>, <c>timespan option</c>, <c>guid option</c> and <c>string option</c>. You can also specify a unit and the name of the column like this: <c>Name (type&lt;unit&gt;)</c>, or you can override only the name. If you don't want to specify all the columns, you can reference the columns by name like this: <c>ColumnName=type</c>.</param> <param name='HasHeaders'>Whether the sample contains the names of the columns as its first line.</param> <param name='IgnoreErrors'>Whether to ignore rows that have the wrong number of columns or which can't be parsed using the inferred or specified schema. Otherwise an exception is thrown when these rows are encountered.</param> <param name='SkipRows'>Skips the first n rows of the CSV file.</param> <param name='AssumeMissingValues'>When set to true, the type provider will assume all columns can have missing values, even if in the provided sample all values are present. Defaults to false.</param> <param name='PreferOptionals'>When set to true, inference will prefer to use the option type instead of nullable types, <c>double.NaN</c> or <c>""</c> for missing values. Defaults to false.</param> <param name='Quote'>The quotation mark (for surrounding values containing the delimiter). Defaults to <c>"</c>.</param> <param name='MissingValues'>The set of strings recognized as missing values specified as a comma-separated string (e.g., "NA,N/A"). Defaults to <c>NaN,NA,N/A,#N/A,:,-,TBA,TBD</c>.</param> <param name='CacheRows'>Whether the rows should be caches so they can be iterated multiple times. Defaults to true. Disable for large datasets.</param> <param name='Culture'>The culture used for parsing numbers and dates. Defaults to the invariant culture.</param> <param name='Encoding'>The encoding used to read the sample. You can specify either the character set name or the codepage number. Defaults to UTF8 for files, and to ISO-8859-1 the for HTTP requests, unless <c>charset</c> is specified in the <c>Content-Type</c> response header.</param> <param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param> <param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource (e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
val data: CsvProvider<...>
CsvProvider<...>.Load(uri: string) : CsvProvider<...>
Loads CSV from the specified uri
CsvProvider<...>.Load(reader: System.IO.TextReader) : CsvProvider<...>
Loads CSV from the specified reader
CsvProvider<...>.Load(stream: System.IO.Stream) : CsvProvider<...>
Loads CSV from the specified stream
val ts: Map<ShortCode.ShortCode,TimeSeries.TimeSeries<float,DatingMethods.RadiocarbonCal,float<cal yr BP>,float<cal yr BP>>>
property StateId.Code: ShortCode.ShortCode with get
property Runtime.CsvFile.Rows: CsvProvider<...>.Row seq with get
<summary> The rows with data </summary>
Multiple items
module Seq from Bristlecone

--------------------
module Seq from Microsoft.FSharp.Collections
val map: mapping: ('T -> 'U) -> source: 'T seq -> 'U seq
val r: CsvProvider<...>.Row
property CsvProvider<...>.Row.Par_betula: decimal with get
Multiple items
val Time<'t> : ModelExpression<'t>

--------------------
module Time from Bristlecone
Multiple items
module TimeSeries from Bristlecone.Time
<summary>Contains functions and types to create and manipulate `TimeSeries` values, which represent observations ordered in time.</summary>

--------------------
type TimeSeries<'T,'date,'timeunit,'timespan> = TimeSeries.TimeSeries<'T,'date,'timeunit,'timespan>
val fromCalibratedRadiocarbonObservations: dataset: TimeSeries.Observation<'a,DatingMethods.RadiocarbonCal> seq -> TimeSeries.TimeSeries<'a,DatingMethods.RadiocarbonCal,float<cal yr BP>,float<cal yr BP>>
property MeasureId.Code: ShortCode.ShortCode with get
property CsvProvider<...>.Row.D15N: decimal with get
Multiple items
module Map from Bristlecone

--------------------
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
val ofList: elements: ('Key * 'T) list -> Map<'Key,'T> (requires comparison)
namespace Bristlecone.Workflow
val logger: (Logging.LogEvent -> unit)
namespace Bristlecone.Logging
module Console from Bristlecone.Logging
<summary> Simple logger to console that prints line-by-line progress and events. </summary>
val logger: nIteration: int<iteration> -> (Logging.LogEvent -> unit)
<summary> A simple console logger. `nIteration` specifies the number of iterations after which to log the current likelihood and parameter values. </summary>
val replicates: int
val cache: string
val orchestrator: Orchestration.OrchestrationAgent<DatingMethods.Radiocarbon<cal yr BP>,float<cal yr BP>,float<cal yr BP>>
module Orchestration from Bristlecone.Workflow
<summary> Queue functions to manage many work packages in parallel. [ Inspired by Tom Petricek: http://fssnip.net/nX ] </summary>
Multiple items
type OrchestrationAgent<'date,'timeunit,'timespan> = new: writeOut: (LogEvent -> unit) * maxSimultaneous: int * retainResults: bool -> OrchestrationAgent<'date,'timeunit,'timespan> member Post: msg: OrchestrationMessage<'date,'timeunit,'timespan> -> unit member TryGetResult: unit -> EstimationResult<'date,'timeunit,'timespan> option
<summary> The `OrchestrationAgent` queues work items of the type `Async&lt;EstimationResult&gt;`, which are run in parallel up to a total of `maxSimultaneous` at one time. </summary>

--------------------
new: writeOut: (Logging.LogEvent -> unit) * maxSimultaneous: int * retainResults: bool -> Orchestration.OrchestrationAgent<'date,'timeunit,'timespan>
module Settings from Sedimentary
namespace System
type Environment = static member Exit: exitCode: int -> unit static member ExpandEnvironmentVariables: name: string -> string static member FailFast: message: string -> unit + 1 overload static member GetCommandLineArgs: unit -> string array static member GetEnvironmentVariable: variable: string -> string + 1 overload static member GetEnvironmentVariables: unit -> IDictionary + 1 overload static member GetFolderPath: folder: SpecialFolder -> string + 1 overload static member GetLogicalDrives: unit -> string array static member SetEnvironmentVariable: variable: string * value: string -> unit + 1 overload static member CommandLine: string ...
<summary>Provides information about, and means to manipulate, the current environment and platform. This class cannot be inherited.</summary>
property System.Environment.ProcessorCount: int with get
<summary>Gets the number of processors available to the current process.</summary>
<returns>The 32-bit signed integer that specifies the number of processors that are available.</returns>
val runAll: unit -> unit
val map2: mapping: ('T1 -> 'T2 -> 'U) -> source1: 'T1 seq -> source2: 'T2 seq -> 'U seq
val async: AsyncBuilder
val result: ModelSystem.EstimationResult<DatingMethods.Radiocarbon<cal yr BP>,float<cal yr BP>,float<cal yr BP>>
val fit: engine: EstimationEngine.EstimationEngine<'a,'b,'modelTimeUnit,'u> -> endCondition: EstimationEngine.EndCondition -> timeSeriesData: CodedMap<TimeSeries<float<'u>,'a,'c,'b>> -> model: ModelSystem.ModelSystem<'modelTimeUnit> -> ModelSystem.EstimationResult<'a,'c,'b> (requires comparison and comparison)
<summary>Fit a time-series model to data.</summary>
<param name="engine">An estimation engine configured and tested for the given model.</param>
<param name="endCondition">The condition at which optimisation should cease.</param>
<param name="timeSeriesData">Time-series dataset that contains a series for each equation in the model system.</param>
<param name="model">A model system of equations, likelihood function, estimatible parameters, and optional measures.</param>
<returns>The result of the model-fitting procedure. If an error occurs, throws an exception.</returns>
property Hypotheses.Hypothesis.Model: ModelSystem.ModelSystem<year> with get
Multiple items
namespace Bristlecone.Data

--------------------
namespace Microsoft.FSharp.Data
module EstimationResult from Bristlecone.Data
val saveAll: dateToString: ('d -> string) -> directory: string -> subject: string -> modelId: string -> thinTraceBy: int option -> result: ModelSystem.EstimationResult<'d,'a,'b> -> unit
<summary>Save the Maximum Likelihood Estimate, trace of the optimisation procedure, and time-series.</summary>
<param name="directory">Relative or absolute directory to save files to</param>
<param name="subject">An identifier for the subject of the test</param>
<param name="modelId">An identifier for the model used</param>
<param name="thinTraceBy">If Some, an integer representing the nth traces to keep from the optimisation trace. If None, does not thin the trace.</param>
<param name="result">The estimation result to save</param>
val d: DatingMethods.Radiocarbon<cal yr BP>
System.Object.ToString() : string
union case Option.None: Option<'T>
val iter: action: ('T -> unit) -> source: 'T seq -> unit
type OrchestrationMessage<'date,'timeunit,'timespan> = | StartWorkPackage of Async<EstimationResult<'date,'timeunit,'timespan>> | StartDependentWorkPackages of Async<EstimationResult<'date,'timeunit,'timespan>> | Finished of EstimationResult<'date,'timeunit,'timespan> | WorkFailed of exn | WorkCancelled
union case Orchestration.OrchestrationMessage.StartWorkPackage: Async<ModelSystem.EstimationResult<'date,'timeunit,'timespan>> -> Orchestration.OrchestrationMessage<'date,'timeunit,'timespan>
member Orchestration.OrchestrationAgent.Post: msg: Orchestration.OrchestrationMessage<'date,'timeunit,'timespan> -> unit

Type something to start searching.