This repository has been archived by the owner on Jul 15, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
recipes.html
97 lines (94 loc) · 15.1 KB
/
recipes.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Plot Recipes · Makie.jl</title><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-dark.css" data-theme-name="documenter-dark"/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="assets/themeswap.js"></script><link href="assets/favicon.ico" rel="icon" type="image/x-icon"/><link href="assets/syntaxtheme.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="index.html"><img src="assets/logo.png" alt="Makie.jl logo"/></a><div class="docs-package-name"><span class="docs-autofit">Makie.jl</span></div><form class="docs-search" action="search.html"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="index.html">Home</a></li><li><span class="tocitem">Basics</span><ul><li><a class="tocitem" href="basic-tutorial.html">Tutorial</a></li><li><a class="tocitem" href="animation.html">Animations</a></li><li><a class="tocitem" href="interaction.html">Observables & Interaction</a></li><li><a class="tocitem" href="plotting_functions.html">Plotting Functions</a></li></ul></li><li><span class="tocitem">Documentation</span><ul><li><a class="tocitem" href="scenes.html">Scenes</a></li><li><a class="tocitem" href="generated/axis.html">Axis</a></li><li><a class="tocitem" href="convenience.html">Convenience functions</a></li><li><a class="tocitem" href="generated/signatures.html">Plot function signatures</a></li><li><a class="tocitem" href="generated/plot-attributes.html">Plot attributes</a></li><li><a class="tocitem" href="generated/colors.html">Colors</a></li><li><a class="tocitem" href="lighting.html">Lighting</a></li><li><a class="tocitem" href="theming.html">Config file</a></li><li><a class="tocitem" href="cameras.html">Cameras</a></li><li class="is-active"><a class="tocitem" href="recipes.html">Plot Recipes</a><ul class="internal"><li><a class="tocitem" href="#Type-recipes"><span>Type recipes</span></a></li><li><a class="tocitem" href="#Full-recipes-with-the-@recipe-macro"><span>Full recipes with the <code>@recipe</code> macro</span></a></li></ul></li><li><a class="tocitem" href="output.html">Output</a></li><li><a class="tocitem" href="backends.html">Backends</a></li><li><a class="tocitem" href="troubleshooting.html">Troubleshooting</a></li></ul></li><li><span class="tocitem">MakieLayout</span><ul><li><a class="tocitem" href="makielayout/tutorial.html">Tutorial</a></li><li><a class="tocitem" href="makielayout/grids.html">GridLayout</a></li><li><a class="tocitem" href="makielayout/laxis.html">LAxis</a></li><li><a class="tocitem" href="makielayout/special_plots.html">Special Plots</a></li><li><a class="tocitem" href="makielayout/llegend.html">LLegend</a></li><li><a class="tocitem" href="makielayout/layoutables_examples.html">Layoutables Examples</a></li><li><a class="tocitem" href="makielayout/theming.html">Theming Layoutables</a></li><li><a class="tocitem" href="makielayout/layouting.html">How Layouting Works</a></li><li><a class="tocitem" href="makielayout/faq.html">Frequently Asked Questions</a></li><li><a class="tocitem" href="makielayout/reference.html">API Reference</a></li></ul></li><li><span class="tocitem">Developer Documentation</span><ul><li><a class="tocitem" href="why-makie.html">Why <code>Makie</code>?</a></li><li><a class="tocitem" href="devdocs.html">Devdocs</a></li><li><a class="tocitem" href="abstractplotting_api.html">AbstractPlotting Reference</a></li></ul></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Documentation</a></li><li class="is-active"><a href="recipes.html">Plot Recipes</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href="recipes.html">Plot Recipes</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://github.com/JuliaPlots/AbstractPlotting.jl/blob/master/docs/src/recipes.md#" title="Edit on GitHub"><span class="docs-icon fab"></span><span class="docs-label is-hidden-touch">Edit on GitHub</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Plot-Recipes"><a class="docs-heading-anchor" href="#Plot-Recipes">Plot Recipes</a><a id="Plot-Recipes-1"></a><a class="docs-heading-anchor-permalink" href="#Plot-Recipes" title="Permalink"></a></h1><p>Recipes allow you to extend <code>Makie</code> with your own custom types and plotting commands.</p><p>There are two types of recipes. <em>Type recipes</em> define a simple mapping from a user defined type to an existing plot type. <em>Full recipes</em> can customize the theme and define a custom plotting function.</p><h2 id="Type-recipes"><a class="docs-heading-anchor" href="#Type-recipes">Type recipes</a><a id="Type-recipes-1"></a><a class="docs-heading-anchor-permalink" href="#Type-recipes" title="Permalink"></a></h2><p>Type recipes are really simple and just overload the argument conversion pipeline, converting from one type to another, plottable type.</p><p>!!! warning <code>convert_arguments</code> must always return a Tuple.</p><p>An example is:</p><pre><code class="language-julia">convert_arguments(x::Circle) = (decompose(Point2f, x),)</code></pre><p>This can be done for all plot types or for a subset of plot types:</p><pre><code class="language-julia"># All plot types
convert_arguments(P::Type{<:AbstractPlot}, x::MyType) = convert_arguments(P, rand(10, 10))
# Only for scatter plots
convert_arguments(P::Type{<:Scatter}, x::MyType) = convert_arguments(P, rand(10, 10))
# For a group of plots, using a conversion trait for instance PointBased plots, which includes Lines and Scatter
convert_arguments(P::PointBased, x::MyType)
# It is also possible to convert multiple arguments
convert_arguments(P::Type{<:Scatter}, x::MyType, y::MyOtherType)</code></pre><p>Optionally you may define the default plot type so that <code>plot(x::MyType)</code> will use this:</p><pre><code class="language-julia">plottype(::MyType) = Surface</code></pre><h2 id="Full-recipes-with-the-@recipe-macro"><a class="docs-heading-anchor" href="#Full-recipes-with-the-@recipe-macro">Full recipes with the <code>@recipe</code> macro</a><a id="Full-recipes-with-the-@recipe-macro-1"></a><a class="docs-heading-anchor-permalink" href="#Full-recipes-with-the-@recipe-macro" title="Permalink"></a></h2><p>A full recipe for <code>MyPlot</code> comes in two parts. First is the plot type name, arguments and theme definition which are defined using the <code>@recipe</code> macro. Second is a custom <code>plot!</code> for <code>MyPlot</code>, implemented in terms of the atomic plotting functions. We use an example to show how this works:</p><pre><code class="language-julia"># arguments (x, y, z) && theme are optional
@recipe(MyPlot, x, y, z) do scene
Theme(
plot_color => :red
)
end</code></pre><p>This macro expands to several things. Firstly a type definition:</p><pre><code class="language-julia">const MyPlot{ArgTypes} = Combined{myplot, ArgTypes}</code></pre><p>The type parameter of <code>Combined</code> contains the function instead of e.g. a symbol. This way the mapping from <code>MyPlot</code> to <code>myplot</code> is safer and simpler. (The downside is we always need a function <code>myplot</code> - TODO: is this a problem?) The following signatures are defined to make <code>MyPlot</code> nice to use:</p><pre><code class="language-julia">myplot(args...; kw_args...) = ...
myplot!(scene, args...; kw_args...) = ...
myplot(kw_args::Dict, args...) = ...
myplot!(scene, kw_args::Dict, args...) = ...
#etc (not 100% settled what signatures there will be)</code></pre><p>A specialization of <code>argument_names</code> is emitted if you have an argument list <code>(x,y,z)</code> provided to the recipe macro:</p><pre><code class="language-none">`argument_names(::Type{<: MyPlot}) = (:x, :y, :z)`</code></pre><p>This is optional but it will allow the use of <code>plot_object[:x]</code> to fetch the first argument from the call <code>plot_object = myplot(rand(10), rand(10), rand(10))</code>, for example.</p><p>Alternatively you can always fetch the <code>i</code>th argument using <code>plot_object[i]</code>, and if you leave out the <code>(x,y,z)</code>, the default version of <code>argument_names</code> will provide <code>plot_object[:arg1]</code> etc.</p><p>The theme given in the body of the <code>@recipe</code> invocation is inserted into a specialization of <code>default_theme</code> which inserts the theme into any scene that plots <code>Myplot</code>:</p><pre><code class="language-julia">function default_theme(scene, ::Myplot)
Theme(
plot_color => :red
)
end</code></pre><p>As the second part of defining <code>MyPlot</code>, you should implement the actual plotting of the <code>MyPlot</code> object by specializing <code>plot!</code>:</p><pre><code class="language-julia">function plot!(plot::MyPlot)
# normal plotting code, building on any previously defined recipes
# or atomic plotting operations, and adding to the combined `plot`:
lines!(plot, rand(10), color = plot[:plot_color])
plot!(plot, plot[:x], plot[:y])
plot
end</code></pre><p>It's possible to add specializations here, depending on the argument <em>types</em> supplied to <code>myplot</code>. For example, to specialize the behavior of <code>myplot(a)</code> when <code>a</code> is a 3D array of floating point numbers:</p><pre><code class="language-julia">const MyVolume = MyPlot{Tuple{<:AbstractArray{<: AbstractFloat, 3}}}
argument_names(::Type{<: MyVolume}) = (:volume,) # again, optional
function plot!(plot::MyVolume)
# plot a volume with a colormap going from fully transparent to plot_color
volume!(plot, plot[:volume], colormap = :transparent => plot[:plot_color])
plot
end</code></pre><p>Here is a complete example of creating a custom type and a recipe for it.</p><pre><code class="language-julia">using GLMakie
using AbstractPlotting
import AbstractPlotting: Plot, default_theme, plot!, to_value
struct Simulation
grid::Vector{Point3f0}
end
# Probably worth having a macro for this!
function default_theme(scene::SceneLike, ::Type{<: Plot(Simulation)})
Theme(
advance = 0,
molecule_sizes = [0.08, 0.04, 0.04],
molecule_colors = [:maroon, :deepskyblue2, :deepskyblue2]
)
end
# The recipe! - will get called for plot(!)(x::SimulationResult)
function AbstractPlotting.plot!(p::Plot(Simulation))
sim = to_value(p[1]) # first argument is the SimulationResult
# when advance changes, get new positions from the simulation
mpos = lift(p[:advance]) do i
sim.grid .+ rand(Point3f0, length(sim.grid)) .* 0.01f0
end
# size shouldn't change, so we might as well get the value instead of signal
pos = to_value(mpos)
N = length(pos)
sizes = lift(p[:molecule_sizes]) do s
repeat(s, outer = N ÷ 3)
end
sizes = lift(p[:molecule_sizes]) do s
repeat(s, outer = N ÷ 3)
end
colors = lift(p[:molecule_colors]) do c
repeat(c, outer = N ÷ 3)
end
scene = meshscatter!(p, mpos, markersize = sizes, color = colors)
indices = Int[]
for i in 1:3:N
push!(indices, i, i + 1, i, i + 2)
end
meshplot = p.plots[end] # meshplot is the last plot we added to p
# meshplot[1] -> the positions (first argument) converted to points, so
# we don't do the conversion 2 times for linesegments!
linesegments!(p, lift(x-> view(x, indices), meshplot[1]))
end
# To write out a video of the whole simulation
n = 5
r = range(-1, stop = 1, length = n)
grid = Point3f0.(r, reshape(r, (1, n, 1)), reshape(r, (1, 1, n)))
molecules = map(1:(n^3) * 3) do i
i3 = ((i - 1) ÷ 3) + 1
xy = 0.1; z = 0.08
i % 3 == 1 && return grid[i3]
i % 3 == 2 && return grid[i3] + Point3f0(xy, xy, z)
i % 3 == 0 && return grid[i3] + Point3f0(-xy, xy, z)
end
result = Simulation(molecules)
scene = plot(result)
N = 100
record(scene, "molecules_simulation.mp4", 1:N) do i
scene[end][:advance] = i
end</code></pre><pre class="documenter-example-output">┌ Warning: Inefficient re-conversion back to GLNative buffer format. Update GLMakie to support direct buffer access
└ @ AbstractPlotting /builds/JuliaGPU/AbstractPlotting-jl/src/display.jl:410</pre><p><video src="molecules_simulation.mp4" controls="true" title="molecules simulation"><a href="molecules_simulation.mp4">molecules simulation</a></video></p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="cameras.html">« Cameras</a><a class="docs-footer-nextpage" href="output.html">Output »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> on <span class="colophon-date" title="Wednesday 2 December 2020 23:15">Wednesday 2 December 2020</span>. Using Julia version 1.3.1.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>