{-# LANGUAGE Strict #-}

module Currycarbon.Calibration.Utils where

import Currycarbon.Types

import qualified Data.Vector.Unboxed as VU
import Data.Maybe (fromMaybe)
import Numeric.SpecFunctions (logBeta)

-- | Rescale a CalPDF so that the sum of the densities is approx. 1.0
normalizeCalPDF :: CalPDF -> CalPDF
normalizeCalPDF :: CalPDF -> CalPDF
normalizeCalPDF (CalPDF String
name Vector YearBCAD
cals Vector Float
dens) = 
    case Vector Float -> Float
forall a. (Unbox a, Num a) => Vector a -> a
VU.sum Vector Float
dens of
      Float
0.0 -> String -> Vector YearBCAD -> Vector Float -> CalPDF
CalPDF String
name Vector YearBCAD
cals Vector Float
dens -- product calibration can yield empty calPDFs
      Float
s   -> String -> Vector YearBCAD -> Vector Float -> CalPDF
CalPDF String
name Vector YearBCAD
cals (Vector Float -> CalPDF) -> Vector Float -> CalPDF
forall a b. (a -> b) -> a -> b
$ (Float -> Float) -> Vector Float -> Vector Float
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map (Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/Float
s) Vector Float
dens

-- | get the density of a normal distribution at a point x
dnorm :: Float -> Float -> Float -> Float 
dnorm :: Float -> Float -> Float -> Float
dnorm Float
mu Float
sigma Float
x = 
    let a :: Float
a = Float -> Float
forall a. Fractional a => a -> a
recip (Float -> Float
forall a. Floating a => a -> a
sqrt (Float
2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
forall a. Floating a => a
pi Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
sigma2))
        b :: Float
b = Float -> Float
forall a. Floating a => a -> a
exp (-Float
c2 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
sigma2))
        c :: Float
c = Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
mu
        c2 :: Float
c2 = Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c
        sigma2 :: Float
sigma2 = Float
sigma Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
sigma
    in Float
aFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
b
    -- alternative implemenation with the statistics package:
    -- import Statistics.Distribution (density)
    -- realToFrac $ density (normalDistr (realToFrac mu) (realToFrac sigma)) (realToFrac x)

-- | get the density of student's-t distribution at a point x
dt :: Double -> Float -> Float
dt :: Double -> Float -> Float
dt Double
dof Float
x =
    let xDouble :: Double
xDouble = Float -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Float
x
        logDensityUnscaled :: Double
logDensityUnscaled = Double -> Double
forall a. Floating a => a -> a
log (Double
dof Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
dof Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
xDoubleDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
xDouble)) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
dof)) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double -> Double
logBeta Double
0.5 (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dof)
    in Double -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Double -> Float) -> Double -> Float
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
exp Double
logDensityUnscaled Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
sqrt Double
dof
    -- alternative implemenation with the statistics package:
    -- import Statistics.Distribution.StudentT (studentT)
    -- realToFrac $ density (studentT (realToFrac dof)) (realToFrac x) -- dof: number of degrees of freedom

isOutsideRangeOfCalCurve :: CalCurveBP -> UncalC14 -> Bool
isOutsideRangeOfCalCurve :: CalCurveBP -> UncalC14 -> Bool
isOutsideRangeOfCalCurve (CalCurveBP Vector YearBP
_ Vector YearBP
uncals Vector YearBP
_) (UncalC14 String
_ YearBP
age YearBP
_) = 
    YearBP
age YearBP -> YearBP -> Bool
forall a. Ord a => a -> a -> Bool
< Vector YearBP -> YearBP
forall a. (Unbox a, Ord a) => Vector a -> a
VU.minimum Vector YearBP
uncals Bool -> Bool -> Bool
|| YearBP
age YearBP -> YearBP -> Bool
forall a. Ord a => a -> a -> Bool
> Vector YearBP -> YearBP
forall a. (Unbox a, Ord a) => Vector a -> a
VU.maximum Vector YearBP
uncals

