Makie Demo

using WebSockets, WebIO, Colors, ImageMagick
using CSSUtil, Makie
using ImageFiltering, JSExpr
using Base64, FixedPointNumbers
using ImageTransformations

1. Goals

  • Interactivity
  • High Performance
  • Easy Syntax
  • Inbuild Widgets
  • sane processing pipeline

2. Recipes

  • final API still in flux, but everything is a recipe in Makie
  • backwards compatibility to Plots.jl

3. Theming

  • every attribute is theme-able
using MakieThemes, AbstractPlotting, Makie, MakieThemes
Makie.hbox(
  Makie.vbox(show_ggthemr(:light), show_ggthemr(:pale)),
	Makie.vbox(show_ggthemr(:fresh), show_ggthemr(:sea)),
)
9.9s
GLMakie (Julia)GLMakie compile
using CSV, StatsMakie
using Makie: vbox, hbox
data_folder = joinpath(dirname(pathof(MakieThemes)), "..", "data")
for dataset  (:www, :drivers, :mtcars, :diamonds)
  data = CSV.read(
    joinpath(data_folder, string(dataset, ".tsv")), 
    delim = '\t', allowmissing = :none
  )
  @eval $(dataset) = $data
end

AbstractPlotting.set_theme!(ggthemr(:fresh))

p1 = scatterlines(
  Data(www), :Minute, :Users,
  Group(color = :Measure, marker = :Measure),
  markersize = 2
)

p2 = plot(
  density, Data(mtcars),
  :mpg, Group(color = :cyl)
)

p3 = plot(
  Position.stack, histogram, Data(diamonds),
  :price, Group(color = :cut)
)

p4 = boxplot(Data(drivers), :Year, :Deaths);

vbox(hbox(p1, p2), hbox(p3, p4))
using LinearAlgebra

n = 20
f   = (x,y,z) -> x*exp(cos(y)*z)
∇f  = (x,y,z) -> Point3f0(exp(cos(y)*z), -sin(y)*z*x*exp(cos(y)*z), x*cos(y)*exp(cos(y)*z))
∇ˢf = (x,y,z) -> ∇f(x,y,z) - Point3f0(x,y,z)*dot(Point3f0(x,y,z), ∇f(x,y,z))

θ = [0;(0.5:n-0.5)/n;1]
φ = [(0:2n-2)*2/(2n-1);2]
x = [cospi(φ)*sinpi(θ) for θ in θ, φ in φ]
y = [sinpi(φ)*sinpi(θ) for θ in θ, φ in φ]
z = [cospi(θ) for θ in θ, φ in φ]

pts = vec(Point3f0.(x, y, z))
∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0
Makie.surface(x, y, z, resolution = (800,800))
arrows!(pts, ∇ˢF, arrowsize = 0.04, linecolor = (:white, 0.6), linewidth = 1)

4. Interaction

1.0s
GLMakie (Julia)GLMakie compile
AbstractPlotting.set_theme!() # reset theme
function lorenz(t0, a, b, c, h)
     Point3f0(
         t0[1] + h * a * (t0[2] - t0[1]),
         t0[2] + h * (t0[1] * (b - t0[3]) - t0[2]),
         t0[3] + h * (t0[1] * t0[2] - c * t0[3]),
     )
end
 # step through the `time`
 function lorenz(array::Vector, a = 5.0 ,b = 2.0, c = 6.0, d = 0.01)
     t0 = Point3f0(0.1, 0, 0)
     for i = eachindex(array)
         t0 = lorenz(t0, a,b,c,d)
         array[i] = t0
     end
     array
 end
a = Interact.slider(0f0:50f0, label = "a", value = 13)
b = Interact.slider(-20f0:20f0, label = "b", value = 10)
c = Interact.slider(0f0:20f0, label = "c", value = 2)
d = Interact.slider(LinRange(0.0, 0.02, 100), label = "d", value = 0.01676)
scales = Interact.slider(LinRange(0.01, 0.5, 100), label = "scale", start = 0.1)
rotation = Interact.slider(LinRange(0, 2pi, 360), label = "rotation")
mcolor = widget(colorant"red")

n1, n2 = 18, 30
N = n1*n2
args_n = observe.((a, b, c, d))
v0 = lorenz(zeros(Point3f0, N), to_value.(args_n)...)
positions = lift(lorenz, Makie.Node(v0), args_n...)
mscene = meshscatter(
  positions,
  markersize = scales,
  intensity = collect(range(0f0, stop = 1f0, length = length(positions[]))),
  color = mcolor, center = false
)
center!(mscene)
lastval = Ref(rotation[])
on(rotation) do x
  global lastval
  rotate_cam!(mscene, lastval[] - x, 0.0, 0.0)
  lastval[] = x
end
upsignal = Observables.async_latest(lift(positions, observe(rotation), mcolor, observe(scales)) do a...
end)
up_scene = lift(x-> Makie.GLMakie.scene2image(mscene), upsignal)
CSSUtil.vbox(a, b, c, d, scales, rotation, mcolor, up_scene)

5. Makie & Cairo backend without GPU

using AbstractPlotting, CairoMakie
r = range(-10, stop = 10, length = 512)
z = ((x, y)-> sin(x) + cos(y)).(r, r')
contour(r, r, z, levels = 5, color = :viridis, linewidth = 3)
r = range(-5, stop = 5, length = 400)
(a, b) = -1, 2
z = ((x,y) -> y.^4 - x.^4 + a .* y.^2 + b .* x.^2).(r, r')
z2 =  z .* (abs.(z) .< 250)
contour(r, r, z2)

5.1. The Makie Gallery

HTML(read(download("https://simondanisch.github.io/ReferenceImages/gallery/index.html"), String))