Customising an existing data structure

The key idea behind the library allows what are, to my mind some exciting extensions.

It would be very common, to have your own representations of data. An example of a library with it's own data structures (there are many) might breeze, which is a library for linear algebra in scala.

The below extension method would add line plotting functionality, to all Breeze DenseVectors. What's cool? You don't need to own either Breeze or dedav to make this work.

extension [T: Numeric](l: DenseVector[T])(using plotTarget: PlotTarget)
  def plotLineChart(mods: JsonMod = List()): LineChart =
    l.toArray.plotLineChart(mods)

Give it a go in a project - this turns a breeze vector into a plottable data structure that emits a line chart!

The moment where I figured it might be worth an attempt at at publishing this library was this;

import breeze.stats.distributions._
import Rand.VariableSeed._
import viz.PlotTarget
import viz.vega.plots.ProbabilityDensity

extension (l: HasInverseCdf)(using plotTarget: PlotTarget)
    def plotDensity(mods: Seq[ujson.Value => Unit] = List()): ProbabilityDensity =
        val probs = breeze.linalg.linspace(0.0+1.0/1000.0,1.0-1.0/1000.0,1000)
        val icdfs = probs.map(l.inverseCdf).toScalaVector.zip(probs.toScalaVector)
        val inject = for((i, p) <- icdfs) yield {
            ujson.Obj("u" -> i, "v" -> p)
        }
        val pipeData :ujson.Value => Unit = spec => spec("data")(0) = ujson.Obj("name" -> "points", "values"->inject)
        ProbabilityDensity(List(pipeData, viz.Utils.fillDiv))

We extend the trait HasInverseCdf, and now? Every distribution with an inverse CDF is plottable!

in 12. lines. of. code. It took way longer to write the documentation, than implement that entire class of plots :-).

Gaussian(2,2).plotDensity(Seq(viz.Utils.fillDiv))
// res0: ProbabilityDensity = ProbabilityDensity(
//   mods = List(
//     repl.MdocSession$MdocApp$$Lambda$15157/0x0000000803a90040@2380a02f,
//     viz.Utils$$$Lambda$15140/0x000000080395e840@4b97359d
//   )
// )
LogNormal(1,0.5).plotDensity(Seq(viz.Utils.fillDiv))
// res1: ProbabilityDensity = ProbabilityDensity(
//   mods = List(
//     repl.MdocSession$MdocApp$$Lambda$15157/0x0000000803a90040@3ea27ae8,
//     viz.Utils$$$Lambda$15140/0x000000080395e840@4b97359d
//   )
// )