-- | Take an uncalibrated date and a raw calibration curve and return
-- the relevant segment of the calibration curve
getRelevantCalCurveSegment :: UncalC14 -> CalCurveBP -> CalCurveBP
getRelevantCalCurveSegment :: UncalC14 -> CalCurveBP -> CalCurveBP
getRelevantCalCurveSegment (UncalC14 String
_ YearBP
mean YearBP
std) (CalCurveBP Vector YearBP
cals Vector YearBP
uncals Vector YearBP
sigmas) =
    let start :: YearBP
start = YearBP
meanYearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
+YearBP
6YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
*YearBP
std
        stop :: YearBP
stop = YearBP
meanYearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
-YearBP
6YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
*YearBP
std
        startIndex :: YearBCAD
startIndex = YearBCAD -> Maybe YearBCAD -> YearBCAD
forall a. a -> Maybe a -> a
fromMaybe YearBCAD
0 (Maybe YearBCAD -> YearBCAD) -> Maybe YearBCAD -> YearBCAD
forall a b. (a -> b) -> a -> b
$ (YearBP -> Bool) -> Vector YearBP -> Maybe YearBCAD
forall a. Unbox a => (a -> Bool) -> Vector a -> Maybe YearBCAD
VU.findIndex (YearBP -> YearBP -> Bool
forall a. Ord a => a -> a -> Bool
<= YearBP
start) Vector YearBP
uncals
        stopIndex :: YearBCAD
stopIndex = (Vector YearBP -> YearBCAD
forall a. Unbox a => Vector a -> YearBCAD
VU.length Vector YearBP
uncals YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
- YearBCAD
1) YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
- YearBCAD -> Maybe YearBCAD -> YearBCAD
forall a. a -> Maybe a -> a
fromMaybe YearBCAD
0 ((YearBP -> Bool) -> Vector YearBP -> Maybe YearBCAD
forall a. Unbox a => (a -> Bool) -> Vector a -> Maybe YearBCAD
VU.findIndex (YearBP -> YearBP -> Bool
forall a. Ord a => a -> a -> Bool
>= YearBP
stop) (Vector YearBP -> Maybe YearBCAD)
-> Vector YearBP -> Maybe YearBCAD
forall a b. (a -> b) -> a -> b
$ Vector YearBP -> Vector YearBP
forall a. Unbox a => Vector a -> Vector a
VU.reverse Vector YearBP
uncals)
        toIndex :: YearBCAD
toIndex = YearBCAD
stopIndex YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
- YearBCAD
startIndex
    in Vector YearBP -> Vector YearBP -> Vector YearBP -> CalCurveBP
CalCurveBP (YearBCAD -> YearBCAD -> Vector YearBP -> Vector YearBP
forall a. Unbox a => YearBCAD -> YearBCAD -> Vector a -> Vector a
VU.slice YearBCAD
startIndex YearBCAD
toIndex Vector YearBP
cals) (YearBCAD -> YearBCAD -> Vector YearBP -> Vector YearBP
forall a. Unbox a => YearBCAD -> YearBCAD -> Vector a -> Vector a
VU.slice YearBCAD
startIndex YearBCAD
toIndex Vector YearBP
uncals) (YearBCAD -> YearBCAD -> Vector YearBP -> Vector YearBP
forall a. Unbox a => YearBCAD -> YearBCAD -> Vector a -> Vector a
VU.slice YearBCAD
startIndex YearBCAD
toIndex Vector YearBP
sigmas)

-- | Modify a calibration curve (segment) with multiple optional steps, 
-- including interpolation and transforming dates to BC/AD format
prepareCalCurveSegment :: Bool -> CalCurveBP -> CalCurveBCAD
prepareCalCurveSegment :: Bool -> CalCurveBP -> CalCurveBCAD
prepareCalCurveSegment Bool
interpolate CalCurveBP
calCurve =
    CalCurveBP -> CalCurveBCAD
makeBCADCalCurve (CalCurveBP -> CalCurveBCAD) -> CalCurveBP -> CalCurveBCAD
forall a b. (a -> b) -> a -> b
$ if Bool
interpolate then CalCurveBP -> CalCurveBP
interpolateCalCurve CalCurveBP
calCurve else CalCurveBP
calCurve

