packages feed

currycarbon-0.4.0.0: src/Currycarbon/Calibration/Bchron.hs

{-# LANGUAGE Strict #-}

module Currycarbon.Calibration.Bchron (calibrateDateBchron) where

import           Currycarbon.Calibration.Utils
import           Currycarbon.Parsers
import           Currycarbon.Types
import           Currycarbon.Utils

import qualified Data.Vector.Unboxed           as VU

-- | Intercept calibration as implemented in the Bchron R package (see 'Bchron')
calibrateDateBchron :: CalibrationDistribution -> CalibrateDatesConf -> CalCurveBP -> UncalC14 -> Either CurrycarbonException CalPDF
calibrateDateBchron distr (CalibrateDatesConf allowOutside interpolate trimCurve trimDens) calCurve uncalC14@(UncalC14 name age ageSd) =
    if not allowOutside && isOutsideRangeOfCalCurve calCurve uncalC14
    then Left $ CurrycarbonCalibrationRangeException $ renderUncalC14 uncalC14
    else
        let rawCalCurveSegment = if trimCurve
                                 then getRelevantCalCurveSegment uncalC14 calCurve
                                 else calCurve
            CalCurveBCAD cals mus tau1s = prepareCalCurveSegment interpolate rawCalCurveSegment
            ageDouble = -(fromIntegral age)+1950
            ageSd2Double = fromIntegral $ ageSd*ageSd
            musDouble = VU.map fromIntegral mus
            tau1sDouble = VU.map fromIntegral tau1s
            dens = case distr of
                NormalDist ->
                    VU.zipWith (\mu tau1 -> dnorm 0 1 ((ageDouble - mu) / sqrt (ageSd2Double + tau1 * tau1))) musDouble tau1sDouble
                StudentTDist degreesOfFreedom ->
                    VU.zipWith (\mu tau1 -> dt degreesOfFreedom ((ageDouble - mu) / sqrt (ageSd2Double + tau1 * tau1))) musDouble tau1sDouble
            calPDF = CalPDF name cals dens
            res = if trimDens
                  then trimLowDensityEdgesCalPDF $ normalizeCalPDF calPDF
                  else normalizeCalPDF calPDF
        in Right res