Merge pull request #135 from QURIresearch/sparklines-2

Refactored Sparklines.res
This commit is contained in:
Quinn 2022-03-29 17:04:20 -04:00 committed by GitHub
commit c74f6618ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 26 deletions

View File

@ -22,13 +22,12 @@ describe("Normal distribution with sparklines", () => {
let normalDistAtMean5: SymbolicDistTypes.normal = {mean: 5.0, stdev: 2.0}
let normalDistAtMean10: SymbolicDistTypes.normal = {mean: 10.0, stdev: 2.0}
let range20Float = E.A.rangeFloat(0, 20) // [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,]
let range20Float = E.A.rangeFloat(0, 20) // [0.0,1.0,2.0,3.0,4.0,...19.0,]
let pdfNormalDistAtMean5 = x => Normal.pdf(x, normalDistAtMean5)
let sparklineMean5 = pdfImage(pdfNormalDistAtMean5, range20Float)
makeTest("mean=5", Sparklines.create(sparklineMean5, ()), `▁▂▃▅███▅▃▂▁▁▁▁▁▁▁▁▁▁▁`)
let sparklineMean15 = normalDistAtMean5 -> parameterWiseAdditionHelper(normalDistAtMean10) -> pdfImage(range20Float)
// let sparklineMean15 = pdfImage(pdfNormalDistAtMean15, range20Float)
makeTest("parameter-wise addition of two normal distributions", Sparklines.create(sparklineMean15, ()), `▁▁▁▁▁▁▁▁▁▁▂▃▅▇███▇▅▃▂`)
})

View File

@ -1,5 +1,4 @@
open Rationale.Function.Infix
module FloatFloatMap = {
module Id = Belt.Id.MakeComparable({
type t = float
@ -87,6 +86,11 @@ module O = {
let max = compare(\">")
}
module O2 = {
let default = (a, b) => O.default(b, a)
let toExn = (a, b) => O.toExn(b, a)
}
/* Functions */
module F = {
let apply = (a, e) => a |> e
@ -269,7 +273,8 @@ module A = {
))
|> Rationale.Result.return
}
let rangeFloat = (start, stop) => start -> Belt.Array.rangeBy(stop, ~step=1) -> (arr => fmap(Belt.Int.toFloat, arr))
let rangeFloat = (~step=1, start, stop) =>
Belt.Array.rangeBy(start, stop, ~step) |> fmap(Belt.Int.toFloat)
// This zips while taking the longest elements of each array.
let zipMaxLength = (array1, array2) => {
@ -323,8 +328,8 @@ module A = {
| r => Some(r)
}
)
let filter = (o, e) => Js.Array.filter(o, e)
let joinWith = (fill, arr) => Js.Array.joinWith(fill, arr)
let filter = Js.Array.filter
let joinWith = Js.Array.joinWith
module O = {
let concatSomes = (optionals: array<option<'a>>): array<'a> =>
@ -407,6 +412,7 @@ module A = {
: {
let _ = Js.Array.push(element, continuous)
}
()
})
@ -436,6 +442,11 @@ module A = {
}
}
module A2 = {
let fmap = (a, b) => Array.map(b, a)
let joinWith = (a, b) => A.joinWith(b, a)
}
module JsArray = {
let concatSomes = (optionals: Js.Array.t<option<'a>>): Js.Array.t<'a> =>
optionals

View File

@ -3,26 +3,24 @@
// Omitting rgb "fire" style, so no `chalk` dependency
// Omitting: NaN handling, special consideration for constant data.
let create = (
numbers: array<float>,
~minimum=?,
~maximum=?,
()
) => {
let ticks = [`▁`, `▂`, `▃`, `▄`, `▅`, `▆`, `▇`, `█`]
let ticks = [`▁`, `▂`, `▃`, `▄`, `▅`, `▆`, `▇`, `█`]
let minimum = E.O.default(Js.Math.minMany_float(numbers), minimum)
let maximum = E.O.default(Js.Math.maxMany_float(numbers), maximum)
let _ticksLength = E.A.length(ticks)
let toHeight = (number: float) => {
let tickIndex = Js.Math.ceil_int((number /. maximum) *. (ticks -> Belt.Array.length -> Belt.Int.toFloat)) - 1
let tickIndex = if maximum == 0.0 || tickIndex < 0 {
0
} else {
tickIndex
}
ticks[tickIndex]
}
toHeight -> E.A.fmap(numbers) -> (arr => E.A.joinWith("", arr))
let _heightToTickIndex = (maximum: float, v: float) => {
let suggestedTickIndex = Js.Math.ceil_int(v /. maximum *. Belt.Int.toFloat(_ticksLength)) - 1
max(suggestedTickIndex, 0)
}
let create = (relativeHeights: array<float>, ~maximum=?, ()) => {
if E.A.length(relativeHeights) === 0 {
""
} else {
let maximum = maximum->E.O2.default(E.A.max(relativeHeights)->E.O2.toExn(""))
relativeHeights
->E.A2.fmap(_heightToTickIndex(maximum))
->E.A2.fmap(r => E.A.get(ticks, r)->E.O2.toExn(""))
->E.A2.joinWith("")
}
}