Makie.jl Documentation

repository·master·Indexed 25 days ago

https://github.com/makieorg/makie.jl

An interactive data visualization and plotting ecosystem for the Julia programming language. Makie supports multiple backends including GLMakie for native OpenGL windows, WGLMakie for WebGL-based rendering in browsers and notebooks, CairoMakie for high-quality static 2D vector graphics, and RPRMakie for physically accurate raytracing. The ecosystem includes tools like ComputePipeline for reactive computations, MakieRecipes for Plots.jl recipe support, and ReferenceUpdater for managing test image artifacts.

Tokens
92.7K
Snippets
297
Records
485
Agent score
83%

What's inside Makie.jl

  1. Understand Makie's Scene Graph architecture

    master

    Makie uses a hierarchical structure called a scene graph to compose complex plots. The two fundamental objects are:

    1. Scene: An abstract rectangular canvas or viewport. A Scene can contain child Scenes (which may have different camera or light settings) and Plot objects. The structure forms a tree where there is always one root Scene.
    2. Plot: Objects that represent visual data. Plots are categorized into:
      • Primitive plots: Basic shapes that backends can render directly (e.g., Scatter, Lines, Text, Image, Mesh).
      • Non-primitive plots (Recipes): Complex plots composed of multiple child plots (e.g., ScatterLines, Poly, or BoxPlot). These are often implemented using the @recipe macro.

    Every Scene is 3D capable, utilizing a 3D camera with projection and view matrices, though orthographic cameras can be used for 2D effects.

  2. Choose a Makie backend

    master

    Makie is a frontend package that defines plotting functions. To actually render plots, you must use one of the following backends:

    • GLMakie: GPU-powered, interactive 2D and 3D plotting in standalone GLFW.jl windows.
    • CairoMakie: Cairo.jl based, non-interactive 2D (and some 3D) backend for publication-quality vector graphics.
    • WGLMakie: WebGL-based interactive 2D and 3D plotting that runs within browsers.
    • RPRMakie: An experimental ray tracing backend.
  3. Understand the Transformation Interface

    master

    Transformations in Makie occur after the conversion pipeline and before drawing. Every scene and plot contains a Transformation object composed of two parts:

    1. transform_func: An arbitrary function that acts on positional data (e.g., points).
    2. model matrix: A matrix encoding scaling, rotation, and translation in 3D space.

    You can manipulate the model matrix using the following functions:

    • translate!()
    • scale!()
    • rotate!()
    • origin!()
  4. Understand CairoMakie limitations

    master

    CairoMakie is optimized for static vector graphics at publication quality. Users should be aware of the following:

    • No Interactivity: It does not support the interactive features found in GLMakie.
    • Performance: It is slower when visualizing very large amounts of data.
    • 3D Plots: While 3D plots are available, they may lack visual fidelity due to the limitations of 2D vector graphics.
  5. Understand the role of a Scene in Makie

    master

    A Scene is a fundamental building block in Makie that acts as a container for Plots and other Scenes (subscenes). While most users interact with the Figure workflow, Scenes are used for custom solutions.

    Key properties:

    • Plots: Access via scene.plots.
    • Subscenes (Children): Access via scene.children. A child scene can be created using childscene = Scene(parentscene).
    • Transformations: Every Scene has a transformation consisting of scale, translation, and rotation.
    • Size: You can set the size in device-independent pixels using Scene(size = (width, height)).
    • Keyword Propagation: Any keyword argument passed to a Scene is propagated to its plots (e.g., setting a palette or colormap at the Scene level).
  6. Understand the SpecApi

    master

    The SpecApi (introduced in version 0.20) allows for declarative plotting using "spec" objects. Instead of mutating an existing figure, you create lightweight descriptions of plots and layouts. These specs are then converted into full Makie objects.

    Key Concepts:

    • PlotSpec: Describes a plot object (e.g., Scatter, Heatmap, Lines).
    • BlockSpec: Describes a container or structural object (e.g., Axis, Colorbar, GridLayout).
    • Composition: Complex layouts are built by nesting simpler specs.
    • Observables: You can pass an observable spec to a Figure. When the spec description changes, Makie uses diffing to automatically rebuild or update the figure content.

    Warning: The SpecApi is under active development and may introduce breaking changes. It is generally slower than the standard mutating API because it performs diffing and re-creates plots to maintain the declarative structure.

    import Makie.SpecApi as S
    
    # Create specs using the S prefix convention
    scatterspec = S.Scatter(1:4) 
    axspec = S.Axis(plots=[scatterspec]) 
    layout_spec = S.GridLayout(axspec) 
    
    # Instantiate the spec into a Figure
    f, _, pl = plot(layout_spec)
    
    # Update the entire figure by updating the observable 'pl'
    pl[1] = S.GridLayout(S.Axis(; title="Lines", plots=[S.Lines(1:4)]))
  7. Explore the Makie Ecosystem

    master

    The Makie ecosystem includes several third-party packages and resources for specialized plotting tasks. Note that because the ecosystem is developing rapidly, you should monitor for potential version conflicts or downgrades when installing these packages.

    Key ecosystem components include:

    • AlgebraOfGraphics.jl: Provides grammar-of-graphics style plotting, inspired by ggplot2.
    • Beautiful Makie: A third-party gallery containing advanced Makie examples.
    • GraphMakie.jl: Specialized for graphs with two- and three-dimensional layout algorithms.
    • GeoMakie.jl: Provides geographic plotting utilities, including projections.
    • SwarmMakie.jl: Specifically for creating beeswarm plots.
  8. Quickstart with ComputePipeline

    master

    ComputePipeline is a computegraph package used for reactive computations and conversions within Makie. It provides a graph-based approach to managing data dependencies, replacing Observables.jl for Makie's internal reactive logic.

    To use it, you initialize a ComputeGraph, define inputs (optionally with conversion functions), and register computations that react to changes in those inputs.

  9. Customize text label background shapes

    master

    The shape attribute allows you to define a custom background for text labels. The shape is transformed to fit the text bounding box plus padding.

    Using Geometry Primitives

    You can pass objects like Circle, GeometryPrimitive, or BezierPath. To control how the shape scales relative to the text, use the shape_limits attribute. shape_limits defines a bounding box that is scaled to match the text bounding box.

    Using a Function for Shapes

    You can pass a function to shape that constructs a vector of points. This function receives origin and size (where size is the text bounding box plus padding) and should return a transformed vector of points.

    Example of a function-based shape for a tight circle:

    function build_shape(origin, size)
        radius = norm(0.5 * size)
        center = Point2f(origin + 0.5 * size)
        return coordinates(Circle(center, radius))
    end
    using CairoMakie
    using GeometryBasics
    using LinearAlgebra
    
    # Example using a function to create a tight circular background
    function build_shape(origin, size)
        radius = norm(0.5 * size)
        center = Point2f(origin + 0.5 * size)
        return coordinates(Circle(center, radius))
    end
    
    f, a, p = textlabel(
        [-1, 0, 1], [1, 1, 1], ["long label", "A", "t\na\nl\nl"],
        shape = build_shape, 
        fontsize = 20, 
        padding = 0
    )
  10. Create a custom plot recipe with `@recipe`

    master

    To create a custom plot type in Makie, follow these steps:

    1. Define a Plot Type: Use the @recipe macro to define a new plot type and its default attributes.
    2. Overload Makie.plot!: Implement the actual visualization by overloading Makie.plot! for your new type. Because Makie processes arguments dynamically, your plot! method should use map! to connect input nodes (converted arguments) to output nodes (data for child plots).
    3. Use map! for dynamic updates: Use map!(attributes, input_nodes, output_nodes) do ... end to register computations in the Makie graph. This ensures that if input arguments (like Observables) change, the plot updates automatically.
    4. Compose with existing plots: Inside your plot! method, call existing plotting functions (like lines! or barplot!) passing the current plot object sc and the computed nodes.
    # 1. Define the plot type and attributes
    @recipe StockChart begin
        downcolor = :red
        upcolor = :green
    end
    
    # 2. Implement the plotting logic
    function Makie.plot!(sc::StockChart{<:Tuple{AbstractVector{<:Real}, AbstractVector{<:StockValue}}})
        input_nodes = [:converted_1, :converted_2]
        output_nodes = [:linesegments, :bar_tos, :color, :barpos]
    
        # Register computation for dynamic updates
        map!(sc.attributes, input_nodes, output_nodes) do times, stockvalues
            # ... compute linesegments, barpos, etc ...
            return (linesegments, bar_tos, colors, barpos)
        end
    
        # 3. Visualize using existing plots
        linesegments!(sc, sc.linesegments, color = sc.color, colormap = sc.colormap)
        barplot!(sc, sc.attributes, sc.barpos, fillto = sc.bar_tos, strokewidth = 0)
    
        return sc
    end