Scala bindings for plotly.js
plotly-scala is a Scala library able to output JSON that can be passed to plotly.js. Its classes closely follow the API of plotly.js, so that one can use plotly-scala by following the documentation of plotly.js. These classes can be converted to JSON, that can be fed directly to plotly.js.
It runs demos of the plotly.js documentation during its tests, to ensure that it is fine with all their features. That allows it to reliably cover a wide range of the plotly.js features - namely, all the examples of the supported sections of the plotly.js documentation are guaranteed to be fine.
It is published for both scala 2.12 and 2.13.
Table of content
import $ivy.`org.plotly-scala::plotly-almond:0.8.1` import plotly._ import plotly.element._ import plotly.layout._ import plotly.Almond._ val (x, y) = Seq( "Banana" -> 10, "Apple" -> 8, "Grapefruit" -> 5 ).unzip Bar(x, y).plot()
jupyter labextension install jupyterlab-plotly
Add the corresponding dependency to your project, like
libraryDependencies += "org.plotly-scala" %%% "plotly-render" % "0.8.1"
From your code, add some imports for plotly,
import plotly._, element._, layout._, Plotly._
Then define plots like
val x = (0 to 100).map(_ * 0.1) val y1 = x.map(d => 2.0 * d + util.Random.nextGaussian()) val y2 = x.map(math.exp) val plot = Seq( Scatter(x, y1).withName("Approx twice"), Scatter(x, y2).withName("Exp") )
and plot them with
val lay = Layout().withTitle("Curves") plot.plot("plot", lay) // attaches to div element with id 'plot'
Load the corresponding dependency, and some imports, like
import $ivy.`org.plotly-scala::plotly-render:0.8.1` import plotly._, element._, layout._, Plotly._
Then plot things like
val labels = Seq("Banana", "Banano", "Grapefruit") val valuesA = labels.map(_ => util.Random.nextGaussian()) val valuesB = labels.map(_ => 0.5 + util.Random.nextGaussian()) Seq( Bar(labels, valuesA, name = "A"), Bar(labels, valuesB, name = "B") ).plot( title = "Level" )
plotly-scala consists in a bunch of definitions, mostly case classes and sealed class hierarchies, closely following the API of plotly.js. It also contains JSON codecs for those, allowing to convert them to JSON that can be passed straightaway to plotly.js.
Internally, plotly-scala uses circe (along with custom codec derivation mechanisms) to convert things to JSON, then render them. The circe objects don't appear in the plotly-scala API - circe is only used internally. The plotly-scala API only returns JSON strings, that can be passed to plotly.js. In subsequent versions, plotly-scala will likely try to shade circe and its dependencies, or switch to a more lightweight JSON library.
plotly-scala supports the features illustrated in the following sections of the plotly.js documentation:
- Scatter Plots,
- Bubble Charts,
- Line Charts,
- Bar Charts,
- Horizontal Bar Charts,
- Filled Area Plots,
- Time Series,
- Multiple Axes,
- Log Plots,
Some of these are illustrated in the demo page.
Adding support for extra plotly.js features
The following workflow can be followed to add support for extra sections of the plotly.js documentation:
- find the corresponding directory in the source of the plotly.js documentation. These directories can also be found in the sources of plotly-scala, under
plotly-documentation/_posts/plotly_js, if its repository has been cloned with the
- enabling testing of the corresponding documentation section examples in the
DocumentationTestsclass, around this line,
- running the tests with
- add the required fields / class definitions, and possibly codecs, to have the added tests pass.
Battlefield tested since early 2016 at Teads.tv
Released under the LGPL v3 license, copyright 2016-2019 Alexandre Archambault and contributors.
Parts based on the original plotly.js API, which is copyright 2016 Plotly, Inc.