makeBCADCalCurve :: CalCurveBP -> CalCurveBCAD
makeBCADCalCurve :: CalCurveBP -> CalCurveBCAD
makeBCADCalCurve (CalCurveBP Vector YearBP
cals Vector YearBP
uncals Vector YearBP
sigmas) = Vector YearBCAD -> Vector YearBCAD -> Vector YearBP -> CalCurveBCAD
CalCurveBCAD (Vector YearBP -> Vector YearBCAD
vectorBPToBCAD Vector YearBP
cals) (Vector YearBP -> Vector YearBCAD
vectorBPToBCAD Vector YearBP
uncals) Vector YearBP
sigmas

vectorBPToBCAD :: VU.Vector YearBP -> VU.Vector YearBCAD
vectorBPToBCAD :: Vector YearBP -> Vector YearBCAD
vectorBPToBCAD = (YearBP -> YearBCAD) -> Vector YearBP -> Vector YearBCAD
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map (\YearBP
x -> -(YearBP -> YearBCAD
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
x) YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
+ YearBCAD
1950)

interpolateCalCurve :: CalCurveBP -> CalCurveBP
interpolateCalCurve :: CalCurveBP -> CalCurveBP
interpolateCalCurve (CalCurveBP Vector YearBP
cals Vector YearBP
uncals Vector YearBP
sigmas) =
    let obs :: Vector (YearBP, YearBP, YearBP)
obs = Vector YearBP
-> Vector YearBP
-> Vector YearBP
-> Vector (YearBP, YearBP, YearBP)
forall a b c.
(Unbox a, Unbox b, Unbox c) =>
Vector a -> Vector b -> Vector c -> Vector (a, b, c)
VU.zip3 Vector YearBP
cals Vector YearBP
uncals Vector YearBP
sigmas
        timeWindows :: Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
timeWindows = Vector (YearBP, YearBP, YearBP)
-> Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
getTimeWindows Vector (YearBP, YearBP, YearBP)
obs
        obsFilled :: Vector (YearBP, YearBP, YearBP)
