Interactive visualization tools for Julia
Yet another plotting package?
InteractiveViz is not a replacement for Plots or Makie, but rather a graphics pipeline system developed on top of Makie. It has a few objectives:
- To provide a simple API to visualize large or possibly infinite datasets (tens of millions of data points) easily.
- To enable interactivity, and be responsive even with large amounts of data.
- To render perceptually accurate summaries at large scale, allowing drill down to individual data points.
- To allow generation of data points on demand through a graphics pipeline, requiring computation only at a level of detail appropriate for display at the viewing resolution. Additional data points can be generated on demand when zooming or panning.
This package was partly inspired by the excellent Datashader package available in the Python ecosystem.
This package does not aim to provide comprehensive production quality plotting. It is aimed at interactive exploration of large datasets.
julia>] pkg> add InteractiveViz
InteractiveViz API and internals changed in
v0.4. If you're familiar with the older API, do read through the documentation again. The functionality has not changed much, but the
v0.4 uses the new Makie layout functionality and has improved its internal design to provide a more flexible data source API.
Let's start off visualizing a simple function of one variable:
julia> using InteractiveViz julia> ilines(sin, 0, 100)
This displays the
sin() function with the initial view set to the x-range of 0 to 100. You can however, pan and zoom (as you would do with a normal
GLMakie window) beyond this range.
Let's next try plotting 2 timeseries, each with 10 million points:
julia> ilines(5*sin.(0.02π .* (1:10000000))) julia> ilines!(randn(10000000))
You can zoom and pan to see details:
Next, let us visualize the famous Mandelbrot set:
julia> using InteractiveViz.Demo julia> iheatmap(mandelbrot, -2, 0.66, -1, 1)
Try zooming in to a tiny part of the image, and see the fractal nature of the image render itself dynamically at full resolution!
And how can we forget the Julia set?
julia> iheatmap(julia, -2, 2, -1.75, 1.75; colormap=:magma)
You could of course plot a large heatmap stored in a matrix as well:
julia> iheatmap(range(0, 10; length=1000), range(0, 1; length=10000), randn(1000,10000))
Finally, let's try a scatter plot with ten million points:
julia> iscatter(randn(10_000_000), randn(10_000_000); markersize=3)
and add on another hundred thousand ones:
julia> iscatter!(randn(1_000_000) .- 1, randn(1_000_000) .- 1; color=:black, markersize=4)
Try zooming into this plot and see that it remains responsive as you zoom down to each individual point, or zoom out to get a birds-eye view!
While we haven't documented all the keyword options here, you'll find that all of the plot attributes for Makie work as options in InteractiveViz.
All of Makie's layout API also works as expected:
julia> using GLMakie julia> f = Figure() julia> p1 = iheatmap(f[1,1], julia, -2, 2, -1.75, 1.75; colormap=:magma) julia> p2 = iheatmap(f[2,1], mandelbrot, -2, 0.66, -1, 1) julia> Colorbar(f[1,2], p1.plot) julia> Colorbar(f[2,2], p2.plot) julia> p3 = ilines(f[1,3], sin, 0, 100; axis=(; limits=(0, 100, -1.5, 1.5))) julia> p4 = ilines(f[2,3], range(0, 100; length=10000), randn(10000)) julia> linkxaxes!(p3.axis, p4.axis)
InteractiveViz data sources are subtypes of the abstract
DataSource type. Currently, three abstract subtypes of data sources are defined:
Continuous1Dfor continuous one-dimensional data (e.g. time series),
Continuous2Dfor continuous two-dimensional data (e.g. 2D topography heatmaps), and
PointSetfor discrete points (e.g. scatter plots).
The API to implement for each data source simply consists of two methods:
sample(data::DataSource, xrange::StepRangeLen, yrange::StepRangeLen) limits(data::DataSource)
sample() samples the data source at a finite resolution and within a viewport represented by a
yrange, and returns samples at the display resolution. The return type depends on the type of data source. Sampling a
PointSet results in a
Point2fSet of sample points. Sampling a
Continuous1D results in a
Samples1D of samples at the locations specified by
xrange, or denser. Sampling a
Continuous2D results in a
Samples2D of samples at the locations specified by
limits() returns a tuple
(xmin, xmax, ymin, ymax) of default x and y axis limits for the data. If a limit is not applicable or unknown for the data source,
nothing may be returned for that entry.
The default implementations available include:
Point2fSet: vector of discrete 2D data points.
Samples1D: uniformly sampled 1D data in a vector, automatically interpolated or aggregated, as required.
Samples2D: uniformly sampled 2D data in a vector, automatically interpolated or aggregated, as required.
Function1D: 1D function that generated the data dynamically on demand.
Function2D: 2D function that generated the data dynamically on demand.
New types of data sources may be defined by the user. To use these, the underlying
iviz() function has to be directly called on the data source. The
iscatter() functions are simply convenience wrappers on the