Workflow

You need a plot target in place, and then we're ready to plot some data. The idea of the library is to wrap vega by simply treating a chart spec as a JSON object.

The library exposes the vega examples and vega lite examples convieniently as case classes. The class names correspond to the title of the charts (with some special characters removed).

Suggested Workflow

  1. Identify a plot which looks similar to your desired visualisation
  2. Customise it, by modifiying the JSON spec to be your desired visualisation

As always... lean into vega;

The Vega Editor

Visualisation as JSON

We can easily manipulate JSON objects using ujson.

My worflow cascade;

  1. Pipe "raw" data into a vega example
  2. Record a list of modifiers which were useful modifications to an example for re-use... (or just use the example as is)
  3. Spec has been modified enough that a list of modifiers is confusing. Extend the WithBaseSpec class directly via a file or resource (see "Custom.scala"). Then pipe data into it.

Some Concepts

Each "plot" is a case class which accepts a list of "modifiers". Each case class has the signature accepting a single argument of type;

Seq[ujson.Value => Unit] 

i.e. a list of functions which modifiy a ujson.Value This signature appears often enough that it is aliased as;

type JsonMod = Seq[ujson.Value => Unit]

Each time a plot "case class" (e.g. BarPlot) is created, each of these functions is applied to a "base spec". To start with, a base spec will be an example from the vega website). The signature of viz.vega.plots.SimpleBarChart() is

case class BarChart(override val mods : JsonMod=List())(using PlotTarget) extends FromUrl(SpecUrl.BarChart)

The constiuents of this definition are;

What that means, is that to add a title, we need to read the vega docs. To skip some steps, try...

SimpleBarChartLite(List(spec => spec("title") = "Got Viz?"))

We'll revisit this in more detail below. Crucially, to know where to add stuff to the spec, you're going to need the vega documentation.

Vega documentation

Vega Lite documentation

Finally, a small number of "helpers" appear often enough that they are honoured with an implementation in the library;

SunburstDrag(List(viz.Utils.fillDiv, viz.Utils.fixDefaultDataUrl))

"Spec Customisation"

Is one level of abstraction deeper.

The core promise of the library, is that it wraps Vega. It goes one further step, by making the "examples" on the vega website, easy to plot, and then customise.

viz.vega.plots.LineChartLite(
    List(
        viz.Utils.fixDefaultDataUrl
    )
)
// res1: LineChartLite = LineChartLite(mods = List(Fix default data url))

As we've changed the home of the chart (which no longer is on the vega lite examples homepage), we also need to adapt it's data url to point to the right place, else data loading will fail. It's not a bad excercise to allow that failure.

This is our hint on how we're going to manage minor modifications to plots.

Here, we have the line chart example from vega lite. viz.vega.plots.xxx contains all the examples on the vega, and vega-lite websites. vega-lite charts have "lite" appended.

Someone was apparently crazy enough to implement pacman in vega. As "proof" that we really did all the examples, and for your gaming pleasure.

viz.vega.plots.Pacman()
// res3: Pacman = Pacman(mods = List())

More seriously though, this library is targeted at "work".

We need a way to customise charts, which we've hinted at above, by providing a list of "modifiers". A very common customisation, is to want to display your own data (!), from the JVM / ammonite / scala runtime, in the chart. Conceptually this is no different from all the other modification we will make - just change the JSON object.