obsFilled = (((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
 -> Vector (YearBP, YearBP, YearBP))
-> Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
-> Vector (YearBP, YearBP, YearBP)
forall a b.
(Unbox a, Unbox b) =>
(a -> Vector b) -> Vector a -> Vector b
VU.concatMap ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
-> Vector (YearBP, YearBP, YearBP)
fillTimeWindows Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
timeWindows
    in (Vector YearBP -> Vector YearBP -> Vector YearBP -> CalCurveBP)
-> (Vector YearBP, Vector YearBP, Vector YearBP) -> CalCurveBP
forall a b c d. (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 Vector YearBP -> Vector YearBP -> Vector YearBP -> CalCurveBP
CalCurveBP ((Vector YearBP, Vector YearBP, Vector YearBP) -> CalCurveBP)
-> (Vector YearBP, Vector YearBP, Vector YearBP) -> CalCurveBP
forall a b. (a -> b) -> a -> b
$ Vector (YearBP, YearBP, YearBP)
-> (Vector YearBP, Vector YearBP, Vector YearBP)
forall a b c.
(Unbox a, Unbox b, Unbox c) =>
Vector (a, b, c) -> (Vector a, Vector b, Vector c)
VU.unzip3 Vector (YearBP, YearBP, YearBP)
obsFilled
    where
        getTimeWindows :: VU.Vector (YearBP,YearBP,YearRange) -> VU.Vector ((YearBP,YearBP,YearRange),(YearBP,YearBP,YearRange))
        getTimeWindows :: Vector (YearBP, YearBP, YearBP)
-> Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
getTimeWindows Vector (YearBP, YearBP, YearBP)
xs = ((YearBP, YearBP, YearBP)
 -> (YearBP, YearBP, YearBP)
 -> ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP)))
-> Vector (YearBP, YearBP, YearBP)
-> Vector (YearBP, YearBP, YearBP)
-> Vector ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
forall a b c.
(Unbox a, Unbox b, Unbox c) =>
(a -> b -> c) -> Vector a -> Vector b -> Vector c
VU.zipWith (,) (Vector (YearBP, YearBP, YearBP) -> Vector (YearBP, YearBP, YearBP)
forall a. Unbox a => Vector a -> Vector a
VU.init Vector (YearBP, YearBP, YearBP)
xs) (Vector (YearBP, YearBP, YearBP) -> Vector (YearBP, YearBP, YearBP)
forall a. Unbox a => Vector a -> Vector a
VU.tail Vector (YearBP, YearBP, YearBP)
xs)
        fillTimeWindows :: ((YearBP,YearBP,YearRange),(YearBP,YearBP,YearRange)) -> VU.Vector (YearBP,YearBP,YearRange)
        fillTimeWindows :: ((YearBP, YearBP, YearBP), (YearBP, YearBP, YearBP))
-> Vector (YearBP, YearBP, YearBP)
fillTimeWindows ((YearBP
calbp1,YearBP
bp1,YearBP
sigma1),(YearBP
calbp2,YearBP
bp2,YearBP
sigma2)) =
            if YearBP
calbp1 YearBP -> YearBP -> Bool
forall a. Eq a => a -> a -> Bool
== YearBP
calbp2 Bool -> Bool -> Bool
|| YearBP
calbp1YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
+YearBP
1 YearBP -> YearBP -> Bool
forall a. Eq a => a -> a -> Bool
== YearBP
calbp2 Bool -> Bool -> Bool
|| YearBP
calbp1YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
-YearBP
1 YearBP -> YearBP -> Bool
forall a. Eq a => a -> a -> Bool
== YearBP
calbp2 
            then (YearBP, YearBP, YearBP) -> Vector (YearBP, YearBP, YearBP)
forall a. Unbox a => a -> Vector a
VU.singleton (YearBP
calbp1,YearBP
bp1,YearBP
sigma1)
            else 
                let newCals :: Vector YearBP
newCals = [YearBP] -> Vector YearBP
forall a. Unbox a => [a] -> Vector a
VU.fromList [YearBP
calbp1,YearBP
calbp1YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
-YearBP
1..YearBP
calbp2YearBP -> YearBP -> YearBP
forall a. Num a => a -> a -> a
+YearBP
1] -- range definition like this to trigger counting down
                    newBPs :: Vector YearBP
newBPs = (YearBP -> YearBP) -> Vector YearBP -> Vector YearBP
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map ((YearBP, YearBP) -> YearBP
forall a b. (a, b) -> b
snd ((YearBP, YearBP) -> YearBP)
-> (YearBP -> (YearBP, YearBP)) -> YearBP -> YearBP
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (YearBP, YearBP) -> (YearBP, YearBP) -> YearBP -> (YearBP, YearBP)
getInBetweenPointsInt (YearBP
calbp1,YearBP
bp1) (YearBP
calbp2,YearBP
bp2)) Vector YearBP
newCals
                    newSigmas :: Vector YearBP
newSigmas = (YearBP -> YearBP) -> Vector YearBP -> Vector YearBP
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map ((YearBP, YearBP) -> YearBP
forall a b. (a, b) -> b
snd ((YearBP, YearBP) -> YearBP)
-> (YearBP -> (YearBP, YearBP)) -> YearBP -> YearBP
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (YearBP, YearBP) -> (YearBP, YearBP) -> YearBP -> (YearBP, YearBP)
getInBetweenPointsInt (YearBP
calbp1,YearBP
sigma1) (YearBP
calbp2,YearBP
sigma2)) Vector YearBP
newCals
                in Vector YearBP
-> Vector YearBP
-> Vector YearBP
-> Vector (YearBP, YearBP, YearBP)
forall a b c.
(Unbox a, Unbox b, Unbox c) =>
Vector a -> Vector b -> Vector c -> Vector (a, b, c)
VU.zip3 Vector YearBP
newCals Vector YearBP
newBPs Vector YearBP
newSigmas
        getInBetweenPointsInt :: (Word, Word) -> (Word, Word) -> Word -> (Word, Word)
        getInBetweenPointsInt :: (YearBP, YearBP) -> (YearBP, YearBP) -> YearBP -> (YearBP, YearBP)
getInBetweenPointsInt (YearBP
x1,YearBP
y1) (YearBP
x2,YearBP
y2) YearBP
xPred =
            let (Float
_,Float
yPred) = (Float, Float) -> (Float, Float) -> Float -> (Float, Float)
getInBetweenPoints (YearBP -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
x1,YearBP -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
y1) (YearBP -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
x2,YearBP -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
y2) (Float -> (Float, Float)) -> Float -> (Float, Float)
forall a b. (a -> b) -> a -> b
$ YearBP -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral YearBP
xPred
            in (YearBP
xPred, Float -> YearBP
forall a b. (RealFrac a, Integral b) => a -> b
round Float
yPred)
        getInBetweenPoints :: (Float, Float) -> (Float, Float) -> Float -> (Float, Float)
        getInBetweenPoints :: (Float, Float) -> (Float, Float) -> Float -> (Float, Float)
getInBetweenPoints (Float
x1,Float
y1) (Float
x2,Float
y2) Float
xPred =
            let yDiff :: Float
yDiff = Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1
                xDiff :: Float
xDiff = Float -> Float
forall a. Num a => a -> a
abs (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float
x1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x2
                yDiffPerxDiff :: Float
yDiffPerxDiff = Float
yDiffFloat -> Float -> Float
forall a. Fractional a => a -> a -> a
/Float
xDiff
                xPredRel :: Float
xPredRel = Float
x1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
xPred
            in (Float
xPred, Float
y1 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
xPredRel Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
yDiffPerxDiff)
        uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
        uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 a -> b -> c -> d
f ~(a
a,b
b,c
c) = a -> b -> c -> d
f a
a b
b c
c

trimLowDensityEdgesCalPDF :: CalPDF -> CalPDF
trimLowDensityEdgesCalPDF :: CalPDF -> CalPDF
trimLowDensityEdgesCalPDF (CalPDF String
name Vector YearBCAD
cals Vector Float
dens) =
    let firstAboveThreshold :: YearBCAD
firstAboveThreshold = YearBCAD -> Maybe YearBCAD -> YearBCAD
forall a. a -> Maybe a -> a
fromMaybe YearBCAD
0 ((Float -> Bool) -> Vector Float -> Maybe YearBCAD
forall a. Unbox a => (a -> Bool) -> Vector a -> Maybe YearBCAD
VU.findIndex (Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.00001) Vector Float
dens)
        lastAboveThreshold :: YearBCAD
lastAboveThreshold = YearBCAD -> Maybe YearBCAD -> YearBCAD
forall a. a -> Maybe a -> a
fromMaybe YearBCAD
0 ((Float -> Bool) -> Vector Float -> Maybe YearBCAD
forall a. Unbox a => (a -> Bool) -> Vector a -> Maybe YearBCAD
VU.findIndex (Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.00001) (Vector Float -> Maybe YearBCAD) -> Vector Float -> Maybe YearBCAD
forall a b. (a -> b) -> a -> b
$ Vector Float -> Vector Float
forall a. Unbox a => Vector a -> Vector a
VU.reverse Vector Float
dens)
        untilLastAboveThreshold :: YearBCAD
untilLastAboveThreshold = Vector Float -> YearBCAD
forall a. Unbox a => Vector a -> YearBCAD
VU.length Vector Float
dens YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
- YearBCAD
firstAboveThreshold YearBCAD -> YearBCAD -> YearBCAD
forall a. Num a => a -> a -> a
- YearBCAD
lastAboveThreshold
        calsSlice :: Vector YearBCAD
calsSlice = YearBCAD -> YearBCAD -> Vector YearBCAD -> Vector YearBCAD
forall a. Unbox a => YearBCAD -> YearBCAD -> Vector a -> Vector a
VU.slice YearBCAD
firstAboveThreshold YearBCAD
untilLastAboveThreshold Vector YearBCAD
cals
        densSlice :: Vector Float
densSlice = YearBCAD -> YearBCAD -> Vector Float -> Vector Float
forall a. Unbox a => YearBCAD -> YearBCAD -> Vector a -> Vector a
VU.slice YearBCAD
firstAboveThreshold YearBCAD
untilLastAboveThreshold Vector Float
dens
    in String -> Vector YearBCAD -> Vector Float -> CalPDF
CalPDF String
name Vector YearBCAD
calsSlice Vector Float
densSlice