Usage
First import all of the SPlot classes
import xyz.devfortress.splot._
Or in Ammonite-REPL
import $ivy.`xyz.devfortress.splot::splot-core:0.4.0`, xyz.devfortress.splot._
This will bring all of the important implicits into the scope without which this library may not work.
Figure
Central class in the SPlot library is Figure
to which plot elements are added and then displayed.
Every figure constructor parameter is populated with default values and you can just create it like so
val fig = new Figure()
It is likely, however, that you will not be satisfied with defaults and will supply different values for some of them.
For example, following code creates Figure
with custom title, labels on both axis, and parameter to display grid.
val fig = new Figure(
title = "Signal of ...",
xLabel = "t - time in seconds",
yLabel = "Signal strength",
showGrid = true
)
Another common thing to change is figures' domain and range. By default domain and range are
set to None
, which means that their values are automatically derived from added plot elements.
Often, however, you may want to have domain or range fixed. That is acomplished by adding (min, max)
tuples
to Figure.domain|range
values.
val fig = new Figure(
domain = (-10, 10),
range = (0.0, 3.0)
)
Ticks on both axis are automatically derived by means of default functions supplied to xTicks
and yTicks
arguments of Figure
constructor. These functions receive range along corresponding axis and return sequence
of (Double, String)
tuples. First element of these tuples is a position at which tick is to be drawn, and second
is corresponding label. Several utility function are available to make it easier to supply custom ticks.
To disable all ticks you can supply instance of Ticks
created without any arguments.
val fig = new Figure(xTicks = Ticks(), yTicks = Ticks())`
Supplying sequence of numbers or ranges to Ticks(...)
will create ticks at predefined positions
val fig new Figure(
xTicks = Ticks(0, 1, 2, 4, 8, 16),
yTicks = Ticks(0.0 to 10 by 1.5)
)
Plot elements are added to the figure by calling
fig.add(plotElement: PlotElement)
For many plot elements, however, convenience functions exist in Figure
that make adding them much easier.
Line Plot
Like most of the plot elements, line plot is derived from sequence of x-y tuples (Double, Double)
where first
element is coordinate position along the x-axis and second along the y-axis. Thus given a sequence of data points
val data = Seq((1.0, 1.0), (2.0, 1.3), (3.0, 1.1))
You can plot line plot where every two subsequent points are connected by a line using convenience function Figure::plot(...)
fig.plot(data)
By default black color is used for all plot element, line width is one pixel, and line type is a solid line. That can be changed like so
fig.plot(data, lw = 2, color = "blue", lt = "--")
Parameter lw
stands for “line width” and defines width of the line in pixels.
Parameter color
is actually of type java.awt.Color
but following colors can be passed by implicit conversion from strings "red"
, "green"
, "blue"
, "black"
, "cyan"
, "gray"
"lightgray"
, "magenta"
, "orange"
, "pink"
, "white"
, "yellow"
.
Likewise, line type (“lt”) is of type LineType
and can be one of SOLID
, DASHES
, DASHES_AND_DOTS
, DOTS
and that can also be expressed by corresponding strings "-"
, "--"
, "-."
, "."
Alternatively, you can use LinePlot
class, which is a PlotElement
, and add it to the figure like so:
fig.add(LinePlot(data))
Scatter Plot
Scatter plot display data as set of points. It can be added by using PointPlot
class:
fig.add(PointPlot(...))
or using convenience function Figure::scatter(...)
fig.scatter(data)
Several different point types/shapes can be used with it. Default is PointType.Dot
. For example, following will plot scatter-plot
using unfilled circles of radius 9 pixels:
fig.scatter(data, pt = "o", ps = 9)
Parameter pt
stands for “point type”, ps
for “point size”. Like for color, for
point type there should be in scope explicit conversion from string into PointType
instances, which are Dot
,
Cross
, X
, Square
, Diamond
and Circle
and their corresponding string
names "."
, "+"
, "x"
, "s"
, "d"
and "o"
. Square, diamond and circle are drawn as unfilled shapes, which means that they are drawn as outlines
and parameter color
refers to the color of that outline. To make them filled objects one needs to set fc
(fill color)
parameter which by default is set to None
. In addition you can set transparency of the fill color by changing fa
(fill alpha) which varies from 0.0 (full transparency) to 1.0 (fully opaque, default value). This value of alpha however does not affect
transparency of outline. If outline is too obscuring, it can be made filly transparent while fill a semi-transparent like so:
fig.scatter(data, pt = "d", ps = 9, fc = "blue", fa = 0.01, color = new Color(0, 0, 0, 0))
The 4th parameter passed to Color
constructor is alpha; 0 value meaning fully transparent.
PointType.Dot
is a special type drawn as just filled square without outline and setting fa
for such plots
does affect its transparency while fc
parameter has no effect.
ZScatter Plot
Similar to scatter plot, color of the point is derived from supplied colormap and zValue
array.
Rectangle
Rectangle plot is a variant of Shape
plot that draws rectangles. At minimum one needs to supply anchor point (lower
left corner of rectangle), and rectangle width and height.
fig.rectangle(anchor = (5, 6), width = 2, height = 3)
By default rectangle will be drawn as outline of solid blue line with width of one pixel. All of these parameters can be explicitly set
fig.rectangle(
anchor = (5, 6),
width = 2,
height = 3,
lw = 2,
lt = "-.", // dashes and dots
fillColor = "yellow",
alpha = 0.2 // semi-transparent
)
Bar Plot
Bar plot is a composite plot assembled from many rectangles. In order to display properly it is required to pass data sequence sorted along the x-axis. For each point it draws filled rectangle from 0 on the y-axis up to the y value for this point. By default width of these bars/rectangles fills up to the next point, i.e. there are no gaps between bars.
fig.barplot(data)
Default fill color is yellow and edge color is black drawn as solid lines of one pixel width. Fill color is fully opaque. Like for other plots default parameters can be overriden, as in the following example:
fig.barplot(data, color = "cyan", edgeColor = "blue", edgeWidth = 2, alpha = 0.1)
Notice that here color
parameter sets fill color. By setting edgeWidth
to 0 one can remove outline altogether.
Width of the bars and if there is gap between them is controlled by width
parameter which is a function that returns width of the
bar when called. For each bar it receives distance to the next data point and returns distance to be used for drawing current bar.
Default function is identity, which means that bars are drawn edge to edge without any space between bars. Thus we can introduce fixed
width for bars like so
fig.barplot(data, width = _ => 0.7)
and flexible gap between bars like so
fig.barplot(data, width = w => 0.7 * w)
Heat-map Plot
Heatmap like plot is made by adding ZMapPlot
object to the figure or using convenience function map(...)
.
This plot is defined at minimum by supplying f: (Double, Double) => Double
function that maps arbitrary point in xy-plane
into some value and parameters xDomain: (Double, Double)
and yDomain: (Double, Double)
that define rectangular
overarching domain on which supplied function f(x, y)
is assumed to be defined. This domain can farther be shaped by use
of inDomain
function (see below).
At any zoom level for every pixel of the plot x and y coordinates are computed and, assuming that they fall within defined domain,
z value f(x,y)
is computed and a color picked from provided colormap (default is viridis
).Thus,
assuming that f(x,y)
function is defined, the simplest map plot defined on a certain rectangle can be drawn like so
def f(x: Double, y:Double): Double = { ... }
fig.map(f, xDomain = (0, 10), yDomain = (0, 1))
By default at the time of plotting this plot range of the z-values will be recorded and complete color map range will be mapped to
this range. This sometimes can lead to abrupt changes in color when varying configuration parameters of f
function.
To fix mapping of z values to colormap range one can pass explicitly zRange
value. For example, following code maps
range of z-values from 0 to 10 into provided colormap.
fig.map(f, xDomain = (0, 10), yDomain = (0, 1), zRange = (0, 10))
Note that doing so clips color value derived from z-values that fell outsize of this range to the lower and upper bounds of colormap.
Colormap is a function Double => java.awt.Color
that maps numbers in range [0,1]
into some color.
By default map(...)
receives viridis
colormap. The only other available colormap is inferno
.
It can be set like so:
fig.map(f, xDomain = (0, 10), yDomain = (0, 1), colorMap = colormaps.inferno)
Setting inDomain
parameter to custom function allow users to farther restrict domain of the plot and make
it non-rectangular. For example, we can define square domain with round hole of diameter 1 like so:
fig.map(
f, xDomain = (-10, 10), yDomain = (-10, 10),
inDomain = (x, y) => x * x + y * y > 1
)
Shape Plot
Arbitrary closed shapes can be drawn by adding Shape
objects to Figure
. No convenience function exist to aid in their creation.