From d177b88c401555ff04e310165cfdfb15bfe70791 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 10:29:29 +0100 Subject: [PATCH 001/106] add second `@recipe` method --- MakieCore/src/recipes.jl | 42 +++++++++++++++++++++++++++++++++++++++ src/makielayout/blocks.jl | 36 +++------------------------------ 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 2e31672853c..59bfc1f7eda 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -189,6 +189,48 @@ macro recipe(theme_func, Tsym::Symbol, args::Symbol...) expr end +macro recipe(Tsym::Symbol, args...) + @info "This is the new recipe" + syms = args[1:end-1] + for sym in syms + sym isa Symbol || throw(ArgumentError("Found argument that is not a symbol in the position where optional argument names should appear: $sym")) + end + attrexpr = args[end] + if !(attrexpr isa Expr && attrexpr.head === :block) + throw(ArgumentError("Last argument is not a begin end block")) + end +end + +function extract_attr(arg) + has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef + + if has_docs + docs = arg.args[3] + attr = arg.args[4] + else + docs = nothing + attr = arg + end + + if !(attr isa Expr && attr.head === :(=) && length(attr.args) == 2) + error("$attr is not a valid attribute line like :x[::Type] = default_value") + end + left = attr.args[1] + default = attr.args[2] + if left isa Symbol + attr_symbol = left + type = Any + else + if !(left isa Expr && left.head === :(::) && length(left.args) == 2) + error("$left is not a Symbol or an expression such as x::Type") + end + attr_symbol = left.args[1]::Symbol + type = left.args[2] + end + + (docs = docs, symbol = attr_symbol, type = type, default = default) +end + """ Plot(args::Vararg{<:DataType,N}) diff --git a/src/makielayout/blocks.jl b/src/makielayout/blocks.jl index c6bf0bdb73f..a7dd4b8480b 100644 --- a/src/makielayout/blocks.jl +++ b/src/makielayout/blocks.jl @@ -205,44 +205,14 @@ function extract_attributes!(body) args = filter(x -> !(x isa LineNumberNode), attrs_block.args) - function extract_attr(arg) - has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef + attrs::Vector{Any} = map(MakieCore.extract_attr, args) - if has_docs - docs = arg.args[3] - attr = arg.args[4] - else - docs = nothing - attr = arg - end - - if !(attr isa Expr && attr.head === :(=) && length(attr.args) == 2) - error("$attr is not a valid attribute line like :x[::Type] = default_value") - end - left = attr.args[1] - default = attr.args[2] - if left isa Symbol - attr_symbol = left - type = Any - else - if !(left isa Expr && left.head === :(::) && length(left.args) == 2) - error("$left is not a Symbol or an expression such as x::Type") - end - attr_symbol = left.args[1]::Symbol - type = left.args[2] - end - - (docs = docs, symbol = attr_symbol, type = type, default = default) - end - - attrs = map(extract_attr, args) - - lras = map(extract_attr, layout_related_attributes) + lras = map(MakieCore.extract_attr, layout_related_attributes) for lra in lras i = findfirst(x -> x.symbol == lra.symbol, attrs) if i === nothing - push!(attrs, extract_attr(lra)) + push!(attrs, lra) end end From 8157551f9f0ef9e60e72091e5bb4537e45bbb852 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 10:37:01 +0100 Subject: [PATCH 002/106] rename function --- MakieCore/src/recipes.jl | 8 +++++--- src/makielayout/blocks.jl | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 59bfc1f7eda..86f879ca60f 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -195,13 +195,15 @@ macro recipe(Tsym::Symbol, args...) for sym in syms sym isa Symbol || throw(ArgumentError("Found argument that is not a symbol in the position where optional argument names should appear: $sym")) end - attrexpr = args[end] - if !(attrexpr isa Expr && attrexpr.head === :block) + attrblock = args[end] + if !(attrblock isa Expr && attrblock.head === :block) throw(ArgumentError("Last argument is not a begin end block")) end + attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] + end -function extract_attr(arg) +function extract_attribute_metadata(arg) has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef if has_docs diff --git a/src/makielayout/blocks.jl b/src/makielayout/blocks.jl index a7dd4b8480b..9df779e54e9 100644 --- a/src/makielayout/blocks.jl +++ b/src/makielayout/blocks.jl @@ -205,9 +205,9 @@ function extract_attributes!(body) args = filter(x -> !(x isa LineNumberNode), attrs_block.args) - attrs::Vector{Any} = map(MakieCore.extract_attr, args) + attrs::Vector{Any} = map(MakieCore.extract_attribute_metadata, args) - lras = map(MakieCore.extract_attr, layout_related_attributes) + lras = map(MakieCore.extract_attribute_metadata, layout_related_attributes) for lra in lras i = findfirst(x -> x.symbol == lra.symbol, attrs) From edd623632a50bec0f4000b01f5bed944fd94aab8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 11:58:16 +0100 Subject: [PATCH 003/106] implement recipe and keyword validation --- MakieCore/src/recipes.jl | 111 ++++++++++++++++++++++++++++++++++++++- MakieCore/src/types.jl | 1 + 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 86f879ca60f..6e35ba552ba 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -189,8 +189,21 @@ macro recipe(theme_func, Tsym::Symbol, args::Symbol...) expr end +function is_attribute end +function default_attribute_values end +function attribute_default_expressions end +function _attribute_docs end +function attribute_names end + +attribute_names(_) = nothing + macro recipe(Tsym::Symbol, args...) - @info "This is the new recipe" + + funcname_sym = to_func_name(Tsym) + funcname! = esc(Symbol("$(funcname_sym)!")) + PlotType = esc(Tsym) + funcname = esc(funcname_sym) + syms = args[1:end-1] for sym in syms sym isa Symbol || throw(ArgumentError("Found argument that is not a symbol in the position where optional argument names should appear: $sym")) @@ -201,8 +214,58 @@ macro recipe(Tsym::Symbol, args...) end attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] + q = quote + $(funcname)() = not_implemented_for($funcname) + const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} + $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) + Core.@__doc__ function ($funcname)(args...; kw...) + kwdict = Dict{Symbol, Any}(kw) + _create_plot($funcname, kwdict, args...) + end + function ($funcname!)(args...; kw...) + kwdict = Dict{Symbol, Any}(kw) + _create_plot!($funcname, kwdict, args...) + end + function MakieCore.is_attribute(T::Type{<:$(PlotType)}, sym::Symbol) + sym in MakieCore.attribute_names(T) + end + function MakieCore.attribute_names(::Type{<:$(PlotType)}) + Set{Symbol}([$([QuoteNode(a.symbol) for a in attrs]...)]) + end + + function $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) + $(make_attr_dict_expr(attrs, :scene)) + end + + function MakieCore.attribute_default_expressions(::Type{<:$PlotType}) + $( + if attrs === nothing + Dict{Symbol, String}() + else + Dict{Symbol, String}([a.symbol => _defaultstring(a.default) for a in attrs]) + end + ) + end + + function MakieCore._attribute_docs(::Type{<:$PlotType}) + Dict( + $( + (attrs !== nothing ? + [Expr(:call, :(=>), QuoteNode(a.symbol), a.docs) for a in attrs] : + [])... + ) + ) + end + + export $PlotType, $funcname, $funcname! + end + + q end +_defaultstring(x) = string(Base.remove_linenums!(x)) +_defaultstring(x::String) = repr(x) + function extract_attribute_metadata(arg) has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef @@ -233,6 +296,39 @@ function extract_attribute_metadata(arg) (docs = docs, symbol = attr_symbol, type = type, default = default) end +function make_attr_dict_expr(attrs, scenesym::Symbol) + + pairs = map(attrs) do a + + d = a.default + if d isa Expr && d.head === :macrocall && d.args[1] == Symbol("@inherit") + if length(d.args) != 4 + error("@inherit works with exactly 2 arguments, expression was $d") + end + if !(d.args[3] isa QuoteNode) + error("Argument 1 of @inherit must be a :symbol, got $(d.args[3])") + end + key, default = d.args[3:4] + # first check scene theme + # then default value + d = quote + if haskey(thm, $key) + to_value(thm[$key]) # only use value of theme entry + else + $default + end + end + end + + Expr(:call, :(=>), QuoteNode(a.symbol), d) + end + + quote + thm = theme($scenesym) + Dict($(pairs...)) + end +end + """ Plot(args::Vararg{<:DataType,N}) @@ -277,3 +373,16 @@ e.g.: ``` """ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! + +function validate_kw(P::Type{<:Plot}, kw::Dict{Symbol}) + nameset = attribute_names(P) + nameset === nothing && return + unknown = setdiff(keys(kw), nameset) + if !isempty(unknown) + n = length(unknown) + throw(ArgumentError( + """Unknown attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). + The available attributes are: $(join(sort(collect(nameset)), ", ", " and ")).""" + )) + end +end \ No newline at end of file diff --git a/MakieCore/src/types.jl b/MakieCore/src/types.jl index e80345d339c..18d574ef727 100644 --- a/MakieCore/src/types.jl +++ b/MakieCore/src/types.jl @@ -79,6 +79,7 @@ mutable struct Plot{PlotFunc, T} <: ScenePlot{PlotFunc} parent::Union{AbstractScene,Plot} function Plot{Typ,T}(kw::Dict{Symbol, Any}, args::Vector{Any}, converted::NTuple{N, Observable}) where {Typ,T,N} + validate_kw(Plot{Typ}, kw) return new{Typ,T}(nothing, kw, args, converted, Attributes(), Plot[], Observables.ObserverFunction[]) end From 1bc7031f6bd963cd58f30a7b0ebee6c08eff0ce4 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 12:06:50 +0100 Subject: [PATCH 004/106] fix some bugs --- MakieCore/src/recipes.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 6e35ba552ba..fd739e83a1d 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -234,7 +234,7 @@ macro recipe(Tsym::Symbol, args...) end function $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) - $(make_attr_dict_expr(attrs, :scene)) + $(make_default_theme_expr(attrs, :scene)) end function MakieCore.attribute_default_expressions(::Type{<:$PlotType}) @@ -296,7 +296,7 @@ function extract_attribute_metadata(arg) (docs = docs, symbol = attr_symbol, type = type, default = default) end -function make_attr_dict_expr(attrs, scenesym::Symbol) +function make_default_theme_expr(attrs, scenesym::Symbol) pairs = map(attrs) do a @@ -325,7 +325,7 @@ function make_attr_dict_expr(attrs, scenesym::Symbol) quote thm = theme($scenesym) - Dict($(pairs...)) + Attributes([$(pairs...)]) end end @@ -381,8 +381,7 @@ function validate_kw(P::Type{<:Plot}, kw::Dict{Symbol}) if !isempty(unknown) n = length(unknown) throw(ArgumentError( - """Unknown attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). - The available attributes are: $(join(sort(collect(nameset)), ", ", " and ")).""" + """Invalid attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). The available attributes are: $(join(sort(collect(nameset)), ", ", " and ")).""" )) end end \ No newline at end of file From 8d275e87bf972b1418cf9cea09ed10c0e0c0c620 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 12:15:49 +0100 Subject: [PATCH 005/106] rename for clarity --- MakieCore/src/recipes.jl | 2 +- MakieCore/src/types.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index fd739e83a1d..f0d4568bc56 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -374,7 +374,7 @@ e.g.: """ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! -function validate_kw(P::Type{<:Plot}, kw::Dict{Symbol}) +function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return unknown = setdiff(keys(kw), nameset) diff --git a/MakieCore/src/types.jl b/MakieCore/src/types.jl index 18d574ef727..d634647c2a4 100644 --- a/MakieCore/src/types.jl +++ b/MakieCore/src/types.jl @@ -79,7 +79,7 @@ mutable struct Plot{PlotFunc, T} <: ScenePlot{PlotFunc} parent::Union{AbstractScene,Plot} function Plot{Typ,T}(kw::Dict{Symbol, Any}, args::Vector{Any}, converted::NTuple{N, Observable}) where {Typ,T,N} - validate_kw(Plot{Typ}, kw) + validate_attribute_keys(Plot{Typ}, kw) return new{Typ,T}(nothing, kw, args, converted, Attributes(), Plot[], Observables.ObserverFunction[]) end From 51018414046104cf0f8c969a34d0fd201b3c7c7a Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 13:11:55 +0100 Subject: [PATCH 006/106] change Scatter recipe --- MakieCore/src/basic_plots.jl | 87 +++++++++++++++++++++++++++--------- MakieCore/src/recipes.jl | 21 +++++++++ 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 326657fb33e..071c9e4f00d 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -40,6 +40,30 @@ function generic_plot_attributes(attr) ) end +function mixin_generic_plot_attributes() + quote + transformation = automatic + "Sets a model matrix for the plot. This overrides adjustments made with `translate!`, `rotate!` and `scale!`." + model = automatic + "Controls whether the plot will be rendered or not." + visible = true + "Adjusts how the plot deals with transparency. In GLMakie `transparency = true` results in using Order Independent Transparency." + transparency = false + "Controls if the plot will draw over other plots. This specifically means ignoring depth checks in GL backends" + overdraw = false + "Enables screen-space ambient occlusion." + ssao = false + "sets whether this plot should be seen by `DataInspector`." + inspectable = true + "adjusts the depth value of a plot after all other transformations, i.e. in clip space, where `0 <= depth <= 1`. This only applies to GLMakie and WGLMakie and can be used to adjust render order (like a tunable overdraw)." + depth_shift = 0.0f0 + "sets the transformation space for box encompassing the plot. See `Makie.spaces()` for possible inputs." + space = :data + "adjusts whether the plot is rendered with fxaa (anti-aliasing)." + fxaa = true + end +end + """ ### Color attributes @@ -76,6 +100,30 @@ function colormap_attributes(attr) ) end +function mixin_colormap_attributes() + quote + """ + Sets the colormap that is sampled for numeric `color`s. + `PlotUtils.cgrad(...)`, `Makie.Reverse(any_colormap)` can be used as well, or any symbol from ColorBrewer or PlotUtils. + To see all available color gradients, you can call `Makie.available_gradients()`. + """ + colormap = @inherit :colormap :viridis + """ + The color transform function. Can be any function, but only works well together with `Colorbar` for `identity`, `log`, `log2`, `log10`, `sqrt`, `logit`, `Makie.pseudolog10` and `Makie.Symlog10`. + """ + colorscale = identity + "The values representing the start and end points of `colormap`." + colorrange = automatic + "The color for any value below the colorrange." + lowclip = automatic + "The color for any value above the colorrange." + highclip = automatic + nan_color = :transparent + "The alpha value of the colormap or color attribute. Multiple alphas like in `plot(alpha=0.2, color=(:red, 0.5)`, will get multiplied." + alpha = 1.0 + end +end + """ ### 3D shading attributes @@ -396,31 +444,28 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Scatter, positions) do scene - attr = Attributes(; - color = theme(scene, :markercolor), +@recipe Scatter positions begin + color = @inherit :markercolor :black - marker = theme(scene, :marker), - markersize = theme(scene, :markersize), + marker = @inherit :marker :circle + markersize = @inherit :markersize 8 - strokecolor = theme(scene, :markerstrokecolor), - strokewidth = theme(scene, :markerstrokewidth), - glowcolor = (:black, 0.0), - glowwidth = 0.0, + strokecolor = @inherit :markerstrokecolor :transparent + strokewidth = @inherit :markerstrokewidth 0 + glowcolor = (:black, 0.0) + glowwidth = 0.0 - rotations = Billboard(), - marker_offset = automatic, + rotations = Billboard() + marker_offset = automatic - transform_marker = false, # Applies the plots transformation to marker - distancefield = nothing, - uv_offset_width = (0.0, 0.0, 0.0, 0.0), - markerspace = :pixel, - - fxaa = false, - cycle = [:color], - ) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) + transform_marker = false # Applies the plots transformation to marker + distancefield = nothing + uv_offset_width = (0.0, 0.0, 0.0, 0.0) + markerspace = :pixel + cycle = [:color] + + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end """ diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index f0d4568bc56..67b6f1be743 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -212,6 +212,7 @@ macro recipe(Tsym::Symbol, args...) if !(attrblock isa Expr && attrblock.head === :block) throw(ArgumentError("Last argument is not a begin end block")) end + attrblock = expand_mixins(attrblock) attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] q = quote @@ -329,6 +330,26 @@ function make_default_theme_expr(attrs, scenesym::Symbol) end end +function expand_mixins(attrblock::Expr) + Expr(:block, mapreduce(expand_mixin, vcat, attrblock.args)...) +end + +expand_mixin(x) = x +function expand_mixin(e::Expr) + if e.head === :macrocall && e.args[1] === Symbol("@mixin") + if length(e.args) != 3 && e.args[2] isa LineNumberNode && e.args[3] isa Symbol + error("Invalid mixin, needs to be of the format `@mixin some_mixin`, got $e") + end + mixin_ex = getproperty(MakieCore, e.args[3])()::Expr + if (mixin_ex.head !== :block) + error("Expected mixin to be a block expression (such as generated by `quote`)") + end + return mixin_ex.args + else + e + end +end + """ Plot(args::Vararg{<:DataType,N}) From 5c3617cdb3e3024f10b99c926c3e7820e4484694 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 13:18:39 +0100 Subject: [PATCH 007/106] use argument symbols correctly --- MakieCore/src/recipes.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 67b6f1be743..023dc99464c 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -261,6 +261,16 @@ macro recipe(Tsym::Symbol, args...) export $PlotType, $funcname, $funcname! end + if !isempty(syms) + push!( + q.args, + :( + $(esc(:($(MakieCore).argument_names)))(::Type{<:$PlotType}, len::Integer) = + $syms + ), + ) + end + q end From 385bfc91557a928817d1b691ff6a0362d1e1ba7d Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 13:22:26 +0100 Subject: [PATCH 008/106] change Lines --- MakieCore/src/basic_plots.jl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 071c9e4f00d..8a1ba0de520 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -339,18 +339,17 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Lines, positions) do scene - attr = Attributes(; - - color = theme(scene, :linecolor), - linewidth = theme(scene, :linewidth), - - linestyle = nothing, - fxaa = false, - cycle = [:color], - ) - generic_plot_attributes!(attr, ) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Lines positions begin + "Sets the color of the line. If no color is set, multiple calls to `line!` will cycle through the axis color palette" + color = @inherit :linecolor :black + "Sets the width of the line in pixel units" + linewidth = @inherit :linewidth 1.0 + "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" + linestyle = nothing + "Sets which attributes to cycle when creating multiple plots." + cycle = [:color] + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end """ From a753094aa9ebb5d2e27bdb41994c5ca2c42b2e21 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 13:24:27 +0100 Subject: [PATCH 009/106] change linesegments --- MakieCore/src/basic_plots.jl | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 8a1ba0de520..b37a52341bf 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -340,7 +340,7 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Lines positions begin - "Sets the color of the line. If no color is set, multiple calls to `line!` will cycle through the axis color palette" + "The color of the line." color = @inherit :linecolor :black "Sets the width of the line in pixel units" linewidth = @inherit :linewidth 1.0 @@ -374,8 +374,17 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(LineSegments, positions) do scene - default_theme(scene, Lines) +@recipe LineSegments positions begin + "The color of the line." + color = @inherit :linecolor :black + "Sets the width of the line in pixel units" + linewidth = @inherit :linewidth 1.0 + "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" + linestyle = nothing + "Sets which attributes to cycle when creating multiple plots." + cycle = [:color] + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end # alternatively, mesh3d? Or having only mesh instead of poly + mesh and figure out 2d/3d via dispatch From 4003b075245fe44743bd0060acc19544d9ab8f7b Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 13:57:08 +0100 Subject: [PATCH 010/106] do a bunch of plots more --- MakieCore/src/basic_plots.jl | 232 ++++++++++++++++++++--------------- 1 file changed, 135 insertions(+), 97 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index b37a52341bf..9719cec8ef9 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -154,6 +154,23 @@ function shading_attributes(attr) ) end +function mixin_shading_attributes() + quote + "Sets the lighting algorithm used. Options are `NoShading` (no lighting), `FastShading` (AmbientLight + PointLight) or `MultiLightShading` (Multiple lights, GLMakie only). Note that this does not affect RPRMakie." + shading = automatic + "Sets how strongly the red, green and blue channel react to diffuse (scattered) light." + diffuse = 1.0 + "Sets how strongly the object reflects light in the red, green and blue channels." + specular = 0.2 + "Sets how sharp the reflection is." + shininess = 32.0f0 + "Sets a weight for secondary light calculation with inverted normals." + backlight = 0f0 + "Adjusts whether the plot is rendered with ssao (screen space ambient occlusion). Note that this only makes sense in 3D plots and is only applicable with `fxaa = true`." + ssao = false + end +end + """ `calculated_attributes!(trait::Type{<: AbstractPlot}, plot)` trait version of calculated_attributes @@ -230,16 +247,11 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Heatmap, x, y, values) do scene - attr = Attributes(; - - interpolate = false, - - linewidth = 0.0, - fxaa = true, - ) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Heatmap x y values begin + "Sets whether colors should be interpolated" + interpolate = false + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end """ @@ -270,18 +282,18 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Volume, x, y, z, volume) do scene - attr = Attributes(; - - algorithm = :mip, - isovalue = 0.5, - isorange = 0.05, - interpolate = true, - fxaa = true, - ) - generic_plot_attributes!(attr) - shading_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Volume x y z volume begin + "Sets the volume algorithm that is used." + algorithm = :mip + "Sets the range of values picked up by the IsoValue algorithm." + isovalue = 0.5 + "Sets the target value for the IsoValue algorithm." + isorange = 0.05 + "Sets whether the volume data should be sampled with interpolation." + interpolate = true + @mixin mixin_generic_plot_attributes + @mixin mixin_shading_attributes + @mixin mixin_colormap_attributes end """ @@ -304,16 +316,14 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Surface, x, y, z) do scene - attr = Attributes(; - color = nothing, - invert_normals = false, - - fxaa = true, - ) - shading_attributes!(attr) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Surface x y z begin + "Can be set to an `Matrix{<: Union{Number, Colorant}}` to color surface independent of the `z` component. If `color=nothing`, it defaults to `color=z`." + color = nothing + "Inverts the normals generated for the surface. This can be useful to illuminate the other side of the surface." + invert_normals = false + @mixin mixin_generic_plot_attributes + @mixin mixin_shading_attributes + @mixin mixin_colormap_attributes end """ @@ -411,17 +421,15 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Mesh, mesh) do scene - attr = Attributes(; - color = :black, - interpolate = true, - - fxaa = true, - cycle = [:color => :patchcolor], - ) - shading_attributes!(attr) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Mesh mesh begin + "Sets the color of the mesh. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates." + color = @inherit :patchcolor :black + "sets whether colors should be interpolated" + interpolate = true + cycle = [:color => :patchcolor] + @mixin mixin_generic_plot_attributes + @mixin mixin_shading_attributes + @mixin mixin_colormap_attributes end """ @@ -453,23 +461,31 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Scatter positions begin + "Sets the color of the marker. If no color is set, multiple calls to `scatter!` will cycle through the axis color palette." color = @inherit :markercolor :black - + "Sets the scatter marker." marker = @inherit :marker :circle + "Sets the size of the marker." markersize = @inherit :markersize 8 - + "Sets the color of the outline around a marker." strokecolor = @inherit :markerstrokecolor :transparent + "Sets the width of the outline around a marker." strokewidth = @inherit :markerstrokewidth 0 + "Sets the color of the glow effect around the marker." glowcolor = (:black, 0.0) + "Sets the size of a glow effect around the marker." glowwidth = 0.0 + "Sets the rotation of the marker. A `Billboard` rotation is always around the depth axis." rotations = Billboard() marker_offset = automatic - - transform_marker = false # Applies the plots transformation to marker + "Controls whether the model matrix (without translation) applies to the marker itself, rather than just the positions. (If this is true, `scale!` and `rotate!` will affect the marker." + transform_marker = false distancefield = nothing uv_offset_width = (0.0, 0.0, 0.0, 0.0) + "Sets the space in which `markersize` is given. See `Makie.spaces()` for possible inputs" markerspace = :pixel + "Sets which attributes to cycle when creating multiple plots" cycle = [:color] @mixin mixin_generic_plot_attributes @@ -501,21 +517,21 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(MeshScatter, positions) do scene - attr = Attributes(; - color = theme(scene, :markercolor), - - marker = :Sphere, - markersize = 0.1, - rotations = 0.0, - space = :data, - - fxaa = true, - cycle = [:color], - ) - shading_attributes!(attr) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe MeshScatter positions begin + "Sets the color of the marker." + color = @inherit :markercolor :black + "Sets the scattered mesh." + marker = :Sphere + "Sets the scale of the mesh. This can be given as a `Vector` to apply to each scattered mesh individually." + markersize = 0.1 + "Sets the rotation of the mesh. A numeric rotation is around the z-axis, a `Vec3f` causes the mesh to rotate such that the the z-axis is now that vector, and a quaternion describes a general rotation. This can be given as a Vector to apply to each scattered mesh individually." + rotations = 0.0 + space = :data + fxaa = true + cycle = [:color] + @mixin mixin_generic_plot_attributes + @mixin mixin_shading_attributes + @mixin mixin_colormap_attributes end """ @@ -549,28 +565,42 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Text, positions) do scene - attr = Attributes(; - color = theme(scene, :textcolor), - - font = theme(scene, :font), - fonts = theme(scene, :fonts), - - strokecolor = (:black, 0.0), - strokewidth = 0, - align = (:left, :bottom), - rotation = 0.0, - fontsize = theme(scene, :fontsize), - position = (0.0, 0.0), - justification = automatic, - lineheight = 1.0, - markerspace = :pixel, - transform_marker = false, - offset = (0.0, 0.0), - word_wrap_width = -1, - ) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) +@recipe Text positions begin + "Specifies one piece of text or a vector of texts to show, where the number has to match the number of positions given. Makie supports `String` which is used for all normal text and `LaTeXString` which layouts mathematical expressions using `MathTeXEngine.jl`." + text = "" + "Sets the color of the text. One can set one color per glyph by passing a `Vector{<:Colorant}`, or one colorant for the whole text. If color is a vector of numbers, the colormap args are used to map the numbers to colors." + color = @inherit :textcolor :black + "Sets the font. Can be a `Symbol` which will be looked up in the `fonts` dictionary or a `String` specifying the (partial) name of a font or the file path of a font file" + font = @inherit :font :regular + "Used as a dictionary to look up fonts specified by `Symbol`, for example `:regular`, `:bold` or `:italic`." + fonts = @inherit :fonts Attributes() + "Sets the color of the outline around a marker." + strokecolor = (:black, 0.0) + "Sets the width of the outline around a marker." + strokewidth = 0 + "Sets the alignment of the string w.r.t. `position`. Uses `:left, :center, :right, :top, :bottom, :baseline` or fractions." + align = (:left, :bottom) + "Rotates text around the given position" + rotation = 0.0 + "The fontsize in units depending on `markerspace`." + fontsize = @inherit :fontsize 16 + "Deprecated: Specifies the position of the text. Use the positional argument to `text` instead." + position = (0.0, 0.0) + "Sets the alignment of text w.r.t its bounding box. Can be `:left, :center, :right` or a fraction. Will default to the horizontal alignment in `align`." + justification = automatic + "The lineheight multiplier." + lineheight = 1.0 + "Sets the space in which `fontsize` acts. See `Makie.spaces()` for possible inputs." + markerspace = :pixel + "Controls whether the model matrix (without translation) applies to the glyph itself, rather than just the positions. (If this is true, `scale!` and `rotate!` will affect the text glyphs.)" + transform_marker = false + "The offset of the text from the given position in `markerspace` units." + offset = (0.0, 0.0) + "Specifies a linewidth limit for text. If a word overflows this limit, a newline is inserted before it. Negative numbers disable word wrapping." + word_wrap_width = -1 + + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end """ @@ -606,22 +636,30 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Poly) do scene - attr = Attributes(; - color = theme(scene, :patchcolor), +@recipe Poly begin + """ + Sets the color of the poly. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. + A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates. + Vector or Matrices of numbers can be used as well, which will use the colormap arguments to map the numbers to colors. + One can also use `Makie.LinePattern`, to cover the poly with a regular stroke pattern. + """ + color = @inherit :patchcolor :black + "Sets the color of the outline around a marker." + strokecolor = @inherit :patchstrokecolor :transparent + "Sets the colormap that is sampled for numeric `color`s." + strokecolormap = @inherit :colormap :viridis + "Sets the width of the outline." + strokewidth = @inherit :patchstrokewidth 0 + "Sets the pattern of the line (e.g. `:solid`, `:dot`, `:dashdot`)" + linestyle = nothing - strokecolor = theme(scene, :patchstrokecolor), - strokecolormap = theme(scene, :colormap), - strokewidth = theme(scene, :patchstrokewidth), - linestyle = nothing, + shading = NoShading + fxaa = true - shading = NoShading, - fxaa = true, + cycle = [:color => :patchcolor] - cycle = [:color => :patchcolor], - ) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, theme(scene, :colormap)) + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes end @recipe(Wireframe) do scene From 47d9ad95774f3fffa1192f5a33771950cc6c37bf Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 13 Feb 2024 19:16:10 +0100 Subject: [PATCH 011/106] fix text bugs --- src/basic_recipes/text.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/basic_recipes/text.jl b/src/basic_recipes/text.jl index 1b42770ede3..6e75ef86cde 100644 --- a/src/basic_recipes/text.jl +++ b/src/basic_recipes/text.jl @@ -76,6 +76,7 @@ function plot!(plot::Text) pop!(attrs, :text) pop!(attrs, :align) pop!(attrs, :color) + pop!(attrs, :calculated_colors) t = text!(plot, glyphcollections; attrs..., position = positions) # remove attributes that the backends will choke on @@ -158,8 +159,10 @@ function plot!(plot::Text{<:Tuple{<:AbstractArray{<:Tuple{<:Any, <:Point}}}}) attrs = plot.attributes pop!(attrs, :position) + pop!(attrs, :calculated_colors) + pop!(attrs, :text) - text!(plot, positions; text = strings, attrs...) + text!(plot, positions; attrs..., text = strings) # update both text and positions together on(plot, strings_and_positions) do str_pos From 8c0b2ad9ed7c88381730f227b4d8a599a2659c36 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 10:18:39 +0100 Subject: [PATCH 012/106] splice in internal attribute after mesh creation --- src/basic_recipes/poly.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/basic_recipes/poly.jl b/src/basic_recipes/poly.jl index 8792eadfb0c..31e2b838f2c 100644 --- a/src/basic_recipes/poly.jl +++ b/src/basic_recipes/poly.jl @@ -164,7 +164,7 @@ end function plot!(plot::Mesh{<: Tuple{<: AbstractVector{P}}}) where P <: Union{AbstractMesh, Polygon} meshes = plot[1] - attributes = Attributes( + attrs = Attributes( visible = plot.visible, shading = plot.shading, fxaa = plot.fxaa, inspectable = plot.inspectable, transparency = plot.transparency, space = plot.space, ssao = plot.ssao, @@ -183,6 +183,8 @@ function plot!(plot::Mesh{<: Tuple{<: AbstractVector{P}}}) where P <: Union{Abst mesh_colors = Observable{Union{AbstractPattern, Matrix{RGBAf}, RGBColors, Float32}}() + interpolate_in_fragment_shader = Observable(false) + map!(plot, mesh_colors, plot.color, num_meshes) do colors, num_meshes # one mesh per color if colors isa AbstractVector && length(colors) == length(num_meshes) @@ -196,15 +198,15 @@ function plot!(plot::Mesh{<: Tuple{<: AbstractVector{P}}}) where P <: Union{Abst end end # For GLMakie (right now), to not interpolate between the colors (which are meant to be per mesh) - attributes[:interpolate_in_fragment_shader] = false + interpolate_in_fragment_shader[] = false return result else # If we have colors per vertex, we need to interpolate in fragment shader - attributes[:interpolate_in_fragment_shader] = true + interpolate_in_fragment_shader[] = true return to_color(colors) end end - attributes[:color] = mesh_colors + attrs[:color] = mesh_colors transform_func = plot.transformation.transform_func bigmesh = lift(plot, meshes, transform_func) do meshes, tf if isempty(meshes) @@ -214,5 +216,8 @@ function plot!(plot::Mesh{<: Tuple{<: AbstractVector{P}}}) where P <: Union{Abst return merge(triangle_meshes) end end - return mesh!(plot, attributes, bigmesh) + mpl = mesh!(plot, attrs, bigmesh) + # splice in internal attribute after creation to avoid validation + attributes(mpl)[:interpolate_in_fragment_shader] = interpolate_in_fragment_shader + return mpl end From f00125b89fb8e4bda29a4352c58d0e37053e9c03 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 10:25:26 +0100 Subject: [PATCH 013/106] add allowlist --- MakieCore/src/recipes.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 023dc99464c..b36e9540cfd 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -408,11 +408,12 @@ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return - unknown = setdiff(keys(kw), nameset) + allowlist = [:xautolimits, :yautolimits, :zautolimits, :label] + unknown = setdiff(keys(kw), nameset, allowlist) if !isempty(unknown) n = length(unknown) throw(ArgumentError( - """Invalid attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). The available attributes are: $(join(sort(collect(nameset)), ", ", " and ")).""" + """Invalid attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). The available plot attributes are: $(join(sort(collect(nameset)), ", ", " and ")). Additional generic keywords are $(join(allowlist, ", ", " and ")).""" )) end end \ No newline at end of file From e2e491d00157028ddb098dc636b17071aedd3aae Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 10:25:46 +0100 Subject: [PATCH 014/106] fix text --- src/basic_recipes/text.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/basic_recipes/text.jl b/src/basic_recipes/text.jl index 6e75ef86cde..b0c754c4bc2 100644 --- a/src/basic_recipes/text.jl +++ b/src/basic_recipes/text.jl @@ -125,7 +125,9 @@ function _get_glyphcollection_and_linesegments(latexstring::LaTeXString, index, end function plot!(plot::Text{<:Tuple{<:AbstractString}}) - text!(plot, plot.position; text = plot[1], plot.attributes...) + attrs = copy(plot.attributes) + pop!(attrs, :calculated_colors) + text!(plot, plot.position; attrs..., text = plot[1]) plot end From 23314e6ccc3e3586b16b413277d1724bae12b8df Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:02:10 +0100 Subject: [PATCH 015/106] add attribute deprecation mechanism --- MakieCore/src/basic_plots.jl | 6 ++++++ MakieCore/src/recipes.jl | 14 +++++++++++++- src/basic_recipes/text.jl | 7 ++++--- test/text.jl | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 9719cec8ef9..550e52c8539 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -603,6 +603,12 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) @mixin mixin_colormap_attributes end +function deprecated_attributes(::Type{<:Text}) + [ + (; attribute = :textsize, message = "`textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.", error = true) + ] +end + """ poly(vertices, indices; kwargs...) poly(points; kwargs...) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index b36e9540cfd..ee7cb640c89 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -405,15 +405,27 @@ e.g.: """ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! +deprecated_attributes(_) = NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}[] + function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return allowlist = [:xautolimits, :yautolimits, :zautolimits, :label] - unknown = setdiff(keys(kw), nameset, allowlist) + deprecations = deprecated_attributes(P)::Vector{NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}} + unknown = setdiff(keys(kw), nameset, allowlist, first.(deprecations)) if !isempty(unknown) n = length(unknown) throw(ArgumentError( """Invalid attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). The available plot attributes are: $(join(sort(collect(nameset)), ", ", " and ")). Additional generic keywords are $(join(allowlist, ", ", " and ")).""" )) end + for (deprecated, message, should_error) in deprecations + if haskey(kw, deprecated) + if should_error + throw(ArgumentError(message)) + else + @warn message + end + end + end end \ No newline at end of file diff --git a/src/basic_recipes/text.jl b/src/basic_recipes/text.jl index b0c754c4bc2..29151dd5ade 100644 --- a/src/basic_recipes/text.jl +++ b/src/basic_recipes/text.jl @@ -1,11 +1,10 @@ function check_textsize_deprecation(@nospecialize(dictlike)) if haskey(dictlike, :textsize) - throw(ArgumentError("The attribute `textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.")) + throw(ArgumentError("`textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.")) end end function plot!(plot::Text) - check_textsize_deprecation(plot) positions = plot[1] # attach a function to any text that calculates the glyph layout and stores it glyphcollections = Observable(GlyphCollection[]; ignore_equal_values=true) @@ -145,7 +144,9 @@ plot!(plot::Text{<:Tuple{<:GlyphCollection}}) = plot plot!(plot::Text{<:Tuple{<:AbstractArray{<:GlyphCollection}}}) = plot function plot!(plot::Text{<:Tuple{<:AbstractArray{<:AbstractString}}}) - text!(plot, plot.position; text = plot[1], plot.attributes...) + attrs = copy(plot.attributes) + pop!(attrs, :calculated_colors) + text!(plot, plot.position; attrs..., text = plot[1]) plot end diff --git a/test/text.jl b/test/text.jl index 4881afa3a12..4f9f377acd0 100644 --- a/test/text.jl +++ b/test/text.jl @@ -118,7 +118,7 @@ end text([L"text", L"text"], position = [Point2f(0, 0), Point2f(1, 1)]) text(collect(zip([L"text", L"text"], [Point2f(0, 0), Point2f(1, 1)]))) - err = ArgumentError("The attribute `textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.") + err = ArgumentError("`textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.") @test_throws err Label(Figure()[1, 1], "hi", textsize = 30) @test_throws err text(1, 2, text = "hi", textsize = 30) end From f2906e21a0c3de8d407c1e2f43068ca91a7183dd Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:03:13 +0100 Subject: [PATCH 016/106] add explanation --- MakieCore/src/recipes.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index ee7cb640c89..925a0b4940b 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -405,6 +405,8 @@ e.g.: """ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! +# plot types can overload this to throw errors or show warnings when deprecated attributes are used. +# this is easier than if every plot type added manual checks in its `plot!` methods deprecated_attributes(_) = NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}[] function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) From b2ff0bf0003df384c3d1bacfc9e01756a243c849 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:15:13 +0100 Subject: [PATCH 017/106] remove `text` for GLMakie --- GLMakie/src/GLAbstraction/GLTypes.jl | 1 + src/basic_recipes/text.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/GLMakie/src/GLAbstraction/GLTypes.jl b/GLMakie/src/GLAbstraction/GLTypes.jl index 206a8dda42a..0c1a6a1ebc0 100644 --- a/GLMakie/src/GLAbstraction/GLTypes.jl +++ b/GLMakie/src/GLAbstraction/GLTypes.jl @@ -385,6 +385,7 @@ function RenderObject( try data[k] = gl_convert(v) catch e + @error "gl_convert for key `$k` failed" rethrow(e) end diff --git a/src/basic_recipes/text.jl b/src/basic_recipes/text.jl index 29151dd5ade..9f3ae2af1b4 100644 --- a/src/basic_recipes/text.jl +++ b/src/basic_recipes/text.jl @@ -81,6 +81,7 @@ function plot!(plot::Text) # remove attributes that the backends will choke on pop!(t.attributes, :font) pop!(t.attributes, :fonts) + pop!(t.attributes, :text) linesegments!(plot, linesegs_shifted; linewidth = linewidths, color = linecolors, space = :pixel) plot From 083b66f7f81ae2fa23a1739f13219187bf1b1903 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:17:48 +0100 Subject: [PATCH 018/106] fix contour volume attributes --- src/basic_recipes/contours.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/basic_recipes/contours.jl b/src/basic_recipes/contours.jl index 861b9e249ed..063bb8c0d39 100644 --- a/src/basic_recipes/contours.jl +++ b/src/basic_recipes/contours.jl @@ -160,6 +160,10 @@ function plot!(plot::Contour{<: Tuple{X, Y, Z, Vol}}) where {X, Y, Z, Vol} pop!(attr, :labelsize) pop!(attr, :labelcolor) pop!(attr, :labelformatter) + pop!(attr, :color) + pop!(attr, :linestyle) + pop!(attr, :enable_depth) + pop!(attr, :linewidth) volume!(plot, attr, x, y, z, volume) end From 3fe0f7fcae99872e7ce2f1daea1f32efecdc5da9 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:29:07 +0100 Subject: [PATCH 019/106] add rasterize to allowlist --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 925a0b4940b..8de8dfa5c9b 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -412,7 +412,7 @@ deprecated_attributes(_) = NamedTuple{(:attribute, :message, :error), Tuple{Symb function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return - allowlist = [:xautolimits, :yautolimits, :zautolimits, :label] + allowlist = [:xautolimits, :yautolimits, :zautolimits, :label, :rasterize] deprecations = deprecated_attributes(P)::Vector{NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}} unknown = setdiff(keys(kw), nameset, allowlist, first.(deprecations)) if !isempty(unknown) From 9fa64ef6da798c7dcf0865ffe72755279c4799ec Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 11:57:44 +0100 Subject: [PATCH 020/106] add `enable_depth` to volume --- MakieCore/src/basic_plots.jl | 1 + src/basic_recipes/contours.jl | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 550e52c8539..3e21eca2fdd 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -291,6 +291,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) isorange = 0.05 "Sets whether the volume data should be sampled with interpolation." interpolate = true + enable_depth = true @mixin mixin_generic_plot_attributes @mixin mixin_shading_attributes @mixin mixin_colormap_attributes diff --git a/src/basic_recipes/contours.jl b/src/basic_recipes/contours.jl index 063bb8c0d39..c38ff209a91 100644 --- a/src/basic_recipes/contours.jl +++ b/src/basic_recipes/contours.jl @@ -162,7 +162,6 @@ function plot!(plot::Contour{<: Tuple{X, Y, Z, Vol}}) where {X, Y, Z, Vol} pop!(attr, :labelformatter) pop!(attr, :color) pop!(attr, :linestyle) - pop!(attr, :enable_depth) pop!(attr, :linewidth) volume!(plot, attr, x, y, z, volume) end From 812ce26e4fc08edfd3704c1dfd9956710799e0d9 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:01:18 +0100 Subject: [PATCH 021/106] add `matcap` to mesh --- MakieCore/src/basic_plots.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 3e21eca2fdd..173ced32dcd 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -428,6 +428,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) "sets whether colors should be interpolated" interpolate = true cycle = [:color => :patchcolor] + matcap = nothing @mixin mixin_generic_plot_attributes @mixin mixin_shading_attributes @mixin mixin_colormap_attributes From b2886ce70cbb12e0659564e216ca561d5646a7d7 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:06:57 +0100 Subject: [PATCH 022/106] set `fxaa = false` on scatter, lines, linesegments, text --- MakieCore/src/basic_plots.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 173ced32dcd..f92caab5b90 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -60,7 +60,7 @@ function mixin_generic_plot_attributes() "sets the transformation space for box encompassing the plot. See `Makie.spaces()` for possible inputs." space = :data "adjusts whether the plot is rendered with fxaa (anti-aliasing)." - fxaa = true + fxaa = false end end @@ -359,6 +359,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] + fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes end @@ -394,6 +395,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] + fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes end @@ -489,7 +491,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) markerspace = :pixel "Sets which attributes to cycle when creating multiple plots" cycle = [:color] - + fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes end @@ -600,7 +602,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) offset = (0.0, 0.0) "Specifies a linewidth limit for text. If a word overflows this limit, a newline is inserted before it. Negative numbers disable word wrapping." word_wrap_width = -1 - + fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes end From a58d191f4ae7c4b05133da5c3020fdab0fb32b06 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:09:47 +0100 Subject: [PATCH 023/106] move fxaa after mixins --- MakieCore/src/basic_plots.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index f92caab5b90..772ac2aea99 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -60,7 +60,7 @@ function mixin_generic_plot_attributes() "sets the transformation space for box encompassing the plot. See `Makie.spaces()` for possible inputs." space = :data "adjusts whether the plot is rendered with fxaa (anti-aliasing)." - fxaa = false + fxaa = true end end @@ -359,9 +359,9 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] - fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes + fxaa = false end """ @@ -395,9 +395,9 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] - fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes + fxaa = false end # alternatively, mesh3d? Or having only mesh instead of poly + mesh and figure out 2d/3d via dispatch @@ -491,9 +491,9 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) markerspace = :pixel "Sets which attributes to cycle when creating multiple plots" cycle = [:color] - fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes + fxaa = false end """ @@ -602,9 +602,9 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) offset = (0.0, 0.0) "Specifies a linewidth limit for text. If a word overflows this limit, a newline is inserted before it. Negative numbers disable word wrapping." word_wrap_width = -1 - fxaa = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes + fxaa = false end function deprecated_attributes(::Type{<:Text}) From 42ff5fb21c11c3177b918831c07820666d6dbb14 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:20:53 +0100 Subject: [PATCH 024/106] fix keywords --- docs/reference/plots/stephist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/plots/stephist.md b/docs/reference/plots/stephist.md index cd4d6238045..43573242d38 100644 --- a/docs/reference/plots/stephist.md +++ b/docs/reference/plots/stephist.md @@ -14,7 +14,7 @@ data = randn(1000) f = Figure() stephist(f[1, 1], data, bins = 10) -stephist(f[1, 2], data, bins = 20, color = :red, strokewidth = 1, strokecolor = :black) +stephist(f[1, 2], data, bins = 20, color = :red, linewidth = 3) stephist(f[2, 1], data, bins = [-5, -2, -1, 0, 1, 2, 5], color = :gray) stephist(f[2, 2], data, normalization = :pdf) f From 0df0503187738d6a072549f7e503b81a030a78cb Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:30:34 +0100 Subject: [PATCH 025/106] remove markersize attribute --- docs/reference/plots/linesegments.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/plots/linesegments.md b/docs/reference/plots/linesegments.md index 2f336f9e2d4..d76ed361122 100644 --- a/docs/reference/plots/linesegments.md +++ b/docs/reference/plots/linesegments.md @@ -41,13 +41,13 @@ ps = rand(Point3f, 500) cs = rand(500) f = Figure(size = (600, 650)) Label(f[1, 1], "base", tellwidth = false) -linesegments(f[2, 1], ps, color = cs, markersize = 20, fxaa = false) +linesegments(f[2, 1], ps, color = cs, fxaa = false) Label(f[1, 2], "fxaa = true", tellwidth = false) -linesegments(f[2, 2], ps, color = cs, markersize = 20, fxaa = true) +linesegments(f[2, 2], ps, color = cs, fxaa = true) Label(f[3, 1], "transparency = true", tellwidth = false) -linesegments(f[4, 1], ps, color = cs, markersize = 20, transparency = true) +linesegments(f[4, 1], ps, color = cs, transparency = true) Label(f[3, 2], "overdraw = true", tellwidth = false) -linesegments(f[4, 2], ps, color = cs, markersize = 20, overdraw = true) +linesegments(f[4, 2], ps, color = cs, overdraw = true) f ``` \end{examplefigure} \ No newline at end of file From 5d0e437ad62208f6e7b55d8e45f938af2ae50afe Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:42:46 +0100 Subject: [PATCH 026/106] remove invalid markersize --- docs/reference/plots/lines.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/plots/lines.md b/docs/reference/plots/lines.md index 83c3e4f82e8..a41d6688d52 100644 --- a/docs/reference/plots/lines.md +++ b/docs/reference/plots/lines.md @@ -69,13 +69,13 @@ ps = rand(Point3f, 500) cs = rand(500) f = Figure(size = (600, 650)) Label(f[1, 1], "base", tellwidth = false) -lines(f[2, 1], ps, color = cs, markersize = 20, fxaa = false) +lines(f[2, 1], ps, color = cs, fxaa = false) Label(f[1, 2], "fxaa = true", tellwidth = false) -lines(f[2, 2], ps, color = cs, markersize = 20, fxaa = true) +lines(f[2, 2], ps, color = cs, fxaa = true) Label(f[3, 1], "transparency = true", tellwidth = false) -lines(f[4, 1], ps, color = cs, markersize = 20, transparency = true) +lines(f[4, 1], ps, color = cs, transparency = true) Label(f[3, 2], "overdraw = true", tellwidth = false) -lines(f[4, 2], ps, color = cs, markersize = 20, overdraw = true) +lines(f[4, 2], ps, color = cs, overdraw = true) f ``` \end{examplefigure} \ No newline at end of file From 2d76684dc223b8b150191bf87d6e26dfd8bd4e66 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 12:48:29 +0100 Subject: [PATCH 027/106] add depthsorting to attributes for scatter --- MakieCore/src/basic_plots.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 772ac2aea99..340f520fbbb 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -491,6 +491,8 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) markerspace = :pixel "Sets which attributes to cycle when creating multiple plots" cycle = [:color] + "Enables depth-sorting of markers which can improve border artifacts. Currently supported in GLMakie only." + depthsorting = false @mixin mixin_generic_plot_attributes @mixin mixin_colormap_attributes fxaa = false From b60cd668899cae9d85d35fd09afd778c593f04c5 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 14 Feb 2024 15:21:51 +0100 Subject: [PATCH 028/106] fix forwarded attributes --- src/interfaces.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interfaces.jl b/src/interfaces.jl index 19c35941eb0..64458e5d1cc 100644 --- a/src/interfaces.jl +++ b/src/interfaces.jl @@ -138,7 +138,7 @@ function Plot{Func}(args::Tuple, plot_attributes::Dict) where {Func} if used_attrs === () args_converted = convert_arguments(P, map(to_value, args)...) else - kw = [Pair(k, to_value(v)) for (k, v) in plot_attributes if k in used_attrs] + kw = [Pair(k, to_value(pop!(plot_attributes, k))) for k in used_attrs if haskey(plot_attributes, k)] args_converted = convert_arguments(P, map(to_value, args)...; kw...) end PNew, converted = apply_convert!(P, Attributes(), args_converted) From 8ac24212fe5061b22c4b657b881e618daa415e59 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 16:13:08 +0100 Subject: [PATCH 029/106] add absorption to volume --- MakieCore/src/basic_plots.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 340f520fbbb..ca3633cc30c 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -292,6 +292,7 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) "Sets whether the volume data should be sampled with interpolation." interpolate = true enable_depth = true + absorption = 1f0 @mixin mixin_generic_plot_attributes @mixin mixin_shading_attributes @mixin mixin_colormap_attributes From 46ee1d3ad559fe748a02f60de6685c08df2b0906 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Wed, 14 Feb 2024 19:21:03 +0100 Subject: [PATCH 030/106] don't use `used_attributes` for datashader canvas convert --- src/basic_recipes/datashader.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/basic_recipes/datashader.jl b/src/basic_recipes/datashader.jl index d9bf42b2244..31408838f8d 100644 --- a/src/basic_recipes/datashader.jl +++ b/src/basic_recipes/datashader.jl @@ -458,20 +458,18 @@ function Makie.plot!(p::DataShader{<:Tuple{Dict{String, Vector{Point{2, Float32} colors = Dict(k => Makie.wong_colors()[i] for (i, (k, v)) in enumerate(categories)) p._categories = colors op = map(total -> (x -> log10(x + 1) / log10(total + 1)), toal_value) - for (k, canvas) in canvases + + for (k, canv) in canvases color = colors[k] cmap = [(color, 0.0), (color, 1.0)] - image!(p, canvas; colorrange=Vec2f(0, 1), colormap=cmap, operation=identity, local_operation=op) + image!(p, canv, identity, op; colorrange=Vec2f(0, 1), colormap=cmap) end return p end data_limits(p::DataShader) = p._boundingbox[] -used_attributes(::Canvas) = (:operation, :local_operation) - -function convert_arguments(P::Type{<:Union{MeshScatter,Image,Surface,Contour,Contour3d}}, canvas::Canvas; - operation=automatic, local_operation=identity) +function convert_arguments(P::Type{<:Union{MeshScatter,Image,Surface,Contour,Contour3d}}, canvas::Canvas, operation=automatic, local_operation=identity) pixel = Aggregation.get_aggregation(canvas; operation=operation, local_operation=local_operation) (xmin, ymin), (xmax, ymax) = extrema(canvas.bounds) return convert_arguments(P, xmin .. xmax, ymin .. ymax, pixel) From 510472376b489d67217486bd761e02e3cea6006f Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Thu, 15 Feb 2024 09:19:41 +0100 Subject: [PATCH 031/106] fix positional args --- src/basic_recipes/datashader.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic_recipes/datashader.jl b/src/basic_recipes/datashader.jl index 31408838f8d..775ab71e011 100644 --- a/src/basic_recipes/datashader.jl +++ b/src/basic_recipes/datashader.jl @@ -400,8 +400,8 @@ function Makie.plot!(p::DataShader{<: Tuple{<: AbstractVector{<: Point}}}) return end p.raw_colorrange = colorrange - image!(p, canvas_with_aggregation; - operation=p.operation, local_operation=p.local_operation, interpolate=p.interpolate, + image!(p, canvas_with_aggregation, p.operation, p.local_operation; + interpolate=p.interpolate, MakieCore.generic_plot_attributes(p)..., MakieCore.colormap_attributes(p)...) return p From e541e4360e4668e6bcd225c9f35eadcc9974e5c0 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Thu, 15 Feb 2024 09:40:07 +0100 Subject: [PATCH 032/106] image --- MakieCore/src/basic_plots.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index ca3633cc30c..7b37290d7d4 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -199,13 +199,13 @@ $(Base.Docs.doc(colormap_attributes!)) $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(Image, x, y, image) do scene - attr = Attributes(; - interpolate = true, - fxaa = false, - ) - generic_plot_attributes!(attr) - return colormap_attributes!(attr, [:black, :white]) +@recipe Image x y image begin + "Sets whether colors should be interpolated between pixels." + interpolate = true + @mixin mixin_generic_plot_attributes + @mixin mixin_colormap_attributes + fxaa = false + colormap = [:black, :white] end """ From a89cc54d0ced552f667fb134dfc4972d6b7c73e9 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Thu, 15 Feb 2024 12:06:01 +0100 Subject: [PATCH 033/106] add better printing and rudimentary tests --- MakieCore/src/recipes.jl | 72 +++++++++++++++++++++++++++++++++++++--- test/pipeline.jl | 14 ++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 8de8dfa5c9b..d2007d0e72a 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -409,17 +409,79 @@ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! # this is easier than if every plot type added manual checks in its `plot!` methods deprecated_attributes(_) = NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}[] +struct InvalidAttributeError <: Exception + plottype::Type + attributes::Set{Symbol} +end + +function print_columns(io::IO, v::Vector{String}; gapsize = 2, row_major = true, cols = displaysize(io)[2]) + lens = length.(v) # for unicode ligatures etc this won't work, but we don't use those for attribute names + function col_widths(ncols) + max_widths = zeros(Int, ncols) + for (i, len) in enumerate(lens) + j = mod1(i, ncols) + max_widths[j] = max(max_widths[j], len) + end + return max_widths + end + ncols = 1 + while true + widths = col_widths(ncols) + aggregated_width = (sum(widths) + (ncols-1) * gapsize) + if aggregated_width > cols + ncols = max(1, ncols-1) + break + end + ncols += 1 + end + widths = col_widths(ncols) + + for (i, (str, len)) in enumerate(zip(v, lens)) + j = mod1(i, ncols) + last_col = j == ncols + print(io, str) + remaining = widths[j] - len + !last_col * gapsize + for _ in 1:remaining + print(io, ' ') + end + if last_col + print(io, '\n') + end + end + + return +end + +function Base.showerror(io::IO, i::InvalidAttributeError) + print(io, "InvalidAttributeError: ") + n = length(i.attributes) + println(io, "Plot type $(i.plottype) does not recognize attribute$(n > 1 ? "s" : "") $(join(i.attributes, ", ", " and ")).") + nameset = sort(string.(collect(attribute_names(i.plottype)))) + println(io) + println(io, "The available plot attributes for $(i.plottype) are:") + println(io) + print_columns(io, nameset; cols = displaysize(stderr)[2]) + allowlist = attribute_name_allowlist() + println(io) + println(io) + println(io, "Generic attributes are:") + println(io) + print_columns(io, sort(string.(allowlist)); cols = displaysize(stderr)[2]) + println(io) +end + +function attribute_name_allowlist() + [:xautolimits, :yautolimits, :zautolimits, :label, :rasterize] +end + function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return - allowlist = [:xautolimits, :yautolimits, :zautolimits, :label, :rasterize] + allowlist = attribute_name_allowlist() deprecations = deprecated_attributes(P)::Vector{NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}} unknown = setdiff(keys(kw), nameset, allowlist, first.(deprecations)) if !isempty(unknown) - n = length(unknown) - throw(ArgumentError( - """Invalid attribute$(n > 1 ? "s" : "") for plot type $P: $(join(unknown, ", ", " and ")). The available plot attributes are: $(join(sort(collect(nameset)), ", ", " and ")). Additional generic keywords are $(join(allowlist, ", ", " and ")).""" - )) + throw(InvalidAttributeError(P, unknown)) end for (deprecated, message, should_error) in deprecations if haskey(kw, deprecated) diff --git a/test/pipeline.jl b/test/pipeline.jl index 6f18bc98729..fcc4c0c3ec0 100644 --- a/test/pipeline.jl +++ b/test/pipeline.jl @@ -147,3 +147,17 @@ end plots = test_default(rand(4, 4, 4)) @test all(x -> x isa Volume, plots) end + +@testset "validated attributes" begin + InvalidAttributeError = Makie.MakieCore.InvalidAttributeError + @test_throws InvalidAttributeError heatmap(zeros(10, 10); does_not_exist = 123) + @test_throws InvalidAttributeError image(zeros(10, 10); does_not_exist = 123) + @test_throws InvalidAttributeError scatter(1:10; does_not_exist = 123) + @test_throws InvalidAttributeError lines(1:10; does_not_exist = 123) + @test_throws InvalidAttributeError linesegments(1:10; does_not_exist = 123) + @test_throws InvalidAttributeError text(1:10; does_not_exist = 123) + @test_throws InvalidAttributeError volume(zeros(3, 3, 3); does_not_exist = 123) + @test_throws InvalidAttributeError meshscatter(1:10; does_not_exist = 123) + @test_throws InvalidAttributeError poly(Point2f[]; does_not_exist = 123) + @test_throws InvalidAttributeError mesh(rand(Point3f, 3); does_not_exist = 123) +end \ No newline at end of file From cc0f71434f1f8ce44eee167a30c2ecd2917922a8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 16 Feb 2024 11:09:31 +0100 Subject: [PATCH 034/106] make allowlist a tuple for fewer allocations --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index d2007d0e72a..db113501bb3 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -471,7 +471,7 @@ function Base.showerror(io::IO, i::InvalidAttributeError) end function attribute_name_allowlist() - [:xautolimits, :yautolimits, :zautolimits, :label, :rasterize] + (:xautolimits, :yautolimits, :zautolimits, :label, :rasterize) end function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) From f4833e46a84fa406cf52d134e05196cdf681fd75 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 16 Feb 2024 11:18:07 +0100 Subject: [PATCH 035/106] attribute names tuple instead of set --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index db113501bb3..2e994eeb7cc 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -231,7 +231,7 @@ macro recipe(Tsym::Symbol, args...) sym in MakieCore.attribute_names(T) end function MakieCore.attribute_names(::Type{<:$(PlotType)}) - Set{Symbol}([$([QuoteNode(a.symbol) for a in attrs]...)]) + ($([QuoteNode(a.symbol) for a in attrs]...),) end function $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) From 49851e6772b7df35a1a64e770ac861ada936b602 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 16 Feb 2024 11:48:33 +0100 Subject: [PATCH 036/106] make deprecations also a tuple --- MakieCore/src/basic_plots.jl | 6 +++--- MakieCore/src/recipes.jl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 7b37290d7d4..9edc27edf91 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -611,9 +611,9 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) end function deprecated_attributes(::Type{<:Text}) - [ - (; attribute = :textsize, message = "`textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.", error = true) - ] + ( + (; attribute = :textsize, message = "`textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.", error = true), + ) end """ diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 2e994eeb7cc..c9026d790c9 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -407,7 +407,7 @@ plottype(plot_args...) = Plot{plot} # default to dispatch to type recipes! # plot types can overload this to throw errors or show warnings when deprecated attributes are used. # this is easier than if every plot type added manual checks in its `plot!` methods -deprecated_attributes(_) = NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}[] +deprecated_attributes(_) = () struct InvalidAttributeError <: Exception plottype::Type @@ -478,7 +478,7 @@ function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) nameset = attribute_names(P) nameset === nothing && return allowlist = attribute_name_allowlist() - deprecations = deprecated_attributes(P)::Vector{NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}} + deprecations = deprecated_attributes(P)::Tuple{Vararg{NamedTuple{(:attribute, :message, :error), Tuple{Symbol, String, Bool}}}} unknown = setdiff(keys(kw), nameset, allowlist, first.(deprecations)) if !isempty(unknown) throw(InvalidAttributeError(P, unknown)) From e38536a0b146913de945952a78114b60b664be51 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 16 Feb 2024 15:46:53 +0100 Subject: [PATCH 037/106] avoid intermediate vector to speed up attribute creation --- MakieCore/src/recipes.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index c9026d790c9..a6bde30fb2e 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -309,7 +309,7 @@ end function make_default_theme_expr(attrs, scenesym::Symbol) - pairs = map(attrs) do a + exprs = map(attrs) do a d = a.default if d isa Expr && d.head === :macrocall && d.args[1] == Symbol("@inherit") @@ -331,12 +331,14 @@ function make_default_theme_expr(attrs, scenesym::Symbol) end end - Expr(:call, :(=>), QuoteNode(a.symbol), d) + :(attr[$(QuoteNode(a.symbol))] = $d) end quote thm = theme($scenesym) - Attributes([$(pairs...)]) + attr = Attributes() + $(exprs...) + attr end end @@ -466,7 +468,7 @@ function Base.showerror(io::IO, i::InvalidAttributeError) println(io) println(io, "Generic attributes are:") println(io) - print_columns(io, sort(string.(allowlist)); cols = displaysize(stderr)[2]) + print_columns(io, sort([string(a) for a in allowlist]); cols = displaysize(stderr)[2]) println(io) end From 5f6a960b0e20e29fac6ede690bc017fac792df09 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 16 Feb 2024 19:45:12 +0100 Subject: [PATCH 038/106] apply same optimization to blocks --- src/makielayout/blocks.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/makielayout/blocks.jl b/src/makielayout/blocks.jl index 9df779e54e9..a4646f5af7c 100644 --- a/src/makielayout/blocks.jl +++ b/src/makielayout/blocks.jl @@ -137,7 +137,7 @@ end function make_attr_dict_expr(attrs, sceneattrsym, curthemesym) - pairs = map(attrs) do a + exprs = map(attrs) do a d = a.default if d isa Expr && d.head === :macrocall && d.args[1] == Symbol("@inherit") @@ -162,10 +162,14 @@ function make_attr_dict_expr(attrs, sceneattrsym, curthemesym) end end - Expr(:call, :(=>), QuoteNode(a.symbol), d) + :(d[$(QuoteNode(a.symbol))] = $d) end - :(Dict($(pairs...))) + quote + d = Dict{Symbol,Any}() + $(exprs...) + d + end end From 8e100af6b2240d1a97c668d507e643e1fd769baf Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 18 Feb 2024 15:47:59 +0100 Subject: [PATCH 039/106] implement mechanism to augment user docstring --- MakieCore/src/recipes.jl | 64 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index a6bde30fb2e..2e54fa9b07c 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -215,11 +215,32 @@ macro recipe(Tsym::Symbol, args...) attrblock = expand_mixins(attrblock) attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] + docs_placeholder = gensym() + q = quote + # This part is as far as I know the only way to modify the docstring on top of the + # recipe, so that we can offer the convenience of automatic augmented docstrings + # but combine them with the simplicity of using a normal docstring. + # The trick is to mark some variable (in this case a gensymmed placeholder) with the + # Core.@__doc__ macro, which causes this variable to get assigned the docstring on top + # of the @recipe invocation. From there, it can then be retrieved, modified, and later + # attached to plotting function by using @doc again. We also delete the binding to the + # temporary variable so no unnecessary docstrings stay in place. + Core.@__doc__ $(esc(docs_placeholder)) = nothing + binding = Docs.Binding(@__MODULE__, $(QuoteNode(docs_placeholder))) + user_docstring = if haskey(Docs.meta(@__MODULE__), binding) + _docstring = @doc($docs_placeholder) + delete!(Docs.meta(@__MODULE__), binding) + _docstring + else + "No docstring defined.\n" + end + + $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) - Core.@__doc__ function ($funcname)(args...; kw...) + function ($funcname)(args...; kw...) kwdict = Dict{Symbol, Any}(kw) _create_plot($funcname, kwdict, args...) end @@ -257,6 +278,9 @@ macro recipe(Tsym::Symbol, args...) ) ) end + + docstring_modified = make_recipe_docstring($PlotType, user_docstring) + @doc docstring_modified $funcname_sym export $PlotType, $funcname, $funcname! end @@ -274,7 +298,43 @@ macro recipe(Tsym::Symbol, args...) q end -_defaultstring(x) = string(Base.remove_linenums!(x)) +function make_recipe_docstring(P::Type{<:Plot}, docstring) + io = IOBuffer() + + print(io, docstring) + + # println(io, "```") + println(io, "## Attributes") + println(io, "Type `?$P.attribute` in the REPL to get more information on any specific attribute.") + println(io) + println(io, "|Attribute|Default|") + println(io, "|:--|:--|") + + names = sort(collect(attribute_names(P))) + exprdict = attribute_default_expressions(P) + for name in names + print(io, "| `", name, "` |") + default = exprdict[name] + println(io, "`", default, "`|") + end + + return String(take!(io)) +end + +# from MacroTools +isline(ex) = (ex isa Expr && ex.head === :line) || isa(ex, LineNumberNode) +rmlines(x) = x +function rmlines(x::Expr) + # Do not strip the first argument to a macrocall, which is + # required. + if x.head === :macrocall && length(x.args) >= 2 + Expr(x.head, x.args[1], nothing, filter(x->!isline(x), x.args[3:end])...) + else + Expr(x.head, filter(x->!isline(x), x.args)...) + end +end + +_defaultstring(x) = string(rmlines(x)) _defaultstring(x::String) = repr(x) function extract_attribute_metadata(arg) From 06a8ef0aff744dde64df972a2525080524ea035d Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 18 Feb 2024 15:52:28 +0100 Subject: [PATCH 040/106] delete manually written out attribute docs --- MakieCore/src/basic_plots.jl | 154 ----------------------------------- 1 file changed, 154 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 9edc27edf91..b3ee37cc9bb 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -188,16 +188,6 @@ calculated_attributes!(plot::T) where T = calculated_attributes!(T, plot) image(image) Plots an image on a rectangle bounded by `x` and `y` (defaults to size of image). - -## Attributes - -### Specific to `Image` - -- `interpolate::Bool = true` sets whether colors should be interpolated. - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Image x y image begin "Sets whether colors should be interpolated between pixels." @@ -236,16 +226,6 @@ Pairs that are missing from the resulting grid will be treated as if `zvector` h If `x` and `y` are omitted with a matrix argument, they default to `x, y = axes(matrix)`. Note that `heatmap` is slower to render than `image` so `image` should be preferred for large, regularly spaced grids. - -## Attributes - -### Specific to `Heatmap` - -- `interpolate::Bool = false` sets whether colors should be interpolated. - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Heatmap x y values begin "Sets whether colors should be interpolated" @@ -266,21 +246,6 @@ Available algorithms are: * `:absorptionrgba` => AbsorptionRGBA * `:additive` => AdditiveRGBA * `:indexedabsorption` => IndexedAbsorptionRGBA - -## Attributes - -### Specific to `Volume` - -- `algorithm::Union{Symbol, RaymarchAlgorithm} = :mip` sets the volume algorithm that is used. -- `isorange::Real = 0.05` sets the range of values picked up by the IsoValue algorithm. -- `isovalue = 0.5` sets the target value for the IsoValue algorithm. -- `interpolate::Bool = true` sets whether the volume data should be sampled with interpolation. - -$(Base.Docs.doc(shading_attributes!)) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Volume x y z volume begin "Sets the volume algorithm that is used." @@ -304,19 +269,6 @@ end Plots a surface, where `(x, y)` define a grid whose heights are the entries in `z`. `x` and `y` may be `Vectors` which define a regular grid, **or** `Matrices` which define an irregular grid. - -## Attributes - -### Specific to `Surface` - -- `invert_normals::Bool = false` inverts the normals generated for the surface. This can be useful to illuminate the other side of the surface. -- `color = nothing`, can be set to an `Matrix{<: Union{Number, Colorant}}` to color surface independent of the `z` component. If `color=nothing`, it defaults to `color=z`. - -$(Base.Docs.doc(shading_attributes!)) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Surface x y z begin "Can be set to an `Matrix{<: Union{Number, Colorant}}` to color surface independent of the `z` component. If `color=nothing`, it defaults to `color=z`." @@ -336,20 +288,6 @@ end Creates a connected line plot for each element in `(x, y, z)`, `(x, y)` or `positions`. `NaN` values are displayed as gaps in the line. - -## Attributes - -### Specific to `Lines` - -- `color=theme(scene, :linecolor)` sets the color of the line. If no color is set, multiple calls to `line!` will cycle through the axis color palette. - Otherwise, one can set one color per line point by passing a `Vector{<:Colorant}`, or one colorant for the whole line. If color is a vector of numbers, the colormap args are used to map the numbers to colors. -- `cycle::Vector{Symbol} = [:color]` sets which attributes to cycle when creating multiple plots. -- `linestyle::Union{Nothing, Symbol, Linestyle} = nothing` sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`. -- `linewidth::Union{Real, Vector} = 1.5` sets the width of the line in pixel units. - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Lines positions begin "The color of the line." @@ -409,21 +347,6 @@ end mesh(xyz, faces) Plots a 3D or 2D mesh. Supported `mesh_object`s include `Mesh` types from [GeometryBasics.jl](https://github.com/JuliaGeometry/GeometryBasics.jl). - -## Attributes - -### Specific to `Mesh` - -- `color=theme(scene, :patchcolor)` sets the color of the mesh. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. - A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates. - Vector or Matrices of numbers can be used as well, which will use the colormap arguments to map the numbers to colors. -- `interpolate::Bool = false` sets whether colors should be interpolated. - -$(Base.Docs.doc(shading_attributes!)) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Mesh mesh begin "Sets the color of the mesh. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates." @@ -443,27 +366,6 @@ end scatter(x, y, z) Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`. - -## Attributes - -### Specific to `Scatter` - -- `color=theme(scene, :markercolor)` sets the color of the marker. If no color is set, multiple calls to `scatter!` will cycle through the axis color palette. - Otherwise, one can set one color per point by passing a `Vector{<:Colorant}`, or one colorant for the whole scatterplot. If color is a vector of numbers, the colormap args are used to map the numbers to colors. -- `cycle::Vector{Symbol} = [:color]` sets which attributes to cycle when creating multiple plots. -- `marker::Union{Symbol, Char, Matrix{<:Colorant}, BezierPath, Polygon}` sets the scatter marker. -- `markersize::Union{<:Real, Vec2f} = 9` sets the size of the marker. -- `markerspace::Symbol = :pixel` sets the space in which `markersize` is given. See `Makie.spaces()` for possible inputs. -- `strokewidth::Real = 0` sets the width of the outline around a marker. -- `strokecolor::Union{Symbol, <:Colorant} = :black` sets the color of the outline around a marker. -- `glowwidth::Real = 0` sets the size of a glow effect around the marker. -- `glowcolor::Union{Symbol, <:Colorant} = (:black, 0)` sets the color of the glow effect. -- `rotations::Union{Real, Billboard, Quaternion} = Billboard(0f0)` sets the rotation of the marker. A `Billboard` rotation is always around the depth axis. -- `transform_marker::Bool = false` controls whether the model matrix (without translation) applies to the marker itself, rather than just the positions. (If this is true, `scale!` and `rotate!` will affect the marker.) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Scatter positions begin "Sets the color of the marker. If no color is set, multiple calls to `scatter!` will cycle through the axis color palette." @@ -506,23 +408,6 @@ end Plots a mesh for each element in `(x, y, z)`, `(x, y)`, or `positions` (similar to `scatter`). `markersize` is a scaling applied to the primitive passed as `marker`. - -## Attributes - -### Specific to `MeshScatter` - -- `color = theme(scene, :markercolor)` sets the color of the marker. If no color is set, multiple calls to `meshscatter!` will cycle through the axis color palette. - Otherwise, one can set one color per point by passing a `Vector{<:Colorant}`, or one colorant for the whole meshscatterplot. If color is a vector of numbers, the colormap args are used to map the numbers to colors. -- `cycle::Vector{Symbol} = [:color]` sets which attributes to cycle when creating multiple plots. -- `marker::Union{Symbol, GeometryBasics.GeometryPrimitive, GeometryBasics.Mesh}` sets the scattered mesh. -- `markersize::Union{<:Real, Vec3f} = 0.1` sets the scale of the mesh. This can be given as a Vector to apply to each scattered mesh individually. -- `rotations::Union{Real, Vec3f, Quaternion} = 0` sets the rotation of the mesh. A numeric rotation is around the z-axis, a `Vec3f` causes the mesh to rotate such that the the z-axis is now that vector, and a quaternion describes a general rotation. This can be given as a Vector to apply to each scattered mesh individually. - -$(Base.Docs.doc(shading_attributes!)) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe MeshScatter positions begin "Sets the color of the marker." @@ -548,29 +433,6 @@ end Plots one or multiple texts passed via the `text` keyword. `Text` uses the `PointBased` conversion trait. - -## Attributes - -### Specific to `Text` - -- `color=theme(scene, :textcolor)` sets the color of the text. One can set one color per glyph by passing a `Vector{<:Colorant}`, or one colorant for the whole text. If color is a vector of numbers, the colormap args are used to map the numbers to colors. -- `text` specifies one piece of text or a vector of texts to show, where the number has to match the number of positions given. Makie supports `String` which is used for all normal text and `LaTeXString` which layouts mathematical expressions using `MathTeXEngine.jl`. -- `align::Tuple{Union{Symbol, Real}, Union{Symbol, Real}} = (:left, :bottom)` sets the alignment of the string w.r.t. `position`. Uses `:left, :center, :right, :top, :bottom, :baseline` or fractions. -- `font::Union{String, Vector{String}} = :regular` sets the font for the string or each character. -- `justification::Union{Real, Symbol} = automatic` sets the alignment of text w.r.t its bounding box. Can be `:left, :center, :right` or a fraction. Will default to the horizontal alignment in `align`. -- `rotation::Union{Real, Quaternion}` rotates text around the given position. -- `fontsize::Union{Real, Vec2f}` sets the size of each character. -- `markerspace::Symbol = :pixel` sets the space in which `fontsize` acts. See `Makie.spaces()` for possible inputs. -- `strokewidth::Real = 0` sets the width of the outline around a marker. -- `strokecolor::Union{Symbol, <:Colorant} = :black` sets the color of the outline around a marker. -- `glowwidth::Real = 0` sets the size of a glow effect around the marker. -- `glowcolor::Union{Symbol, <:Colorant} = (:black, 0)` sets the color of the glow effect. -- `word_wrap_width::Real = -1` specifies a linewidth limit for text. If a word overflows this limit, a newline is inserted before it. Negative numbers disable word wrapping. -- `transform_marker::Bool = false` controls whether the model matrix (without translation) applies to the glyph itself, rather than just the positions. (If this is true, `scale!` and `rotate!` will affect the text glyphs.) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Text positions begin "Specifies one piece of text or a vector of texts to show, where the number has to match the number of positions given. Makie supports `String` which is used for all normal text and `LaTeXString` which layouts mathematical expressions using `MathTeXEngine.jl`." @@ -632,22 +494,6 @@ When a shape is given (essentially anything decomposable by `GeometryBasics`), i Plots polygons, which are defined by `coordinates` (the coordinates of the vertices) and `connectivity` (the edges between the vertices). - -## Attributes - -### Specific to `Poly` -- `color=theme(scene, :patchcolor)` sets the color of the poly. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. - A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates. - Vector or Matrices of numbers can be used as well, which will use the colormap arguments to map the numbers to colors. - One can also use `Makie.LinePattern`, to cover the poly with a regular stroke pattern. -- `strokecolor::Union{Symbol, <:Colorant} = :black` sets the color of the outline around a marker. -- `strokecolormap`::Union{Symbol, Vector{<:Colorant}} = :viridis` sets the colormap that is sampled for numeric `color`s. -- `strokewidth::Real = 0` sets the width of the outline around a marker. -- `linestyle::Union{Nothing, Symbol, Vector} = nothing` sets the pattern of the line (e.g. `:solid`, `:dot`, `:dashdot`) - -$(Base.Docs.doc(colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe Poly begin """ From 39cecb98b0fb56d3beaf0aae94b81099265ea507 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 18 Feb 2024 15:58:13 +0100 Subject: [PATCH 041/106] use funcsym in docstring --- MakieCore/src/recipes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 2e54fa9b07c..54e9172562a 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -279,7 +279,7 @@ macro recipe(Tsym::Symbol, args...) ) end - docstring_modified = make_recipe_docstring($PlotType, user_docstring) + docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(funcname_sym)), user_docstring) @doc docstring_modified $funcname_sym export $PlotType, $funcname, $funcname! @@ -298,14 +298,14 @@ macro recipe(Tsym::Symbol, args...) q end -function make_recipe_docstring(P::Type{<:Plot}, docstring) +function make_recipe_docstring(P::Type{<:Plot}, funcsym, docstring) io = IOBuffer() print(io, docstring) # println(io, "```") println(io, "## Attributes") - println(io, "Type `?$P.attribute` in the REPL to get more information on any specific attribute.") + println(io, "Type `?$funcsym.attribute` in the REPL to get more information on any specific attribute.") println(io) println(io, "|Attribute|Default|") println(io, "|:--|:--|") From 857524ae9ee4c889eb5cbb34f76b208aca55f9f3 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 18 Feb 2024 16:24:09 +0100 Subject: [PATCH 042/106] incorporate attribute docs into docstring again --- MakieCore/src/recipes.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 54e9172562a..d28c62a8931 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -301,21 +301,21 @@ end function make_recipe_docstring(P::Type{<:Plot}, funcsym, docstring) io = IOBuffer() + attr_docstrings = _attribute_docs(P) + print(io, docstring) # println(io, "```") println(io, "## Attributes") - println(io, "Type `?$funcsym.attribute` in the REPL to get more information on any specific attribute.") println(io) - println(io, "|Attribute|Default|") - println(io, "|:--|:--|") names = sort(collect(attribute_names(P))) exprdict = attribute_default_expressions(P) for name in names - print(io, "| `", name, "` |") default = exprdict[name] - println(io, "`", default, "`|") + print(io, "**`", name, "`:**", " `", default, "` — ") + println(io, something(attr_docstrings[name], "*No docs available.*")) + println(io) end return String(take!(io)) From 3281470414b1e1ad5d7a842236001de8b76693fa Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 18 Feb 2024 16:27:56 +0100 Subject: [PATCH 043/106] use equal --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index d28c62a8931..79d402cb334 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -313,7 +313,7 @@ function make_recipe_docstring(P::Type{<:Plot}, funcsym, docstring) exprdict = attribute_default_expressions(P) for name in names default = exprdict[name] - print(io, "**`", name, "`:**", " `", default, "` — ") + print(io, "**`", name, "`** = ", " `", default, "` — ") println(io, something(attr_docstrings[name], "*No docs available.*")) println(io) end From 37c0cccbcbcebf9cad6e494708ffe12fc2883075 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Mon, 19 Feb 2024 11:04:02 +0100 Subject: [PATCH 044/106] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5e8be46f4..d922a1610df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] +- **Breaking (sort of)** Added a new `@recipe` variant which allows documenting attributes directly where they are defined and validating that all attributes are known whenever a plot is created. This is not breaking in the sense that the API changes, but user code is likely to break because of misspelled attribute names etc. that have so far gone unnoticed. - Fixed an issue where CairoMakie would unnecessarily rasterize polygons [#3605](https://github.com/MakieOrg/Makie.jl/pull/3605). - Added `PointBased` conversion trait to `scatterlines` recipe [#3603](https://github.com/MakieOrg/Makie.jl/pull/3603). From 4b9d8c9195b64cd973010f6eb90aee670c984f38 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 19:55:51 +0100 Subject: [PATCH 045/106] introduce `DocumentedAttributes` with macro --- MakieCore/src/basic_plots.jl | 106 +++++++++++------------ MakieCore/src/recipes.jl | 162 +++++++++++++++++++++++++++++++---- 2 files changed, 195 insertions(+), 73 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index b3ee37cc9bb..7b182499c59 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -41,7 +41,7 @@ function generic_plot_attributes(attr) end function mixin_generic_plot_attributes() - quote + @DocumentedAttributes begin transformation = automatic "Sets a model matrix for the plot. This overrides adjustments made with `translate!`, `rotate!` and `scale!`." model = automatic @@ -51,7 +51,7 @@ function mixin_generic_plot_attributes() transparency = false "Controls if the plot will draw over other plots. This specifically means ignoring depth checks in GL backends" overdraw = false - "Enables screen-space ambient occlusion." + "Adjusts whether the plot is rendered with ssao (screen space ambient occlusion). Note that this only makes sense in 3D plots and is only applicable with `fxaa = true`." ssao = false "sets whether this plot should be seen by `DataInspector`." inspectable = true @@ -101,13 +101,13 @@ function colormap_attributes(attr) end function mixin_colormap_attributes() - quote + @DocumentedAttributes begin """ Sets the colormap that is sampled for numeric `color`s. `PlotUtils.cgrad(...)`, `Makie.Reverse(any_colormap)` can be used as well, or any symbol from ColorBrewer or PlotUtils. To see all available color gradients, you can call `Makie.available_gradients()`. """ - colormap = @inherit :colormap :viridis + colormap = @inherit colormap :viridis """ The color transform function. Can be any function, but only works well together with `Colorbar` for `identity`, `log`, `log2`, `log10`, `sqrt`, `logit`, `Makie.pseudolog10` and `Makie.Symlog10`. """ @@ -155,7 +155,7 @@ function shading_attributes(attr) end function mixin_shading_attributes() - quote + @DocumentedAttributes begin "Sets the lighting algorithm used. Options are `NoShading` (no lighting), `FastShading` (AmbientLight + PointLight) or `MultiLightShading` (Multiple lights, GLMakie only). Note that this does not affect RPRMakie." shading = automatic "Sets how strongly the red, green and blue channel react to diffuse (scattered) light." @@ -166,8 +166,6 @@ function mixin_shading_attributes() shininess = 32.0f0 "Sets a weight for secondary light calculation with inverted normals." backlight = 0f0 - "Adjusts whether the plot is rendered with ssao (screen space ambient occlusion). Note that this only makes sense in 3D plots and is only applicable with `fxaa = true`." - ssao = false end end @@ -192,8 +190,8 @@ Plots an image on a rectangle bounded by `x` and `y` (defaults to size of image) @recipe Image x y image begin "Sets whether colors should be interpolated between pixels." interpolate = true - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... fxaa = false colormap = [:black, :white] end @@ -230,8 +228,8 @@ Note that `heatmap` is slower to render than `image` so `image` should be prefer @recipe Heatmap x y values begin "Sets whether colors should be interpolated" interpolate = false - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... end """ @@ -258,9 +256,9 @@ Available algorithms are: interpolate = true enable_depth = true absorption = 1f0 - @mixin mixin_generic_plot_attributes - @mixin mixin_shading_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_shading_attributes()... + mixin_colormap_attributes()... end """ @@ -275,9 +273,9 @@ Plots a surface, where `(x, y)` define a grid whose heights are the entries in ` color = nothing "Inverts the normals generated for the surface. This can be useful to illuminate the other side of the surface." invert_normals = false - @mixin mixin_generic_plot_attributes - @mixin mixin_shading_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_shading_attributes()... + mixin_colormap_attributes()... end """ @@ -289,17 +287,18 @@ Creates a connected line plot for each element in `(x, y, z)`, `(x, y)` or `posi `NaN` values are displayed as gaps in the line. """ + @recipe Lines positions begin "The color of the line." - color = @inherit :linecolor :black + color = @inherit linecolor "Sets the width of the line in pixel units" - linewidth = @inherit :linewidth 1.0 + linewidth = @inherit linewidth "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... fxaa = false end @@ -327,15 +326,15 @@ $(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ @recipe LineSegments positions begin "The color of the line." - color = @inherit :linecolor :black + color = @inherit linecolor "Sets the width of the line in pixel units" - linewidth = @inherit :linewidth 1.0 + linewidth = @inherit linewidth "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" linestyle = nothing "Sets which attributes to cycle when creating multiple plots." cycle = [:color] - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... fxaa = false end @@ -350,14 +349,14 @@ Plots a 3D or 2D mesh. Supported `mesh_object`s include `Mesh` types from [Geome """ @recipe Mesh mesh begin "Sets the color of the mesh. Can be a `Vector{<:Colorant}` for per vertex colors or a single `Colorant`. A `Matrix{<:Colorant}` can be used to color the mesh with a texture, which requires the mesh to contain texture coordinates." - color = @inherit :patchcolor :black + color = @inherit patchcolor "sets whether colors should be interpolated" interpolate = true cycle = [:color => :patchcolor] matcap = nothing - @mixin mixin_generic_plot_attributes - @mixin mixin_shading_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_shading_attributes()... + mixin_colormap_attributes()... end """ @@ -369,15 +368,15 @@ Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`. """ @recipe Scatter positions begin "Sets the color of the marker. If no color is set, multiple calls to `scatter!` will cycle through the axis color palette." - color = @inherit :markercolor :black + color = @inherit markercolor "Sets the scatter marker." - marker = @inherit :marker :circle + marker = @inherit marker "Sets the size of the marker." - markersize = @inherit :markersize 8 + markersize = @inherit markersize "Sets the color of the outline around a marker." - strokecolor = @inherit :markerstrokecolor :transparent + strokecolor = @inherit markerstrokecolor "Sets the width of the outline around a marker." - strokewidth = @inherit :markerstrokewidth 0 + strokewidth = @inherit markerstrokewidth "Sets the color of the glow effect around the marker." glowcolor = (:black, 0.0) "Sets the size of a glow effect around the marker." @@ -396,8 +395,8 @@ Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`. cycle = [:color] "Enables depth-sorting of markers which can improve border artifacts. Currently supported in GLMakie only." depthsorting = false - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... fxaa = false end @@ -411,19 +410,17 @@ Plots a mesh for each element in `(x, y, z)`, `(x, y)`, or `positions` (similar """ @recipe MeshScatter positions begin "Sets the color of the marker." - color = @inherit :markercolor :black + color = @inherit markercolor "Sets the scattered mesh." marker = :Sphere "Sets the scale of the mesh. This can be given as a `Vector` to apply to each scattered mesh individually." markersize = 0.1 "Sets the rotation of the mesh. A numeric rotation is around the z-axis, a `Vec3f` causes the mesh to rotate such that the the z-axis is now that vector, and a quaternion describes a general rotation. This can be given as a Vector to apply to each scattered mesh individually." rotations = 0.0 - space = :data - fxaa = true cycle = [:color] - @mixin mixin_generic_plot_attributes - @mixin mixin_shading_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_shading_attributes()... + mixin_colormap_attributes()... end """ @@ -438,11 +435,11 @@ Plots one or multiple texts passed via the `text` keyword. "Specifies one piece of text or a vector of texts to show, where the number has to match the number of positions given. Makie supports `String` which is used for all normal text and `LaTeXString` which layouts mathematical expressions using `MathTeXEngine.jl`." text = "" "Sets the color of the text. One can set one color per glyph by passing a `Vector{<:Colorant}`, or one colorant for the whole text. If color is a vector of numbers, the colormap args are used to map the numbers to colors." - color = @inherit :textcolor :black + color = @inherit textcolor "Sets the font. Can be a `Symbol` which will be looked up in the `fonts` dictionary or a `String` specifying the (partial) name of a font or the file path of a font file" - font = @inherit :font :regular + font = @inherit font "Used as a dictionary to look up fonts specified by `Symbol`, for example `:regular`, `:bold` or `:italic`." - fonts = @inherit :fonts Attributes() + fonts = @inherit fonts "Sets the color of the outline around a marker." strokecolor = (:black, 0.0) "Sets the width of the outline around a marker." @@ -452,7 +449,7 @@ Plots one or multiple texts passed via the `text` keyword. "Rotates text around the given position" rotation = 0.0 "The fontsize in units depending on `markerspace`." - fontsize = @inherit :fontsize 16 + fontsize = @inherit fontsize "Deprecated: Specifies the position of the text. Use the positional argument to `text` instead." position = (0.0, 0.0) "Sets the alignment of text w.r.t its bounding box. Can be `:left, :center, :right` or a fraction. Will default to the horizontal alignment in `align`." @@ -467,8 +464,8 @@ Plots one or multiple texts passed via the `text` keyword. offset = (0.0, 0.0) "Specifies a linewidth limit for text. If a word overflows this limit, a newline is inserted before it. Negative numbers disable word wrapping." word_wrap_width = -1 - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... fxaa = false end @@ -502,23 +499,22 @@ Plots polygons, which are defined by Vector or Matrices of numbers can be used as well, which will use the colormap arguments to map the numbers to colors. One can also use `Makie.LinePattern`, to cover the poly with a regular stroke pattern. """ - color = @inherit :patchcolor :black + color = @inherit patchcolor "Sets the color of the outline around a marker." - strokecolor = @inherit :patchstrokecolor :transparent + strokecolor = @inherit patchstrokecolor "Sets the colormap that is sampled for numeric `color`s." - strokecolormap = @inherit :colormap :viridis + strokecolormap = @inherit colormap "Sets the width of the outline." - strokewidth = @inherit :patchstrokewidth 0 + strokewidth = @inherit patchstrokewidth "Sets the pattern of the line (e.g. `:solid`, `:dot`, `:dashdot`)" linestyle = nothing shading = NoShading - fxaa = true cycle = [:color => :patchcolor] - @mixin mixin_generic_plot_attributes - @mixin mixin_colormap_attributes + mixin_generic_plot_attributes()... + mixin_colormap_attributes()... end @recipe(Wireframe) do scene diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 79d402cb334..b91aeeb02e7 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -197,6 +197,140 @@ function attribute_names end attribute_names(_) = nothing +Base.@kwdef struct AttributeMetadata + docstring::Union{Nothing,String} + default_expr::Any +end + +update_metadata(am1::AttributeMetadata, am2::AttributeMetadata) = AttributeMetadata( + am2.docstring === nothing ? am1.docstring : am2.docstring, + am2.default_expr # TODO: should it be possible to overwrite only a docstring by not giving a default expr? +) + +struct DocumentedAttributes + d::Dict{Symbol,AttributeMetadata} + closure::Function +end + +macro DocumentedAttributes(expr::Expr) + if !(expr isa Expr && expr.head === :block) + throw(ArgumentError("Argument is not a begin end block")) + end + + metadata_exprs = [] + closure_exprs = [] + mixin_exprs = Expr[] + + for arg in expr.args + arg isa LineNumberNode && continue + + has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef + + if has_docs + docs = arg.args[3] + attr = arg.args[4] + else + docs = nothing + attr = arg + end + + is_attr_line = attr isa Expr && attr.head === :(=) && length(attr.args) == 2 + is_mixin_line = attr isa Expr && attr.head === :(...) && length(attr.args) == 1 + if !(is_attr_line || is_mixin_line) + error("$attr is neither a valid attribute line like `x = default_value` nor a mixin line like `some_mixin...`") + end + + if is_attr_line + sym = attr.args[1] + default = attr.args[2] + if !(sym isa Symbol) + error("$sym should be a symbol") + end + + push!(metadata_exprs, quote + am = AttributeMetadata(; docstring = $docs, default_expr = $(QuoteNode(default))) + if haskey(d, $(QuoteNode(sym))) + d[$(QuoteNode(sym))] = update_metadata(d[$(QuoteNode(sym))], am) + else + d[$(QuoteNode(sym))] = am + end + end) + + if default isa Expr && default.head === :macrocall && default.args[1] === Symbol("@inherit") + if length(default.args) ∉ (3, 4) + error("@inherit works with 1 or 2 arguments, expression was $d") + end + if !(default.args[3] isa Symbol) + error("Argument 1 of @inherit must be a Symbol, got $(default.args[3])") + end + key = default.args[3] + _default = get(default.args, 4, :(error("Inherited key $($(QuoteNode(key))) not found in theme with no fallback given."))) + # first check scene theme + # then default value + d = :( + dict[$(QuoteNode(sym))] = if haskey(thm, $(QuoteNode(key))) + to_value(thm[$(QuoteNode(key))]) # only use value of theme entry + else + $_default + end + ) + push!(closure_exprs, d) + else + push!(closure_exprs, :( + dict[$(QuoteNode(sym))] = $(esc(default)) + )) + end + elseif is_mixin_line + # this intermediate variable is needed to evaluate each mixin only once + # and is inserted at the start of the final code block + gsym = gensym("mixin") + mixin = only(attr.args) + push!(mixin_exprs, quote + $gsym = $(esc(mixin)) + if !($gsym isa DocumentedAttributes) + error("Mixin was not a DocumentedAttributes but $($gsym)") + end + end) + + # the actual runtime values of the mixed in defaults + # are computed using the closure stored in the DocumentedAttributes + closure_exp = quote + # `scene` and `dict` here are defined below where this exp is interpolated into + merge!(dict, $gsym.closure(scene)) + end + push!(closure_exprs, closure_exp) + + # docstrings and default expressions of the mixed in + # DocumentedAttributes are inserted + metadata_exp = quote + for (key, value) in $gsym.d + if haskey(d, key) + error("Mixin `$($(QuoteNode(mixin)))` had the key :$key which already existed. It's not allowed for mixins to overwrite keys to avoid accidental overwrites. Drop those keys from the mixin first.") + end + d[key] = value + end + end + push!(metadata_exprs, metadata_exp) + else + error("Unreachable") + end + end + + quote + $(mixin_exprs...) + d = Dict{Symbol,AttributeMetadata}() + $(metadata_exprs...) + closure = function (scene) + thm = theme(scene) + dict = Dict{Symbol,Any}() + $(closure_exprs...) + return dict + end + DocumentedAttributes(d, closure) + end +end + + macro recipe(Tsym::Symbol, args...) funcname_sym = to_func_name(Tsym) @@ -212,11 +346,13 @@ macro recipe(Tsym::Symbol, args...) if !(attrblock isa Expr && attrblock.head === :block) throw(ArgumentError("Last argument is not a begin end block")) end - attrblock = expand_mixins(attrblock) - attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] + # attrblock = expand_mixins(attrblock) + # attrs = [extract_attribute_metadata(arg) for arg in attrblock.args if !(arg isa LineNumberNode)] docs_placeholder = gensym() + attr_placeholder = gensym() + q = quote # This part is as far as I know the only way to modify the docstring on top of the # recipe, so that we can offer the convenience of automatic augmented docstrings @@ -236,6 +372,7 @@ macro recipe(Tsym::Symbol, args...) "No docstring defined.\n" end + const MakieCore.$(attr_placeholder) = @DocumentedAttributes $attrblock $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} @@ -251,32 +388,21 @@ macro recipe(Tsym::Symbol, args...) function MakieCore.is_attribute(T::Type{<:$(PlotType)}, sym::Symbol) sym in MakieCore.attribute_names(T) end + function MakieCore.attribute_names(::Type{<:$(PlotType)}) - ($([QuoteNode(a.symbol) for a in attrs]...),) + keys(MakieCore.$(attr_placeholder).d) end function $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) - $(make_default_theme_expr(attrs, :scene)) + MakieCore.$(attr_placeholder).closure(scene) end function MakieCore.attribute_default_expressions(::Type{<:$PlotType}) - $( - if attrs === nothing - Dict{Symbol, String}() - else - Dict{Symbol, String}([a.symbol => _defaultstring(a.default) for a in attrs]) - end - ) + Dict(k => v.default_expr for (k, v) in MakieCore.$(attr_placeholder).d) end function MakieCore._attribute_docs(::Type{<:$PlotType}) - Dict( - $( - (attrs !== nothing ? - [Expr(:call, :(=>), QuoteNode(a.symbol), a.docs) for a in attrs] : - [])... - ) - ) + Dict(k => v.docstring for (k, v) in MakieCore.$(attr_placeholder).d) end docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(funcname_sym)), user_docstring) From d614fd80487b5e2b94ef9292ec40c712058d3c34 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 20:19:28 +0100 Subject: [PATCH 046/106] add function to access `DocumentedAttributes` of a recipe --- MakieCore/src/recipes.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index b91aeeb02e7..35fb6f6d99e 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -194,6 +194,7 @@ function default_attribute_values end function attribute_default_expressions end function _attribute_docs end function attribute_names end +function documented_attributes end # this can be used for inheriting from other recipes attribute_names(_) = nothing @@ -374,6 +375,8 @@ macro recipe(Tsym::Symbol, args...) const MakieCore.$(attr_placeholder) = @DocumentedAttributes $attrblock + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = MakieCore.$(attr_placeholder) + $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) From 8eb463b105e38980f4d6809638aa2e7bfafec870 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 21:40:29 +0100 Subject: [PATCH 047/106] fix module mutation problem for now --- MakieCore/src/recipes.jl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 35fb6f6d99e..30ff586ee7e 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -373,9 +373,7 @@ macro recipe(Tsym::Symbol, args...) "No docstring defined.\n" end - const MakieCore.$(attr_placeholder) = @DocumentedAttributes $attrblock - - $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = MakieCore.$(attr_placeholder) + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = @DocumentedAttributes $attrblock # TODO: make this constant, store somewhere global $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} @@ -392,20 +390,20 @@ macro recipe(Tsym::Symbol, args...) sym in MakieCore.attribute_names(T) end - function MakieCore.attribute_names(::Type{<:$(PlotType)}) - keys(MakieCore.$(attr_placeholder).d) + function MakieCore.attribute_names(T::Type{<:$(PlotType)}) + keys(documented_attributes(T).d) end - function $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) - MakieCore.$(attr_placeholder).closure(scene) + function $(MakieCore).default_theme(scene, T::Type{<:$PlotType}) + documented_attributes(T).closure(scene) end - function MakieCore.attribute_default_expressions(::Type{<:$PlotType}) - Dict(k => v.default_expr for (k, v) in MakieCore.$(attr_placeholder).d) + function MakieCore.attribute_default_expressions(T::Type{<:$PlotType}) + Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) end - function MakieCore._attribute_docs(::Type{<:$PlotType}) - Dict(k => v.docstring for (k, v) in MakieCore.$(attr_placeholder).d) + function MakieCore._attribute_docs(T::Type{<:$PlotType}) + Dict(k => v.docstring for (k, v) in documented_attributes(T).d) end docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(funcname_sym)), user_docstring) From 11bdfa53ff64cbc7e5e06a3749a5ee9b2d421cca Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 21:46:02 +0100 Subject: [PATCH 048/106] move definition behind PlotType --- MakieCore/src/recipes.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 30ff586ee7e..936df5907f7 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -373,10 +373,12 @@ macro recipe(Tsym::Symbol, args...) "No docstring defined.\n" end - $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = @DocumentedAttributes $attrblock # TODO: make this constant, store somewhere global $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} + + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = @DocumentedAttributes $attrblock # TODO: make this constant, store somewhere global + $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) function ($funcname)(args...; kw...) kwdict = Dict{Symbol, Any}(kw) From 4bac2f7c9b7f82eaca9033070c0c749600cf1a42 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 21:51:11 +0100 Subject: [PATCH 049/106] return Attributes instead of Dict --- MakieCore/src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 936df5907f7..aa33bdba160 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -376,7 +376,7 @@ macro recipe(Tsym::Symbol, args...) $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} - + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = @DocumentedAttributes $attrblock # TODO: make this constant, store somewhere global $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) @@ -397,7 +397,7 @@ macro recipe(Tsym::Symbol, args...) end function $(MakieCore).default_theme(scene, T::Type{<:$PlotType}) - documented_attributes(T).closure(scene) + Attributes(documented_attributes(T).closure(scene)) end function MakieCore.attribute_default_expressions(T::Type{<:$PlotType}) From 9add0da5a2386c5aeb09e22e1d1e9fda3dc84fa5 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 1 Mar 2024 22:10:04 +0100 Subject: [PATCH 050/106] convert wireframe recipe --- MakieCore/src/basic_plots.jl | 15 ++++++++++----- src/basic_recipes/wireframe.jl | 17 ----------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 7b182499c59..18d2d2e7c69 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -517,11 +517,16 @@ Plots polygons, which are defined by mixin_colormap_attributes()... end -@recipe(Wireframe) do scene - attr = Attributes(; - depth_shift = -1f-5, - ) - return merge!(attr, default_theme(scene, LineSegments)) +""" + wireframe(x, y, z) + wireframe(positions) + wireframe(mesh) + +Draws a wireframe, either interpreted as a surface or as a mesh. +""" +@recipe Wireframe begin + documented_attributes(LineSegments)... + depth_shift = -1f-5 end @recipe(Arrows, points, directions) do scene diff --git a/src/basic_recipes/wireframe.jl b/src/basic_recipes/wireframe.jl index bbf6d271e0d..d22fa051121 100644 --- a/src/basic_recipes/wireframe.jl +++ b/src/basic_recipes/wireframe.jl @@ -1,20 +1,3 @@ -""" - wireframe(x, y, z) - wireframe(positions) - wireframe(mesh) - -Draws a wireframe, either interpreted as a surface or as a mesh. - -## Attributes -$(ATTRIBUTES) -""" -wireframe - -""" -See [`wireframe`](@ref). -""" -wireframe! - function convert_arguments(::Type{<: Wireframe}, x::AbstractVector, y::AbstractVector, z::AbstractMatrix) (ngrid(x, y)..., z) end From 5592d7bcff0b4302c82114918665c70b71ef9173 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 08:18:44 +0100 Subject: [PATCH 051/106] close over reference --- MakieCore/src/recipes.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index aa33bdba160..3b125ecb727 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -354,6 +354,8 @@ macro recipe(Tsym::Symbol, args...) attr_placeholder = gensym() + + q = quote # This part is as far as I know the only way to modify the docstring on top of the # recipe, so that we can offer the convenience of automatic augmented docstrings @@ -377,7 +379,8 @@ macro recipe(Tsym::Symbol, args...) $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} - $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = @DocumentedAttributes $attrblock # TODO: make this constant, store somewhere global + const $attr_placeholder = @DocumentedAttributes $attrblock + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = $attr_placeholder $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) function ($funcname)(args...; kw...) From c5f73a937a958bee0d688c6636b664abc8147ff5 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 08:42:51 +0100 Subject: [PATCH 052/106] don't include prereleases in benchmark, failed with 1.11 alpha --- .github/workflows/compilation-benchmark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compilation-benchmark.yaml b/.github/workflows/compilation-benchmark.yaml index 091f76f5cbb..717f9037653 100644 --- a/.github/workflows/compilation-benchmark.yaml +++ b/.github/workflows/compilation-benchmark.yaml @@ -29,7 +29,7 @@ jobs: - uses: julia-actions/setup-julia@v1 with: version: '1' - include-all-prereleases: true + # include-all-prereleases: true arch: x64 - uses: julia-actions/cache@v1 - name: Benchmark From 6c09ea54e1924dd9d0dbdf95dcfba80a00f6c085 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 09:18:27 +0100 Subject: [PATCH 053/106] stringify default expr --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 3b125ecb727..c283f81b2e9 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -404,7 +404,7 @@ macro recipe(Tsym::Symbol, args...) end function MakieCore.attribute_default_expressions(T::Type{<:$PlotType}) - Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) + Dict(k => _defaultstring(v.default_expr) for (k, v) in documented_attributes(T).d) end function MakieCore._attribute_docs(T::Type{<:$PlotType}) From d71797027df9d1e1975d07fd159c11caf3ed9844 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:20:26 +0100 Subject: [PATCH 054/106] convert arrows --- MakieCore/src/basic_plots.jl | 76 +++++++++++++++++++++------------- docs/reference/plots/arrows.md | 32 -------------- src/basic_recipes/arrows.jl | 2 +- 3 files changed, 49 insertions(+), 61 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 18d2d2e7c69..a9a83911cf8 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -529,34 +529,54 @@ Draws a wireframe, either interpreted as a surface or as a mesh. depth_shift = -1f-5 end -@recipe(Arrows, points, directions) do scene - attr = Attributes( - color = :black, - - arrowsize = automatic, - arrowhead = automatic, - arrowtail = automatic, - - linecolor = automatic, - linestyle = nothing, - align = :origin, - - normalize = false, - lengthscale = 1f0, - - colorscale = identity, - - quality = 32, - markerspace = :pixel, - ) +@recipe Arrows points directions begin + color = :black + + """Scales the size of the arrow head. This defaults to + `0.3` in the 2D case and `Vec3f(0.2, 0.2, 0.3)` in the 3D case. For the latter + the first two components scale the radius (in x/y direction) and the last scales + the length of the cone. If the arrowsize is set to 1, the cone will have a + diameter and length of 1.""" + arrowsize = automatic + """Defines the marker (2D) or mesh (3D) that is used as + the arrow head. The default for is `'▲'` in 2D and a cone mesh in 3D. For the + latter the mesh should start at `Point3f(0)` and point in positive z-direction.""" + arrowhead = automatic + """Defines the mesh used to draw the arrow tail in 3D. + It should start at `Point3f(0)` and extend in negative z-direction. The default + is a cylinder. This has no effect on the 2D plot.""" + arrowtail = automatic + """Sets the color used for the arrow tail which is + represented by a line in 2D.""" + linecolor = automatic + """Sets the linestyle used in 2D. Does not apply to 3D plots.""" + linestyle = nothing + """Sets how arrows are positioned. By default arrows start at + the given positions and extend along the given directions. If this attribute is + set to `:head`, `:lineend`, `:tailend`, `:headstart` or `:center` the given + positions will be between the head and tail of each arrow instead.""" + align = :origin + """By default the lengths of the directions given to `arrows` + are used to scale the length of the arrow tails. If this attribute is set to + true the directions are normalized, skipping this scaling.""" + normalize = false + """Scales the length of the arrow tail.""" + lengthscale = 1f0 + + """Defines the number of angle subdivisions used when generating + the arrow head and tail meshes. Consider lowering this if you have performance + issues. Only applies to 3D plots.""" + quality = 32 + markerspace = :pixel - generic_plot_attributes!(attr) - shading_attributes!(attr) - colormap_attributes!(attr, theme(scene, :colormap)) + mixin_generic_plot_attributes()... + mixin_shading_attributes()... + mixin_colormap_attributes()... - attr[:fxaa] = automatic - attr[:linewidth] = automatic - # connect arrow + linecolor by default - get!(attr, :arrowcolor, attr[:linecolor]) - return attr + fxaa = automatic + """Scales the width/diameter of the arrow tail. + Defaults to `1` for 2D and `0.05` for the 3D case.""" + linewidth = automatic + """Sets the color of the arrow head.""" + arrowcolor = automatic end diff --git a/docs/reference/plots/arrows.md b/docs/reference/plots/arrows.md index 54cef0bb62b..c3a47e2b394 100644 --- a/docs/reference/plots/arrows.md +++ b/docs/reference/plots/arrows.md @@ -2,38 +2,6 @@ {{doc arrows}} -### Attributes - -- `arrowhead = automatic`: Defines the marker (2D) or mesh (3D) that is used as - the arrow head. The default for is `'▲'` in 2D and a cone mesh in 3D. For the - latter the mesh should start at `Point3f(0)` and point in positive z-direction. -- `arrowtail = automatic`: Defines the mesh used to draw the arrow tail in 3D. - It should start at `Point3f(0)` and extend in negative z-direction. The default - is a cylinder. This has no effect on the 2D plot. -- `quality = 32`: Defines the number of angle subdivisions used when generating - the arrow head and tail meshes. Consider lowering this if you have performance - issues. Only applies to 3D plots. -- `linecolor = :black`: Sets the color used for the arrow tail which is - represented by a line in 2D. -- `arrowcolor = linecolor`: Sets the color of the arrow head. -- `arrowsize = automatic`: Scales the size of the arrow head. This defaults to - `0.3` in the 2D case and `Vec3f(0.2, 0.2, 0.3)` in the 3D case. For the latter - the first two components scale the radius (in x/y direction) and the last scales - the length of the cone. If the arrowsize is set to 1, the cone will have a - diameter and length of 1. -- `linewidth = automatic`: Scales the width/diameter of the arrow tail. - Defaults to `1` for 2D and `0.05` for the 3D case. -- `lengthscale = 1f0`: Scales the length of the arrow tail. -- `linestyle = nothing`: Sets the linestyle used in 2D. Does not apply to 3D - plots. -- `normalize = false`: By default the lengths of the directions given to `arrows` - are used to scale the length of the arrow tails. If this attribute is set to - true the directions are normalized, skipping this scaling. -- `align = :origin`: Sets how arrows are positioned. By default arrows start at - the given positions and extend along the given directions. If this attribute is - set to `:head`, `:lineend`, `:tailend`, `:headstart` or `:center` the given - positions will be between the head and tail of each arrow instead. - ### Examples \begin{examplefigure}{} diff --git a/src/basic_recipes/arrows.jl b/src/basic_recipes/arrows.jl index c9a04553ea6..467f7528b06 100644 --- a/src/basic_recipes/arrows.jl +++ b/src/basic_recipes/arrows.jl @@ -122,8 +122,8 @@ function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N}}, V}}) wher fxaa, ssao, transparency, visible, inspectable ) - arrow_c = map((a, c)-> a === automatic ? c : a , arrowplot, arrowcolor, color) line_c = map((a, c)-> a === automatic ? c : a , arrowplot, linecolor, color) + arrow_c = map((a, c)-> a === automatic ? c : a , arrowplot, arrowcolor, line_c) fxaa_bool = lift(fxaa -> fxaa == automatic ? N == 3 : fxaa, arrowplot, fxaa) # automatic == fxaa for 3D marker_head = lift((ah, q) -> arrow_head(N, ah, q), arrowplot, arrowhead, quality) From a81786cb29be367f4d4cc5b116d319e1b3f2d85b Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:22:46 +0100 Subject: [PATCH 055/106] add docs --- MakieCore/src/basic_plots.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index a9a83911cf8..4de634c15b8 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -546,8 +546,9 @@ end It should start at `Point3f(0)` and extend in negative z-direction. The default is a cylinder. This has no effect on the 2D plot.""" arrowtail = automatic - """Sets the color used for the arrow tail which is - represented by a line in 2D.""" + """Sets the color used for the arrow tail which is represented by a line in 2D. + Will copy `color` if set to `automatic`. + """ linecolor = automatic """Sets the linestyle used in 2D. Does not apply to 3D plots.""" linestyle = nothing @@ -577,6 +578,6 @@ end """Scales the width/diameter of the arrow tail. Defaults to `1` for 2D and `0.05` for the 3D case.""" linewidth = automatic - """Sets the color of the arrow head.""" + """Sets the color of the arrow head. Will copy `linecolor` if set to `automatic`.""" arrowcolor = automatic end From c55c9938b9a31f88076afe404ebd7d85bf61df33 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:29:42 +0100 Subject: [PATCH 056/106] directly convert default exprs to strings --- MakieCore/src/recipes.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index c283f81b2e9..787bb1ac4b0 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -200,7 +200,7 @@ attribute_names(_) = nothing Base.@kwdef struct AttributeMetadata docstring::Union{Nothing,String} - default_expr::Any + default_expr::String # stringified expression, just needed for docs purposes end update_metadata(am1::AttributeMetadata, am2::AttributeMetadata) = AttributeMetadata( @@ -249,7 +249,7 @@ macro DocumentedAttributes(expr::Expr) end push!(metadata_exprs, quote - am = AttributeMetadata(; docstring = $docs, default_expr = $(QuoteNode(default))) + am = AttributeMetadata(; docstring = $docs, default_expr = $(_default_expr_string(default))) if haskey(d, $(QuoteNode(sym))) d[$(QuoteNode(sym))] = update_metadata(d[$(QuoteNode(sym))], am) else @@ -404,7 +404,7 @@ macro recipe(Tsym::Symbol, args...) end function MakieCore.attribute_default_expressions(T::Type{<:$PlotType}) - Dict(k => _defaultstring(v.default_expr) for (k, v) in documented_attributes(T).d) + Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) end function MakieCore._attribute_docs(T::Type{<:$PlotType}) @@ -466,8 +466,8 @@ function rmlines(x::Expr) end end -_defaultstring(x) = string(rmlines(x)) -_defaultstring(x::String) = repr(x) +_default_expr_string(x) = string(rmlines(x)) +_default_expr_string(x::String) = repr(x) function extract_attribute_metadata(arg) has_docs = arg isa Expr && arg.head === :macrocall && arg.args[1] isa GlobalRef From 65b56345ddfab8707c7c68d35c23b33337beabad Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:37:15 +0100 Subject: [PATCH 057/106] convert ablines --- src/basic_recipes/ablines.jl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/basic_recipes/ablines.jl b/src/basic_recipes/ablines.jl index 3c2268b241e..95d14445597 100644 --- a/src/basic_recipes/ablines.jl +++ b/src/basic_recipes/ablines.jl @@ -3,16 +3,11 @@ Creates a line defined by `f(x) = slope * x + intercept` crossing a whole `Scene` with 2D projection at its current limits. You can pass one or multiple intercepts or slopes. - -All style attributes are the same as for `LineSegments`. """ -@recipe(ABLines) do scene - Theme(; - xautolimits = false, - yautolimits = false, - default_theme(LineSegments, scene)..., - cycle = :color, - ) +@recipe ABLines begin + xautolimits = false + yautolimits = false + MakieCore.documented_attributes(LineSegments)... end function Makie.plot!(p::ABLines) From bf86c397f5beeb882c7413da735f7bf67f6fec7f Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:37:24 +0100 Subject: [PATCH 058/106] print wrong attribute in red --- MakieCore/src/recipes.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 787bb1ac4b0..1192d10804d 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -649,7 +649,12 @@ end function Base.showerror(io::IO, i::InvalidAttributeError) print(io, "InvalidAttributeError: ") n = length(i.attributes) - println(io, "Plot type $(i.plottype) does not recognize attribute$(n > 1 ? "s" : "") $(join(i.attributes, ", ", " and ")).") + print(io, "Plot type $(i.plottype) does not recognize attribute$(n > 1 ? "s" : "") ") + for (j, att) in enumerate(i.attributes) + j > 1 && print(io, j == length(i.attributes) ? " and " : ", ") + printstyled(io, att; color = :red, bold = true) + end + println(".") nameset = sort(string.(collect(attribute_names(i.plottype)))) println(io) println(io, "The available plot attributes for $(i.plottype) are:") From 99d886e5f99f92ad49a60f15306253bad4ca271e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:38:55 +0100 Subject: [PATCH 059/106] convert annotations --- src/basic_recipes/annotations.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/basic_recipes/annotations.jl b/src/basic_recipes/annotations.jl index 941614d2301..c792ad86501 100644 --- a/src/basic_recipes/annotations.jl +++ b/src/basic_recipes/annotations.jl @@ -2,12 +2,9 @@ annotations(strings::Vector{String}, positions::Vector{Point}) Plots an array of texts at each position in `positions`. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Annotations, text, position) do scene - default_theme(scene, Text) +@recipe Annotations text position begin + MakieCore.documented_attributes(Text)... end function convert_arguments(::Type{<: Annotations}, From 485a82d001179730066f1dce8b219a8ca46f76ee Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:41:12 +0100 Subject: [PATCH 060/106] convert arc --- src/basic_recipes/arc.jl | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/basic_recipes/arc.jl b/src/basic_recipes/arc.jl index b13042c402d..4445db15cf8 100644 --- a/src/basic_recipes/arc.jl +++ b/src/basic_recipes/arc.jl @@ -10,15 +10,11 @@ Examples: `arc(Point2f(0), 1, 0.0, π)` `arc(Point2f(1, 2), 0.3. π, -π)` - -## Attributes -$(ATTRIBUTES) """ -@recipe(Arc, origin, radius, start_angle, stop_angle) do scene - Attributes(; - default_theme(scene, Lines)..., - resolution = 361, - ) +@recipe Arc origin radius start_angle stop_angle begin + MakieCore.documented_attributes(Lines)... + "The number of line points approximating the arc." + resolution = 361 end function plot!(p::Arc) From 5595d49c2210de8dc2fe0e6aa627f06b14bef7d6 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:41:42 +0100 Subject: [PATCH 061/106] remove attributes in arrows docstring --- src/basic_recipes/arrows.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/basic_recipes/arrows.jl b/src/basic_recipes/arrows.jl index 467f7528b06..ed70e42e82f 100644 --- a/src/basic_recipes/arrows.jl +++ b/src/basic_recipes/arrows.jl @@ -22,9 +22,6 @@ grid. If a `Function` is provided in place of `u, v, [w]`, then it must accept a `Point` as input, and return an appropriately dimensioned `Point`, `Vec`, or other array-like output. - -## Attributes -$(ATTRIBUTES) """ arrows From c678ab6adb7746fb22b7dfc117cc54e4643a693e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 10:43:53 +0100 Subject: [PATCH 062/106] convert band --- src/basic_recipes/band.jl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/basic_recipes/band.jl b/src/basic_recipes/band.jl index 9a8de39b48d..6bdfd7ff5ec 100644 --- a/src/basic_recipes/band.jl +++ b/src/basic_recipes/band.jl @@ -4,17 +4,10 @@ Plots a band from `ylower` to `yupper` along `x`. The form `band(lower, upper)` plots a [ruled surface](https://en.wikipedia.org/wiki/Ruled_surface) between the points in `lower` and `upper`. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Band, lowerpoints, upperpoints) do scene - attr = Attributes(; - default_theme(scene, Mesh)..., - colorrange = automatic, - ) - attr[:shading][] = NoShading - attr +@recipe Band lowerpoints upperpoints begin + MakieCore.documented_attributes(Mesh)... + shading = NoShading end convert_arguments(::Type{<: Band}, x, ylower, yupper) = (Point2f.(x, ylower), Point2f.(x, yupper)) From 5643973410e4df892e2c00ed3522317fe527c45c Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 15:13:03 +0100 Subject: [PATCH 063/106] fix escaping issue --- MakieCore/src/recipes.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 1192d10804d..d2490715794 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -272,7 +272,7 @@ macro DocumentedAttributes(expr::Expr) dict[$(QuoteNode(sym))] = if haskey(thm, $(QuoteNode(key))) to_value(thm[$(QuoteNode(key))]) # only use value of theme entry else - $_default + $(esc(_default)) end ) push!(closure_exprs, d) @@ -354,8 +354,6 @@ macro recipe(Tsym::Symbol, args...) attr_placeholder = gensym() - - q = quote # This part is as far as I know the only way to modify the docstring on top of the # recipe, so that we can offer the convenience of automatic augmented docstrings @@ -379,7 +377,15 @@ macro recipe(Tsym::Symbol, args...) $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Plot{$funcname,$(esc(:ArgType))} - const $attr_placeholder = @DocumentedAttributes $attrblock + # This weird syntax is so that the output of the macrocall can be escaped because it + # contains user expressions, without escaping what's passed to the macro because that + # messes with its transformation logic. Because we escape the whole block with the macro, + # we don't reference it by symbol but splice in the macro itself into the AST + # with `var"@DocumentedAttributes"` + const $attr_placeholder = $( + esc(Expr(:macrocall, var"@DocumentedAttributes", LineNumberNode(@__LINE__), attrblock)) + ) + $(MakieCore).documented_attributes(::Type{<:$(PlotType)}) = $attr_placeholder $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) From eb3afeef3fe1490a4e04c2c0474088d607d07bc8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 15:37:39 +0100 Subject: [PATCH 064/106] convert barplot --- src/basic_recipes/barplot.jl | 91 ++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index 31fe1f95b85..437ce692f16 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -35,54 +35,53 @@ function bar_default_fillto(tf::Tuple, ys, offset, in_y_direction) end """ - barplot(x, y; kwargs...) + barplot(positions, heights; kwargs...) -Plots a barplot; `y` defines the height. `x` and `y` should be 1 dimensional. -Bar width is determined by the attribute `width`, shrunk by `gap` in the following way: -`width -> width * (1 - gap)`. - -## Attributes -$(ATTRIBUTES) +Plots a barplot. """ -@recipe(BarPlot, x, y) do scene - Attributes(; - fillto = automatic, - offset = 0.0, - color = theme(scene, :patchcolor), - alpha = 1.0, - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = automatic, - lowclip = automatic, - highclip = automatic, - nan_color = :transparent, - dodge = automatic, - n_dodge = automatic, - gap = 0.2, - dodge_gap = 0.03, - marker = Rect, - stack = automatic, - strokewidth = theme(scene, :patchstrokewidth), - strokecolor = theme(scene, :patchstrokecolor), - width = automatic, - direction = :y, - visible = theme(scene, :visible), - inspectable = theme(scene, :inspectable), - cycle = [:color => :patchcolor], - - bar_labels = nothing, - flip_labels_at = Inf, - label_rotation = 0π, - label_color = theme(scene, :textcolor), - color_over_background = automatic, - color_over_bar = automatic, - label_offset = 5, - label_font = theme(scene, :font), - label_size = theme(scene, :fontsize), - label_formatter = bar_label_formatter, - label_align = automatic, - transparency = false - ) +@recipe BarPlot x y begin + """Controls the baseline of the bars. This is zero in the default `automatic` case unless the barplot is in a log-scaled `Axis`. + With a log scale, the automatic default is half the minimum value because zero is an invalid value for a log scale. + """ + fillto = automatic + offset = 0.0 + color = @inherit patchcolor + MakieCore.mixin_generic_plot_attributes()... + MakieCore.mixin_colormap_attributes()... + dodge = automatic + n_dodge = automatic + """ + The final width of the bars is calculated as `w * (1 - gap)` where `w` is the width of each bar + as determined with the `width` attribute. + """ + gap = 0.2 + dodge_gap = 0.03 + stack = automatic + strokewidth = @inherit patchstrokewidth + strokecolor = @inherit patchstrokecolor + """ + The gapless width of the bars. If `automatic`, the width `w` is calculated as `minimum(diff(sort(unique(positions)))`. + The actual width of the bars is calculated as `w * (1 - gap)`. + """ + width = automatic + "Controls the direction of the bars, can be `:y` (vertical) or `:x` (horizontal)." + direction = :y + cycle = [:color => :patchcolor] + "Labels added at the end of each bar." + bar_labels = nothing + flip_labels_at = Inf + label_rotation = 0π + label_color = @inherit textcolor + color_over_background = automatic + color_over_bar = automatic + "The distance of the labels from the bar ends in screen units." + label_offset = 5 + "The font of the bar labels." + label_font = @inherit font + "The font size of the bar labels." + label_size = @inherit fontsize + label_formatter = bar_label_formatter + label_align = automatic end conversion_trait(::Type{<: BarPlot}) = PointBased() From af698d1af50fee93da73045df2ebfb73b21f1f07 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 17:47:50 +0100 Subject: [PATCH 065/106] convert bracket --- src/basic_recipes/bracket.jl | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/basic_recipes/bracket.jl b/src/basic_recipes/bracket.jl index 9a76143e342..20262386af1 100644 --- a/src/basic_recipes/bracket.jl +++ b/src/basic_recipes/bracket.jl @@ -7,28 +7,29 @@ Draws a bracket between each pair of points (x1, y1) and (x2, y2) with a text label at the midpoint. By default each label is rotated parallel to the line between the bracket points. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Bracket) do scene - Theme( - offset = 0, - width = 15, - text = "", - font = theme(scene, :font), - orientation = :up, - align = (:center, :center), - textoffset = automatic, - fontsize = theme(scene, :fontsize), - rotation = automatic, - color = theme(scene, :linecolor), - textcolor = theme(scene, :textcolor), - linewidth = theme(scene, :linewidth), - linestyle = :solid, - justification = automatic, - style = :curly, - ) +@recipe Bracket begin + "The offset of the bracket perpendicular to the line from start to end point in screen units. + The direction depends on the `orientation` attribute." + offset = 0 + """ + The width of the bracket (perpendicularly away from the line from start to end point) in screen units. + """ + width = 15 + text = "" + font = @inherit font + "Which way the bracket extends relative to the line from start to end point. Can be `:up` or `:down`." + orientation = :up + align = (:center, :center) + textoffset = automatic + fontsize = @inherit fontsize + rotation = automatic + color = @inherit linecolor + textcolor = @inherit textcolor + linewidth = @inherit linewidth + linestyle = :solid + justification = automatic + style = :curly end Makie.convert_arguments(::Type{<:Bracket}, point1::VecTypes, point2::VecTypes) = ([(Point2f(point1), Point2f(point2))],) From 1fb0f3966d845ff261681bd108a8296a9e32b28c Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 17:48:08 +0100 Subject: [PATCH 066/106] fix barplot usage in hist --- src/stats/hist.jl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/stats/hist.jl b/src/stats/hist.jl index 165f361bc07..d02b2325ba7 100644 --- a/src/stats/hist.jl +++ b/src/stats/hist.jl @@ -179,8 +179,17 @@ function Makie.plot!(plot::Hist) bar_labels = lift(plot, plot.bar_labels) do x x === :values ? :y : x end + + bar_attrs = copy(plot.attributes) + delete!(bar_attrs, :over_background_color) + delete!(bar_attrs, :bins) + delete!(bar_attrs, :scale_to) + delete!(bar_attrs, :weights) + delete!(bar_attrs, :normalization) + delete!(bar_attrs, :over_bar_color) + # plot the values, not the observables, to be in control of updating - bp = barplot!(plot, points[]; width = widths[], gap = 0, plot.attributes..., fillto=plot.fillto, offset=plot.offset, bar_labels=bar_labels, color=color) + bp = barplot!(plot, points[]; width = widths[], gap = 0, bar_attrs..., fillto=plot.fillto, offset=plot.offset, bar_labels=bar_labels, color=color) # update the barplot points without triggering, then trigger with `width` on(plot, widths) do w From 315e161398fcbc21c7d84a315d5dd05955c0976f Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 17:59:21 +0100 Subject: [PATCH 067/106] convert contourf --- src/basic_recipes/contourf.jl | 72 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/basic_recipes/contourf.jl b/src/basic_recipes/contourf.jl index 89ff2ae4da3..c55c65ea4e0 100644 --- a/src/basic_recipes/contourf.jl +++ b/src/basic_recipes/contourf.jl @@ -3,43 +3,43 @@ Plots a filled contour of the height information in `zs` at horizontal grid positions `xs` and vertical grid positions `ys`. - -The attribute `levels` can be either -- an `Int` that produces n equally wide levels or bands -- an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 levels or bands - -You can also set the `mode` attribute to `:relative`. -In this mode you specify edges by the fraction between minimum and maximum value of `zs`. -This can be used for example to draw bands for the upper 90% while excluding the lower 10% with `levels = 0.1:0.1:1.0, mode = :relative`. - -In :normal mode, if you want to show a band from `-Inf` to the low edge, -set `extendlow` to `:auto` for the same color as the first level, -or specify a different color (default `nothing` means no extended band) -If you want to show a band from the high edge to `Inf`, set `extendhigh` -to `:auto` for the same color as the last level, or specify a different color -(default `nothing` means no extended band). - -If `levels` is an `Int`, the contour plot will be rectangular as all `zs` will be covered. -This is why `Axis` defaults to tight limits for such contourf plots. -If you specify `levels` as an `AbstractVector{<:Real}`, however, note that the axis limits include the default margins because the contourf plot can have an irregular shape. -You can use `tightlimits!(ax)` to tighten the limits similar to the `Int` behavior. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Contourf) do scene - Theme( - levels = 10, - mode = :normal, - colormap = theme(scene, :colormap), - colorscale = identity, - extendlow = nothing, - extendhigh = nothing, - # TODO, Isoband doesn't seem to support nans? - nan_color = :transparent, - inspectable = theme(scene, :inspectable), - transparency = false - ) +@recipe Contourf begin + """ + Can be either + - an `Int` that produces n equally wide levels or bands + - an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 levels or bands + + If `levels` is an `Int`, the contour plot will be rectangular as all `zs` values will be covered edge to edge. + This is why `Axis` defaults to tight limits for such contourf plots. + If you specify `levels` as an `AbstractVector{<:Real}`, however, note that the axis limits include the default margins because the contourf plot can have an irregular shape. + You can use `tightlimits!(ax)` to tighten the limits similar to the `Int` behavior. + """ + levels = 10 + """ + Determines how the `levels` attribute is interpreted, either `:normal` or `:relative`. + In `:normal` mode, the levels correspond directly to the z values. + In `:relative` mode, you specify edges by the fraction between minimum and maximum value of `zs`. + This can be used for example to draw bands for the upper 90% while excluding the lower 10% with `levels = 0.1:0.1:1.0, mode = :relative`. + """ + mode = :normal + colormap = @inherit colormap + colorscale = identity + """ + In `:normal` mode, if you want to show a band from `-Inf` to the low edge, + set `extendlow` to `:auto` to give the extension the same color as the first level, + or specify a color directly (default `nothing` means no extended band). + """ + extendlow = nothing + """ + In `:normal` mode, if you want to show a band from the high edge to `Inf`, set `extendhigh` + to `:auto` to give the extension the same color as the last level, or specify a color directly + (default `nothing` means no extended band). + """ + extendhigh = nothing + # TODO, Isoband doesn't seem to support nans? + nan_color = :transparent + MakieCore.mixin_generic_plot_attributes()... end # these attributes are computed dynamically and needed for colorbar e.g. From f59799b503c8f87f54f0bc87466fcad75cb142d2 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 18:01:27 +0100 Subject: [PATCH 068/106] typo --- src/basic_recipes/contourf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic_recipes/contourf.jl b/src/basic_recipes/contourf.jl index c55c65ea4e0..e79cd5efa96 100644 --- a/src/basic_recipes/contourf.jl +++ b/src/basic_recipes/contourf.jl @@ -10,7 +10,7 @@ and vertical grid positions `ys`. - an `Int` that produces n equally wide levels or bands - an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 levels or bands - If `levels` is an `Int`, the contour plot will be rectangular as all `zs` values will be covered edge to edge. + If `levels` is an `Int`, the contourf plot will be rectangular as all `zs` values will be covered edge to edge. This is why `Axis` defaults to tight limits for such contourf plots. If you specify `levels` as an `AbstractVector{<:Real}`, however, note that the axis limits include the default margins because the contourf plot can have an irregular shape. You can use `tightlimits!(ax)` to tighten the limits similar to the `Int` behavior. From 0d93e33f3ea4b25f7d06be853406331fd70ecba0 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 18:46:07 +0100 Subject: [PATCH 069/106] convert contour --- src/basic_recipes/contours.jl | 71 +++++++++++++++++------------------ 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/src/basic_recipes/contours.jl b/src/basic_recipes/contours.jl index c38ff209a91..b1406f89b98 100644 --- a/src/basic_recipes/contours.jl +++ b/src/basic_recipes/contours.jl @@ -9,39 +9,39 @@ end Creates a contour plot of the plane spanning `x::Vector`, `y::Vector`, `z::Matrix`. If only `z::Matrix` is supplied, the indices of the elements in `z` will be used as the `x` and `y` locations when plotting the contour. - -The attribute levels can be either - - an Int that produces n equally wide levels or bands - - an AbstractVector{<:Real} that lists n consecutive edges from low to high, which result in n-1 levels or bands - -To add contour labels, use `labels = true`, and pass additional label attributes such as `labelcolor`, `labelsize`, `labelfont` or `labelformatter`. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Contour) do scene - attr = Attributes(; - color = nothing, - levels = 5, - linewidth = 1.0, - linestyle = nothing, - enable_depth = true, - transparency = false, - labels = false, - - labelfont = theme(scene, :font), - labelcolor = nothing, # matches color by default - labelformatter = contour_label_formatter, - labelsize = 10, # arbitrary - ) - - - MakieCore.colormap_attributes!(attr, theme(scene, :colormap)) - MakieCore.generic_plot_attributes!(attr) - - return attr +@recipe Contour begin + """ + The color of the contour lines. If `nothing`, the color is determined by the numerical values of the + contour levels in combination with `colormap` and `colorrange`. + """ + color = nothing + """ + Controls the number and location of the contour lines. Can be either + + - an `Int` that produces n equally wide levels or bands + - an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 levels or bands + """ + levels = 5 + linewidth = 1.0 + linestyle = nothing + enable_depth = true + """ + If `true`, adds text labels to the contour lines. + """ + labels = false + "The font of the contour labels." + labelfont = @inherit font + "Color of the contour labels, if `nothing` it matches `color` by default." + labelcolor = nothing # matches color by default + """ + Formats the numeric values of the contour levels to strings. + """ + labelformatter = contour_label_formatter + "Font size of the contour labels" + labelsize = 10 # arbitrary + MakieCore.mixin_colormap_attributes()... + MakieCore.mixin_generic_plot_attributes()... end """ @@ -49,12 +49,9 @@ end Creates a 3D contour plot of the plane spanning x::Vector, y::Vector, z::Matrix, with z-elevation for each level. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Contour3d) do scene - default_theme(scene, Contour) +@recipe Contour3d begin + MakieCore.documented_attributes(Contour)... end angle(p1::Union{Vec2f,Point2f}, p2::Union{Vec2f,Point2f})::Float32 = From 43f09151b68bd1db795226df1d93ef1e925874b1 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 2 Mar 2024 18:50:19 +0100 Subject: [PATCH 070/106] fix waterfall --- src/basic_recipes/waterfall.jl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/basic_recipes/waterfall.jl b/src/basic_recipes/waterfall.jl index 1aa0bf787cb..8f5b5fd01de 100644 --- a/src/basic_recipes/waterfall.jl +++ b/src/basic_recipes/waterfall.jl @@ -67,10 +67,20 @@ function Makie.plot!(p::Waterfall) ) end + bar_attrs = copy(p.attributes) + delete!(bar_attrs, :direction_color) + delete!(bar_attrs, :marker_pos) + delete!(bar_attrs, :final_color) + delete!(bar_attrs, :final_dodge_gap) + delete!(bar_attrs, :show_direction) + delete!(bar_attrs, :final_gap) + delete!(bar_attrs, :show_final) + delete!(bar_attrs, :marker_neg) + barplot!( p, lift(x -> x.xy, p, fromto); - p.attributes..., + bar_attrs..., fillto=lift(x -> x.fillto, p, fromto), stack=automatic, ) From 28ba53683a84e52352b1c469c6616fdb256d9ed8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:11:05 +0100 Subject: [PATCH 071/106] comment out arrows test --- ReferenceTests/src/tests/examples3d.jl | 42 +++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ReferenceTests/src/tests/examples3d.jl b/ReferenceTests/src/tests/examples3d.jl index 7ed6356728a..2b15d26068f 100644 --- a/ReferenceTests/src/tests/examples3d.jl +++ b/ReferenceTests/src/tests/examples3d.jl @@ -199,27 +199,27 @@ end f, ax, p = surface(x, y, z, color=Makie.logo(), transparency=true) end -@reference_test "Arrows on Sphere" begin - n = 20 - f = (x, y, z) -> x * exp(cos(y) * z) - ∇f = (x, y, z) -> Point3f(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) - Point3f(x, y, z) * dot(Point3f(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(Point3f.(x, y, z)) - ∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0 - surface(x, y, z) - arrows!( - pts, ∇ˢF, - arrowsize=0.03, linecolor=(:white, 0.6), linewidth=0.03 - ) - current_figure() -end +# @reference_test "Arrows on Sphere" begin +# n = 20 +# f = (x, y, z) -> x * exp(cos(y) * z) +# ∇f = (x, y, z) -> Point3f(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) - Point3f(x, y, z) * dot(Point3f(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(Point3f.(x, y, z)) +# ∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0 +# surface(x, y, z) +# arrows!( +# pts, ∇ˢF, +# arrowsize=0.03, linecolor=(:white, 0.6), linewidth=0.03 +# ) +# current_figure() +# end @reference_test "surface + contour3d" begin vx = -1:0.01:1 From a5061571fc5b4ca03f4b9c497afe9f82a6b22205 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:29:57 +0100 Subject: [PATCH 072/106] convert datashader --- src/basic_recipes/datashader.jl | 105 ++++++++++++++++---------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/src/basic_recipes/datashader.jl b/src/basic_recipes/datashader.jl index 775ab71e011..87179139c4b 100644 --- a/src/basic_recipes/datashader.jl +++ b/src/basic_recipes/datashader.jl @@ -273,7 +273,7 @@ end !!! warning This feature might change outside breaking releases, since the API is not yet finalized. - Please be vary of bugs in the implementation and open issues if you encounter odd behaviour. + Please be wary of bugs in the implementation and open issues if you encounter odd behaviour. Points can be any array type supporting iteration & getindex, including memory mapped arrays. If you have separate arrays for x and y coordinates and want to avoid conversion and copy, consider using: @@ -282,60 +282,61 @@ using Makie.StructArrays points = StructArray{Point2f}((x, y)) datashader(points) ``` -Do pay attention though, that if x and y don't have a fast iteration/getindex implemented, this might be slower then just copying it into a new array. +Do pay attention though, that if x and y don't have a fast iteration/getindex implemented, this might be slower than just copying the data into a new array. For best performance, use `method=Makie.AggThreads()` and make sure to start julia with `julia -tauto` or have the environment variable `JULIA_NUM_THREADS` set to the number of cores you have. - -## Attributes - -### Specific to `DataShader` - -- `agg = AggCount()` can be `AggCount()`, `AggAny()` or `AggMean()`. User extendable by overloading: - - - ```Julia - struct MyAgg{T} <: Makie.AggOp end - MyAgg() = MyAgg{Float64}() - Makie.Aggregation.null(::MyAgg{T}) where {T} = zero(T) - Makie.Aggregation.embed(::MyAgg{T}, x) where {T} = convert(T, x) - Makie.Aggregation.merge(::MyAgg{T}, x::T, y::T) where {T} = x + y - Makie.Aggregation.value(::MyAgg{T}, x::T) where {T} = x - ``` - -- `method = AggThreads()` can be `AggThreads()` or `AggSerial()`. -- `async::Bool = true` will calculate get_aggregation in a task, and skip any zoom/pan updates while busy. Great for interaction, but must be disabled for saving to e.g. png or when inlining in documenter. - -- `operation::Function = automatic` Defaults to `Makie.equalize_histogram` function which gets called on the whole get_aggregation array before display (`operation(final_aggregation_result)`). -- `local_operation::Function = identity` function which gets call on each element after the aggregation (`map!(x-> local_operation(x), final_aggregation_result)`). - -- `point_transform::Function = identity` function which gets applied to every point before aggregating it. -- `binsize::Number = 1` factor defining how many bins one wants per screen pixel. Set to n > 1 if you want a corser image. -- `show_timings::Bool = false` show how long it takes to aggregate each frame. -- `interpolate::Bool = true` If the resulting image should be displayed interpolated. - -$(Base.Docs.doc(MakieCore.colormap_attributes!)) - -$(Base.Docs.doc(MakieCore.generic_plot_attributes!)) """ -@recipe(DataShader, points) do scene - attr = Theme( - - agg = AggCount(), - method = AggThreads(), - async = true, - # Defaults to equalize_histogram - # just set to automatic, so that if one sets local_operation, one doesn't do equalize_histogram on top of things. - operation=automatic, - local_operation=identity, - - point_transform = identity, - binsize = 1, - show_timings = false, - - interpolate = true - ) - MakieCore.generic_plot_attributes!(attr) - return MakieCore.colormap_attributes!(attr, theme(scene, :colormap)) +@recipe DataShader points begin + """ + Can be `AggCount()`, `AggAny()` or `AggMean()`. User-extensible by overloading: + + ```julia + struct MyAgg{T} <: Makie.AggOp end + MyAgg() = MyAgg{Float64}() + Makie.Aggregation.null(::MyAgg{T}) where {T} = zero(T) + Makie.Aggregation.embed(::MyAgg{T}, x) where {T} = convert(T, x) + Makie.Aggregation.merge(::MyAgg{T}, x::T, y::T) where {T} = x + y + Makie.Aggregation.value(::MyAgg{T}, x::T) where {T} = x + ``` + """ + agg = AggCount() + """ + Can be `AggThreads()` or `AggSerial()` for threaded vs. serial aggregation. + """ + method = AggThreads() + """ + Will calculate `get_aggregation` in a task, and skip any zoom/pan updates while busy. Great for interaction, but must be disabled for saving to e.g. png or when inlining in Documenter. + """ + async = true + # Defaults to equalize_histogram + # just set to automatic, so that if one sets local_operation, one doesn't do equalize_histogram on top of things. + """ + Defaults to `Makie.equalize_histogram` function which gets called on the whole get_aggregation array before display (`operation(final_aggregation_result)`). + """ + operation=automatic + """ + Function which gets called on each element after the aggregation (`map!(x-> local_operation(x), final_aggregation_result)`). + """ + local_operation=identity + + """ + Function which gets applied to every point before aggregating it. + """ + point_transform = identity + """ + Factor defining how many bins one wants per screen pixel. Set to n > 1 if you want a coarser image. + """ + binsize = 1 + """ + Set to `true` to show how long it takes to aggregate each frame. + """ + show_timings = false + """ + If the resulting image should be displayed interpolated. + """ + interpolate = true + MakieCore.mixin_generic_plot_attributes()... + MakieCore.mixin_colormap_attributes()... end function fast_bb(points, f) From 6eaf4c54b40f81f1f34ae3d56cda741c763da91d Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:36:27 +0100 Subject: [PATCH 073/106] convert errorbar and rangebar --- src/basic_recipes/error_and_rangebars.jl | 58 ++++++++++-------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/src/basic_recipes/error_and_rangebars.jl b/src/basic_recipes/error_and_rangebars.jl index 95dc2ec39e1..f3ac3d46e54 100644 --- a/src/basic_recipes/error_and_rangebars.jl +++ b/src/basic_recipes/error_and_rangebars.jl @@ -13,24 +13,19 @@ Plots errorbars at xy positions, extending by errors in the given `direction`. If you want to plot intervals from low to high values instead of relative errors, use `rangebars`. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Errorbars) do scene - Theme( - whiskerwidth = 0, - color = theme(scene, :linecolor), - linewidth = theme(scene, :linewidth), - direction = :y, - visible = theme(scene, :visible), - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = automatic, - inspectable = theme(scene, :inspectable), - transparency = false, - cycle = [:color] - ) +@recipe Errorbars begin + "The width of the whiskers or line caps in screen units." + whiskerwidth = 0 + "The color of the lines. Can be an array to color each bar separately." + color = @inherit linecolor + "The thickness of the lines in screen units." + linewidth = @inherit linewidth + "The direction in which the bars are drawn. Can be `:x` or `:y`." + direction = :y + cycle = [:color] + MakieCore.mixin_colormap_attributes()... + MakieCore.mixin_generic_plot_attributes()... end @@ -43,24 +38,19 @@ Plots rangebars at `val` in one dimension, extending from `low` to `high` in the given the chosen `direction`. If you want to plot errors relative to a reference value, use `errorbars`. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Rangebars) do scene - Theme( - whiskerwidth = 0, - color = theme(scene, :linecolor), - linewidth = theme(scene, :linewidth), - direction = :y, - visible = theme(scene, :visible), - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = automatic, - inspectable = theme(scene, :inspectable), - transparency = false, - cycle = [:color] - ) +@recipe Rangebars begin + "The width of the whiskers or line caps in screen units." + whiskerwidth = 0 + "The color of the lines. Can be an array to color each bar separately." + color = @inherit linecolor + "The thickness of the lines in screen units." + linewidth = @inherit linewidth + "The direction in which the bars are drawn. Can be `:x` or `:y`." + direction = :y + cycle = [:color] + MakieCore.mixin_colormap_attributes()... + MakieCore.mixin_generic_plot_attributes()... end ### conversions for errorbars From e83a330d275159744518a6744cb8b5f97c7dafc7 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:50:03 +0100 Subject: [PATCH 074/106] convert hvlines --- src/basic_recipes/hvlines.jl | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/basic_recipes/hvlines.jl b/src/basic_recipes/hvlines.jl index a919629d6b6..2a460a6e94e 100644 --- a/src/basic_recipes/hvlines.jl +++ b/src/basic_recipes/hvlines.jl @@ -8,14 +8,13 @@ they are broadcast to calculate the final line segments. All style attributes are the same as for `LineSegments`. """ -@recipe(HLines) do scene - Theme(; - xautolimits = false, - xmin = 0, - xmax = 1, - default_theme(scene, LineSegments)..., - cycle = :color, - ) +@recipe HLines begin + "The start of the lines in relative axis units (0 to 1) along the x dimension." + xmin = 0 + "The end of the lines in relative axis units (0 to 1) along the x dimension." + xmax = 1 + MakieCore.documented_attributes(LineSegments)... + cycle = [:color] end """ @@ -28,14 +27,13 @@ they are broadcast to calculate the final line segments. All style attributes are the same as for `LineSegments`. """ -@recipe(VLines) do scene - Theme(; - yautolimits = false, - ymin = 0, - ymax = 1, - default_theme(scene, LineSegments)..., - cycle = :color, - ) +@recipe VLines begin + "The start of the lines in relative axis units (0 to 1) along the y dimension." + ymin = 0 + "The start of the lines in relative axis units (0 to 1) along the y dimension." + ymax = 1 + MakieCore.documented_attributes(LineSegments)... + cycle = [:color] end function projview_to_2d_limits(pv) From ea060694e0a1d88b7dcb24dcba883daca32d126c Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:52:36 +0100 Subject: [PATCH 075/106] convert hvspan --- src/basic_recipes/hvlines.jl | 4 ---- src/basic_recipes/hvspan.jl | 36 +++++++++++++++--------------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/basic_recipes/hvlines.jl b/src/basic_recipes/hvlines.jl index 2a460a6e94e..7e95eb4457d 100644 --- a/src/basic_recipes/hvlines.jl +++ b/src/basic_recipes/hvlines.jl @@ -5,8 +5,6 @@ Create horizontal lines across a `Scene` with 2D projection. The lines will be placed at `ys` in data coordinates and `xmin` to `xmax` in scene coordinates (0 to 1). All three of these can have single or multiple values because they are broadcast to calculate the final line segments. - -All style attributes are the same as for `LineSegments`. """ @recipe HLines begin "The start of the lines in relative axis units (0 to 1) along the x dimension." @@ -24,8 +22,6 @@ Create vertical lines across a `Scene` with 2D projection. The lines will be placed at `xs` in data coordinates and `ymin` to `ymax` in scene coordinates (0 to 1). All three of these can have single or multiple values because they are broadcast to calculate the final line segments. - -All style attributes are the same as for `LineSegments`. """ @recipe VLines begin "The start of the lines in relative axis units (0 to 1) along the y dimension." diff --git a/src/basic_recipes/hvspan.jl b/src/basic_recipes/hvspan.jl index cb082347705..51c391789fb 100644 --- a/src/basic_recipes/hvspan.jl +++ b/src/basic_recipes/hvspan.jl @@ -5,18 +5,15 @@ Create horizontal bands spanning across a `Scene` with 2D projection. The bands will be placed from `ys_low` to `ys_high` in data coordinates and `xmin` to `xmax` in scene coordinates (0 to 1). All four of these can have single or multiple values because they are broadcast to calculate the final spans. - -All style attributes are the same as for `Poly`. """ -@recipe(HSpan) do scene - Theme(; - xautolimits = false, - xmin = 0, - xmax = 1, - default_theme(Poly, scene)..., - cycle = [:color => :patchcolor], - ) - end +@recipe HSpan begin + "The start of the bands in relative axis units (0 to 1) along the x dimension." + xmin = 0 + "The end of the bands in relative axis units (0 to 1) along the x dimension." + xmax = 1 + MakieCore.documented_attributes(Poly)... + cycle = [:color => :patchcolor] +end """ vspan(xs_low, xs_high; ymin = 0.0, ymax = 1.0, attrs...) @@ -25,17 +22,14 @@ Create vertical bands spanning across a `Scene` with 2D projection. The bands will be placed from `xs_low` to `xs_high` in data coordinates and `ymin` to `ymax` in scene coordinates (0 to 1). All four of these can have single or multiple values because they are broadcast to calculate the final spans. - -All style attributes are the same as for `Poly`. """ -@recipe(VSpan) do scene - Theme(; - yautolimits = false, - ymin = 0, - ymax = 1, - default_theme(Poly, scene)..., - cycle = [:color => :patchcolor], - ) +@recipe VSpan begin + "The start of the bands in relative axis units (0 to 1) along the y dimension." + ymin = 0 + "The end of the bands in relative axis units (0 to 1) along the y dimension." + ymax = 1 + MakieCore.documented_attributes(Poly)... + cycle = [:color => :patchcolor] end function Makie.plot!(p::Union{HSpan, VSpan}) From c2c61e52da458c25a11860f40ce684ceffed8905 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 14:59:45 +0100 Subject: [PATCH 076/106] convert pie --- docs/reference/plots/pie.md | 21 --------------------- src/basic_recipes/pie.jl | 36 +++++++++++++++++------------------- 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/docs/reference/plots/pie.md b/docs/reference/plots/pie.md index 78cee3f26f0..bec0f1e6868 100644 --- a/docs/reference/plots/pie.md +++ b/docs/reference/plots/pie.md @@ -2,27 +2,6 @@ {{doc pie}} - - -## Attributes - -### Generic - -- `normalize = true` sets whether the data will be normalized to the range [0, 2π]. -- `color` sets the color of the pie segments. It can be given as a single named color or a vector of the same length as the input data -- `strokecolor = :black` sets the color of the outline around the segments. -- `strokewidth = 1` sets the width of the outline around the segments. -- `vertex_per_deg = 1` defines the number of vertices per degree that are used to create the pie plot with polys. Increase if smoother circles are needed. -- `radius = 1` sets the radius for the pie plot. -- `inner_radius = 0` sets the inner radius of the plot. Choose as a value between 0 and `radius` to create a donut chart. -- `offset = 0` rotates the pie plot counterclockwise as given in radians. -- `transparency = false` adjusts how the plot deals with transparency. In GLMakie `transparency = true` results in using Order Independent Transparency. -- `inspectable = true` sets whether this plot should be seen by `DataInspector`. - -### Other - -Set the axis properties `autolimitaspect = 1` or `aspect = DataAspect()` to ensure that the pie chart looks like a circle and not an ellipsoid. - ## Examples \begin{examplefigure}{} diff --git a/src/basic_recipes/pie.jl b/src/basic_recipes/pie.jl index e13033d39e9..43f0e1454c8 100644 --- a/src/basic_recipes/pie.jl +++ b/src/basic_recipes/pie.jl @@ -1,25 +1,23 @@ """ - pie(fractions; kwargs...) + pie(values; kwargs...) -Creates a pie chart with the given `fractions`. - -## Attributes -$(ATTRIBUTES) +Creates a pie chart from the given `values`. """ -@recipe(Pie, values) do scene - Theme( - normalize = true, - color = :gray, - strokecolor = :black, - strokewidth = 1, - vertex_per_deg = 1, - radius = 1, - inner_radius = 0, - offset = 0, - inspectable = theme(scene, :inspectable), - visible = true, - transparency = false - ) +@recipe Pie values begin + "If `true`, the sum of all values is normalized to 2π (a full circle)." + normalize = true + color = :gray + strokecolor = :black + strokewidth = 1 + "Controls how many polygon vertices are used for one degree of rotation." + vertex_per_deg = 1 + "The outer radius of the pie segments." + radius = 1 + "The inner radius of the pie segments. If this is larger than zero, the pie pieces become ring sections." + inner_radius = 0 + "The angular offset of the first pie segment from the (1, 0) vector in radians." + offset = 0 + MakieCore.mixin_generic_plot_attributes()... end function plot!(plot::Pie) From 8f876382700ea56eb7c0cd3ee2d7e50ec86dbd5b Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 15:26:22 +0100 Subject: [PATCH 077/106] convert rainclouds --- docs/reference/plots/rainclouds.md | 80 +++++++++------ src/basic_recipes/raincloud.jl | 155 ++++++++++++++++------------- 2 files changed, 138 insertions(+), 97 deletions(-) diff --git a/docs/reference/plots/rainclouds.md b/docs/reference/plots/rainclouds.md index 2a5f434bcee..2233f2a3030 100644 --- a/docs/reference/plots/rainclouds.md +++ b/docs/reference/plots/rainclouds.md @@ -67,7 +67,7 @@ category_labels, data_array = mockup_categories_and_data_array(3) colors = Makie.wong_colors() rainclouds(category_labels, data_array; - xlabel = "Categories of Distributions", ylabel = "Samples", title = "My Title", + axis = (; xlabel = "Categories of Distributions", ylabel = "Samples", title = "My Title"), plot_boxplots = false, cloud_width=0.5, clouds=hist, hist_bins=50, color = colors[indexin(category_labels, unique(category_labels))]) ``` @@ -77,8 +77,8 @@ rainclouds(category_labels, data_array; \begin{examplefigure}{} ```julia rainclouds(category_labels, data_array; - ylabel = "Categories of Distributions", - xlabel = "Samples", title = "My Title", + axis = (; ylabel = "Categories of Distributions", + xlabel = "Samples", title = "My Title"), orientation = :horizontal, plot_boxplots = true, cloud_width=0.5, clouds=hist, color = colors[indexin(category_labels, unique(category_labels))]) @@ -88,8 +88,11 @@ rainclouds(category_labels, data_array; \begin{examplefigure}{} ```julia rainclouds(category_labels, data_array; - xlabel = "Categories of Distributions", - ylabel = "Samples", title = "My Title", + axis = (; + xlabel = "Categories of Distributions", + ylabel = "Samples", + title = "My Title" + ), plot_boxplots = true, cloud_width=0.5, clouds=hist, color = colors[indexin(category_labels, unique(category_labels))]) ``` @@ -99,7 +102,11 @@ rainclouds(category_labels, data_array; \begin{examplefigure}{} ```julia rainclouds(category_labels, data_array; - xlabel = "Categories of Distributions", ylabel = "Samples", title = "My Title", + axis = (; + xlabel = "Categories of Distributions", + ylabel = "Samples", + title = "My Title" + ), plot_boxplots = true, cloud_width=0.5, side = :right, violin_limits = extrema, color = colors[indexin(category_labels, unique(category_labels))]) ``` @@ -108,7 +115,11 @@ rainclouds(category_labels, data_array; \begin{examplefigure}{} ```julia rainclouds(category_labels, data_array; - xlabel = "Categories of Distributions", ylabel = "Samples", title = "My Title", + axis = (; + xlabel = "Categories of Distributions", + ylabel = "Samples", + title = "My Title", + ), plot_boxplots = true, cloud_width=0.5, side = :right, color = colors[indexin(category_labels, unique(category_labels))]) ``` @@ -119,7 +130,11 @@ rainclouds(category_labels, data_array; more_category_labels, more_data_array = mockup_categories_and_data_array(6) rainclouds(more_category_labels, more_data_array; - xlabel = "Categories of Distributions", ylabel = "Samples", title = "My Title", + axis = (; + xlabel = "Categories of Distributions", + ylabel = "Samples", + title = "My Title", + ), plot_boxplots = true, cloud_width=0.5, color = colors[indexin(more_category_labels, unique(more_category_labels))]) ``` @@ -129,8 +144,11 @@ rainclouds(more_category_labels, more_data_array; ```julia category_labels, data_array = mockup_categories_and_data_array(6) rainclouds(category_labels, data_array; - xlabel = "Categories of Distributions", - ylabel = "Samples", title = "My Title", + axis = (; + xlabel = "Categories of Distributions", + ylabel = "Samples", + title = "My Title", + ), plot_boxplots = true, cloud_width=0.5, color = colors[indexin(category_labels, unique(category_labels))]) ``` @@ -146,26 +164,30 @@ fig = Figure(size = (800*2, 600*5)) colors = [Makie.wong_colors(); Makie.wong_colors()] category_labels, data_array = mockup_categories_and_data_array(3) -rainclouds!(Axis(fig[1, 1]), category_labels, data_array; - title = "Left Side, with Box Plot", +rainclouds!( + Axis(fig[1, 1], title = "Left Side, with Box Plot"), + category_labels, data_array; side = :left, plot_boxplots = true, color = colors[indexin(category_labels, unique(category_labels))]) -rainclouds!(Axis(fig[2, 1]), category_labels, data_array; - title = "Left Side, without Box Plot", +rainclouds!( + Axis(fig[2, 1], title = "Left Side, without Box Plot"), + category_labels, data_array; side = :left, plot_boxplots = false, color = colors[indexin(category_labels, unique(category_labels))]) -rainclouds!(Axis(fig[1, 2]), category_labels, data_array; - title = "Right Side, with Box Plot", +rainclouds!( + Axis(fig[1, 2], title = "Right Side, with Box Plot"), + category_labels, data_array; side = :right, plot_boxplots = true, color = colors[indexin(category_labels, unique(category_labels))]) -rainclouds!(Axis(fig[2, 2]), category_labels, data_array; - title = "Right Side, without Box Plot", +rainclouds!( + Axis(fig[2, 2], title = "Right Side, without Box Plot"), + category_labels, data_array; side = :right, plot_boxplots = false, color = colors[indexin(category_labels, unique(category_labels))]) @@ -175,25 +197,27 @@ rainclouds!(Axis(fig[2, 2]), category_labels, data_array; # with and without clouds category_labels, data_array = mockup_categories_and_data_array(12) -rainclouds!(Axis(fig[3, 1:2]), category_labels, data_array; - title = "More categories. Default spacing.", +rainclouds!( + Axis(fig[3, 1:2], title = "More categories. Default spacing."), + category_labels, data_array; plot_boxplots = true, - dist_between_categories = 1.0, + gap = 1.0, color = colors[indexin(category_labels, unique(category_labels))]) -rainclouds!(Axis(fig[4, 1:2]), category_labels, data_array; - title = "More categories. Adjust space. (smaller cloud widths and smaller category distances)", +rainclouds!( + Axis(fig[4, 1:2], title = "More categories. Adjust space. (smaller cloud widths and smaller category distances)"), + category_labels, data_array; plot_boxplots = true, cloud_width = 0.3, - dist_between_categories = 0.5, + gap = 0.5, color = colors[indexin(category_labels, unique(category_labels))]) - -rainclouds!(Axis(fig[5, 1:2]), category_labels, data_array; - title = "More categories. Adjust space. No clouds.", +rainclouds!( + Axis(fig[5, 1:2], title = "More categories. Adjust space. No clouds."), + category_labels, data_array; plot_boxplots = true, clouds = nothing, - dist_between_categories = 0.5, + gap = 0.5, color = colors[indexin(category_labels, unique(category_labels))]) supertitle = Label(fig[0, :], "Cloud Plot Testing (Scatter, Violin, Boxplot)", fontsize=30) diff --git a/src/basic_recipes/raincloud.jl b/src/basic_recipes/raincloud.jl index 93b47b07fbc..c99e54eed7d 100644 --- a/src/basic_recipes/raincloud.jl +++ b/src/basic_recipes/raincloud.jl @@ -28,83 +28,100 @@ between each. - `data_array`: Typically `Vector{Float64}` used for to represent the datapoints to plot. # Keywords -- `gap=0.2`: Distance between elements of x-axis. -- `side=:left`: Can take values of `:left`, `:right`, determines where the violin plot will - be, relative to the scatter points -- `dodge`: vector of `Integer`` (length of data) of grouping variable to create multiple - side-by-side boxes at the same x position -- `dodge_gap = 0.03`: spacing between dodged boxes -- `n_dodge`: the number of categories to dodge (defaults to maximum(dodge)) -- `color`: a single color, or a vector of colors, one for each point ## Violin/Histogram Plot Specific Keywords -- `clouds=violin`: [violin, hist, nothing] to show cloud plots either as violin or histogram - plot, or no cloud plot. -- `hist_bins=30`: if `clouds=hist`, this passes down the number of bins to the histogram - call. -- `cloud_width=1.0`: Determines size of violin plot. Corresponds to `width` keyword arg in -`violin`. -- `orientation=:vertical` orientation of raindclouds (`:vertical` or `:horizontal`) -- `violin_limits=(-Inf, Inf)`: specify values to trim the `violin`. Can be a `Tuple` or a - `Function` (e.g. `datalimits=extrema`) - -## Box Plot Specific Keywords -- `plot_boxplots=true`: Boolean to show boxplots to summarize distribution of data. -- `boxplot_width=0.1`: Width of the boxplot in category x-axis absolute terms. -- `center_boxplot=true`: Determines whether or not to have the boxplot be centered in the - category. -- `whiskerwidth=0.5`: The width of the Q1, Q3 whisker in the boxplot. Value as a portion of - the `boxplot_width`. -- `strokewidth=1.0`: Determines the stroke width for the outline of the boxplot. -- `show_median=true`: Determines whether or not to have a line should the median value in - the boxplot. -- `boxplot_nudge=0.075`: Determines the distance away the boxplot should be placed from the - center line when `center_boxplot` is `false`. This is the value used to recentering the - boxplot. -- `show_boxplot_outliers`: show outliers in the boxplot as points (usually confusing when -paired with the scatter plot so the default is to not show them) ## Scatter Plot Specific Keywords - `side_nudge`: Default value is 0.02 if `plot_boxplots` is true, otherwise `0.075` default. - `jitter_width=0.05`: Determines the width of the scatter-plot bar in category x-axis absolute terms. -- `markersize=2`: Size of marker used for the scatter plot. - -## Axis General Keywords -- `title` -- `xlabel` -- `ylabel` """ -@recipe(RainClouds, category_labels, data_array) do scene - return Attributes( - side = :left, - orientation = :vertical, - center_boxplot = true, - # Cloud plot - cloud_width = 0.75, - violin_limits = (-Inf, Inf), - # Box Plot Settings - boxplot_width = 0.1, - whiskerwidth = 0.5, - strokewidth = 1.0, - show_median = true, - boxplot_nudge = 0.075, - - gap = 0.2, - - markersize = 2.0, - dodge = automatic, - n_dodge = automatic, - dodge_gap = 0.01, - - plot_boxplots = true, - show_boxplot_outliers = false, - clouds = violin, - hist_bins = 30, - - color = theme(scene, :patchcolor), - cycle = [:color => :patchcolor], - ) +@recipe RainClouds category_labels data_array begin + """ + Can take values of `:left`, `:right`, determines where the violin plot will be, + relative to the scatter points + """ + side = :left + """ + Orientation of rainclouds (`:vertical` or `:horizontal`) + """ + orientation = :vertical + """ + Whether or not to center the boxplot on the category. + """ + center_boxplot = true + # Cloud plot + """ + Determines size of violin plot. Corresponds to `width` keyword arg in `violin`. + """ + cloud_width = 0.75 + """ + Specify values to trim the `violin`. Can be a `Tuple` or a + `Function` (e.g. `datalimits=extrema`) + """ + violin_limits = (-Inf, Inf) + # Box Plot Settings + """ + Width of the boxplot on the category axis. + """ + boxplot_width = 0.1 + "The width of the Q1, Q3 whisker in the boxplot. Value as a portion of the `boxplot_width`." + whiskerwidth = 0.5 + "Determines the stroke width for the outline of the boxplot." + strokewidth = 1.0 + """ + Determines whether or not to have a line for the median value in the boxplot. + """ + show_median = true + """ + Determines the distance away the boxplot should be placed from the + center line when `center_boxplot` is `false`. This is the value used to recentering the + boxplot. + """ + boxplot_nudge = 0.075 + + "Distance between elements on the main axis (depending on `orientation`)." + gap = 0.2 + + """ + Size of marker used for the scatter plot. + """ + markersize = 2.0 + + """ + Vector of `Integer` (length of data) of grouping variable to create multiple + side-by-side boxes at the same x position + """ + dodge = automatic + """ + The number of categories to dodge (defaults to `maximum(dodge)`) + """ + n_dodge = automatic + "Spacing between dodged boxes." + dodge_gap = 0.01 + + "Whether to show boxplots to summarize distribution of data." + plot_boxplots = true + """ + Show outliers in the boxplot as points (usually confusing when + paired with the scatter plot so the default is to not show them) + """ + show_boxplot_outliers = false + """ + [`violin`, `hist`, `nothing`] how to show cloud plots, either as violin or histogram + plots, or not at all. + """ + clouds = violin + """ + If `clouds=hist`, this passes down the number of bins to the histogram call. + """ + hist_bins = 30 + + """ + A single color, or a vector of colors, one for each point. + """ + color = @inherit patchcolor + cycle = [:color => :patchcolor] end # create_jitter_array(length_data_array; jitter_width = 0.1, clamped_portion = 0.1) From 0baa663610a30844d91c224bda72298087b8f4ee Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 16:56:58 +0100 Subject: [PATCH 078/106] convert scatterlines --- MakieCore/src/basic_plots.jl | 2 +- src/basic_recipes/scatterlines.jl | 44 +++++++++++++++---------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 4de634c15b8..1a08ff08037 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -291,7 +291,7 @@ Creates a connected line plot for each element in `(x, y, z)`, `(x, y)` or `posi @recipe Lines positions begin "The color of the line." color = @inherit linecolor - "Sets the width of the line in pixel units" + "Sets the width of the line in screen units" linewidth = @inherit linewidth "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" linestyle = nothing diff --git a/src/basic_recipes/scatterlines.jl b/src/basic_recipes/scatterlines.jl index cc2e02d4ec8..286c9ef5644 100644 --- a/src/basic_recipes/scatterlines.jl +++ b/src/basic_recipes/scatterlines.jl @@ -2,30 +2,28 @@ scatterlines(xs, ys, [zs]; kwargs...) Plots `scatter` markers and `lines` between them. - -## Attributes -$(ATTRIBUTES) """ -@recipe(ScatterLines) do scene - s_theme = default_theme(scene, Scatter) - l_theme = default_theme(scene, Lines) - Attributes( - color = l_theme.color, - colormap = l_theme.colormap, - colorscale = l_theme.colorscale, - colorrange = get(l_theme.attributes, :colorrange, automatic), - linestyle = l_theme.linestyle, - linewidth = l_theme.linewidth, - markercolor = automatic, - markercolormap = automatic, - markercolorrange = automatic, - markersize = s_theme.markersize, - strokecolor = s_theme.strokecolor, - strokewidth = s_theme.strokewidth, - marker = s_theme.marker, - inspectable = theme(scene, :inspectable), - cycle = [:color], - ) +@recipe ScatterLines begin + "The color of the line, and by default also of the scatter markers." + color = @inherit linecolor + "Sets the pattern of the line e.g. `:solid`, `:dot`, `:dashdot`. For custom patterns look at `Linestyle(Number[...])`" + linestyle = nothing + "Sets the width of the line in screen units" + linewidth = @inherit linewidth + markercolor = automatic + markercolormap = automatic + markercolorrange = automatic + "Sets the size of the marker." + markersize = @inherit markersize + "Sets the color of the outline around a marker." + strokecolor = @inherit markerstrokecolor + "Sets the width of the outline around a marker." + strokewidth = @inherit markerstrokewidth + "Sets the scatter marker." + marker = @inherit marker + MakieCore.mixin_generic_plot_attributes()... + MakieCore.mixin_colormap_attributes()... + cycle = [:color] end conversion_trait(::Type{<: ScatterLines}) = PointBased() From f733fcae7c9df9db4a18bbd5e2f2540f708a27c0 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:00:45 +0100 Subject: [PATCH 079/106] convert series --- src/basic_recipes/series.jl | 39 +++++++++++++------------------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/basic_recipes/series.jl b/src/basic_recipes/series.jl index a0375a0790a..58197f95b47 100644 --- a/src/basic_recipes/series.jl +++ b/src/basic_recipes/series.jl @@ -1,17 +1,7 @@ """ - series(curves; - linewidth=2, - color=:lighttest, - solid_color=nothing, - labels=nothing, - # scatter arguments, if any is set != nothing, a scatterplot is added - marker=nothing, - markersize=nothing, - markercolor=automatic, - strokecolor=nothing, - strokewidth=nothing) + series(curves) Curves can be: * `AbstractVector{<: AbstractVector{<: Point2}}`: the native representation of a series as a vector of lines @@ -19,21 +9,20 @@ Curves can be: * `AbstractVector, AbstractMatrix`: the same as the above, but the first argument sets the x values for all lines * `AbstractVector{<: Tuple{X<: AbstractVector, Y<: AbstractVector}}`: A vector of tuples, where each tuple contains a vector for the x and y coordinates +If any of `marker`, `markersize`, `markercolor`, `strokecolor` or `strokewidth` is set != nothing, a scatterplot is added. """ -@recipe(Series, curves) do scene - Attributes( - linewidth=2, - color=:lighttest, - solid_color=nothing, - labels=nothing, - linestyle=:solid, - marker=nothing, - markersize=nothing, - markercolor=automatic, - strokecolor=nothing, - strokewidth=nothing, - space = :data, - ) +@recipe Series curves begin + linewidth=2 + color=:lighttest + solid_color=nothing + labels=nothing + linestyle=:solid + marker=nothing + markersize=nothing + markercolor=automatic + strokecolor=nothing + strokewidth=nothing + space = :data end replace_missing(x) = ismissing(x) ? NaN : x From a9d5e51fe55e67b1ce2ca7b2e8fb480c6861f213 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:03:49 +0100 Subject: [PATCH 080/106] convert spy --- src/basic_recipes/spy.jl | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/basic_recipes/spy.jl b/src/basic_recipes/spy.jl index eda01af1237..feab9efc753 100644 --- a/src/basic_recipes/spy.jl +++ b/src/basic_recipes/spy.jl @@ -10,21 +10,14 @@ spy(x) # or if you want to specify the range of x and y: spy(0..1, 0..1, x) ``` -## Attributes -$(ATTRIBUTES) """ -@recipe(Spy, x, y, z) do scene - Attributes( - marker = automatic, - markersize = automatic, - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = automatic, - framecolor = :black, - framesize = 1, - inspectable = theme(scene, :inspectable), - visible = theme(scene, :visible) - ) +@recipe Spy x y z begin + marker = automatic + markersize = automatic + framecolor = :black + framesize = 1 + MakieCore.mixin_generic_plot_attributes()... + MakieCore.mixin_colormap_attributes()... end function convert_arguments(::Type{<: Spy}, x::SparseArrays.AbstractSparseArray) From cb70f02506ba7a401ea6ef052b50a43fc8bbe05a Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:06:04 +0100 Subject: [PATCH 081/106] convert stairs --- src/basic_recipes/stairs.jl | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/basic_recipes/stairs.jl b/src/basic_recipes/stairs.jl index 4d74024c9b1..543cb9e2fba 100644 --- a/src/basic_recipes/stairs.jl +++ b/src/basic_recipes/stairs.jl @@ -3,21 +3,17 @@ Plot a stair function. -The `step` parameter can take the following values: -- `:pre`: horizontal part of step extends to the left of each value in `xs`. -- `:post`: horizontal part of step extends to the right of each value in `xs`. -- `:center`: horizontal part of step extends halfway between the two adjacent values of `xs`. - -The conversion trait of stem is `PointBased`. - -## Attributes -$(ATTRIBUTES) +The conversion trait of `stairs` is `PointBased`. """ -@recipe(Stairs) do scene - a = Attributes( - step = :pre, # :center :post - ) - merge(a, default_theme(scene, Lines)) +@recipe Stairs begin + """ + The `step` parameter can take the following values: + - `:pre`: horizontal part of step extends to the left of each value in `xs`. + - `:post`: horizontal part of step extends to the right of each value in `xs`. + - `:center`: horizontal part of step extends halfway between the two adjacent values of `xs`. + """ + step = :pre + MakieCore.documented_attributes(Lines)... end conversion_trait(::Type{<:Stairs}) = PointBased() From 0d5c14c74fc91ab9eb888b2ef6237a2464aa0602 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:09:38 +0100 Subject: [PATCH 082/106] convert stem --- src/basic_recipes/stem.jl | 61 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/basic_recipes/stem.jl b/src/basic_recipes/stem.jl index 682478762e5..91ab22462ef 100644 --- a/src/basic_recipes/stem.jl +++ b/src/basic_recipes/stem.jl @@ -3,40 +3,35 @@ Plots markers at the given positions extending from `offset` along stem lines. -`offset` can be a number, in which case it sets y for 2D, and z for 3D stems. -It can be a Point2 for 2D plots, as well as a Point3 for 3D plots. -It can also be an iterable of any of these at the same length as xs, ys, zs. - -The conversion trait of stem is `PointBased`. - -## Attributes -$(ATTRIBUTES) +The conversion trait of `stem` is `PointBased`. """ -@recipe(Stem) do scene - Attributes( - stemcolor = theme(scene, :linecolor), - stemcolormap = theme(scene, :colormap), - stemcolorrange = automatic, - stemwidth = theme(scene, :linewidth), - stemlinestyle = nothing, - trunkwidth = theme(scene, :linewidth), - trunklinestyle = nothing, - trunkcolor = theme(scene, :linecolor), - trunkcolormap = theme(scene, :colormap), - trunkcolorrange = automatic, - offset = 0, - marker = :circle, - markersize = theme(scene, :markersize), - color = theme(scene, :markercolor), - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = automatic, - strokecolor = theme(scene, :markerstrokecolor), - strokewidth = theme(scene, :markerstrokewidth), - visible = true, - inspectable = theme(scene, :inspectable), - cycle = [[:stemcolor, :color, :trunkcolor] => :color], - ) +@recipe Stem begin + stemcolor = @inherit linecolor + stemcolormap = @inherit colormap + stemcolorrange = automatic + stemwidth = @inherit linewidth + stemlinestyle = nothing + trunkwidth = @inherit linewidth + trunklinestyle = nothing + trunkcolor = @inherit linecolor + trunkcolormap = @inherit colormap + trunkcolorrange = automatic + """ + Can be a number, in which case it sets `y` for 2D, and `z` for 3D stems. + It can be a `Point2` for 2D plots, as well as a `Point3` for 3D plots. + It can also be an iterable of any of these at the same length as `xs`, `ys`, `zs`. + """ + offset = 0 + marker = :circle + markersize = @inherit markersize + color = @inherit markercolor + colormap = @inherit colormap + colorscale = identity + colorrange = automatic + strokecolor = @inherit markerstrokecolor + strokewidth = @inherit markerstrokewidth + MakieCore.mixin_generic_plot_attributes()... + cycle = [[:stemcolor, :color, :trunkcolor] => :color] end From 48c66597063470539feaebc1f58d86eed49f05e6 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:13:13 +0100 Subject: [PATCH 083/106] convert streamplot --- src/basic_recipes/streamplot.jl | 45 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/basic_recipes/streamplot.jl b/src/basic_recipes/streamplot.jl index 6855c9858c5..20d4b287506 100644 --- a/src/basic_recipes/streamplot.jl +++ b/src/basic_recipes/streamplot.jl @@ -11,34 +11,29 @@ v(x::Point2{T}) where T = Point2f(x[2], 4*x[1]) streamplot(v, -2..2, -2..2) ``` -One can choose the color of the lines by passing a function `color_func(dx::Point)` to the `color` attribute. -By default this is set to `norm`, but can be set to any function or composition of functions. -The `dx` which is passed to `color_func` is the output of `f` at the point being colored. - -## Attributes -$(ATTRIBUTES) - ## Implementation See the function `Makie.streamplot_impl` for implementation details. """ -@recipe(StreamPlot, f, limits) do scene - attr = Attributes( - stepsize = 0.01, - gridsize = (32, 32, 32), - maxsteps = 500, - color = norm, - - arrow_size = automatic, - arrow_head = automatic, - density = 1.0, - quality = 16, - - linewidth = theme(scene, :linewidth), - linestyle = nothing, - ) - MakieCore.colormap_attributes!(attr, theme(scene, :colormap)) - MakieCore.generic_plot_attributes!(attr) - return attr +@recipe StreamPlot f limits begin + stepsize = 0.01 + gridsize = (32, 32, 32) + maxsteps = 500 + """ + One can choose the color of the lines by passing a function `color_func(dx::Point)` to the `color` attribute. + This can be set to any function or composition of functions. + The `dx` which is passed to `color_func` is the output of `f` at the point being colored. + """ + color = norm + + arrow_size = automatic + arrow_head = automatic + density = 1.0 + quality = 16 + + linewidth = @inherit linewidth + linestyle = nothing + MakieCore.mixin_colormap_attributes()... + MakieCore.mixin_generic_plot_attributes()... end function convert_arguments(::Type{<: StreamPlot}, f::Function, xrange, yrange) From 7b1c28daf2b27f86a608984525f268270c710c3e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:23:32 +0100 Subject: [PATCH 084/106] convert timeseries --- src/basic_recipes/timeseries.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/basic_recipes/timeseries.jl b/src/basic_recipes/timeseries.jl index 7e7fc9ca8ed..510f2d2abd1 100644 --- a/src/basic_recipes/timeseries.jl +++ b/src/basic_recipes/timeseries.jl @@ -2,6 +2,7 @@ timeseries(x::Observable{{Union{Number, Point2}}}) Plots a sampled signal. + Usage: ```julia signal = Observable(1.0) @@ -20,11 +21,9 @@ end ``` """ -@recipe(TimeSeries, signal) do scene - Attributes( - history = 100; - default_theme(scene, Lines)... - ) +@recipe TimeSeries signal begin + history = 100 + MakieCore.documented_attributes(Lines)... end signal2point(signal::Number, start) = Point2f(time() - start, signal) From 04b8053a7d9307d5ef0723cbd8ba532b533cebd8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:23:51 +0100 Subject: [PATCH 085/106] convert tooltip --- src/basic_recipes/tooltip.jl | 108 ++++++++++++++--------------------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/src/basic_recipes/tooltip.jl b/src/basic_recipes/tooltip.jl index b94b557a74b..683e6ecd023 100644 --- a/src/basic_recipes/tooltip.jl +++ b/src/basic_recipes/tooltip.jl @@ -2,73 +2,53 @@ tooltip(position, string) tooltip(x, y, string) -Creates a tooltip pointing at `position` displaying the given `string` - -## Attributes - -### Generic - -- `visible::Bool = true` sets whether the plot will be rendered or not. -- `overdraw::Bool = false` sets whether the plot will draw over other plots. This specifically means ignoring depth checks in GL backends. -- `transparency::Bool = false` adjusts how the plot deals with transparency. In GLMakie `transparency = true` results in using Order Independent Transparency. -- `inspectable::Bool = true` sets whether this plot should be seen by `DataInspector`. -- `depth_shift::Float32 = 0f0` adjusts the depth value of a plot after all other transformations, i.e. in clip space, where `0 <= depth <= 1`. This only applies to GLMakie and WGLMakie and can be used to adjust render order (like a tunable overdraw). -- `space::Symbol = :data` sets the transformation space for positions of markers. See `Makie.spaces()` for possible inputs. - -### Tooltip specific - -- `offset = 10` sets the offset between the given `position` and the tip of the triangle pointing at that position. -- `placement = :above` sets where the tooltipü should be placed relative to `position`. Can be `:above`, `:below`, `:left`, `:right`. -- `align = 0.5` sets the alignment of the tooltip relative `position`. With `align = 0.5` the tooltip is centered above/below/left/right the `position`. -- `backgroundcolor = :white` sets the background color of the tooltip. -- `triangle_size = 10` sets the size of the triangle pointing at `position`. -- `outline_color = :black` sets the color of the tooltip outline. -- `outline_linewidth = 2f0` sets the linewidth of the tooltip outline. -- `outline_linestyle = nothing` sets the linestyle of the tooltip outline. - -- `textpadding = (4, 4, 4, 4)` sets the padding around text in the tooltip. This is given as `(left, right, bottom top)` offsets. -- `textcolor = theme(scene, :textcolor)` sets the text color. -- `fontsize = 16` sets the text size. -- `font = theme(scene, :font)` sets the font. -- `strokewidth = 0`: Gives text an outline if set to a positive value. -- `strokecolor = :white` sets the text outline color. -- `justification = :left` sets whether text is aligned to the `:left`, `:center` or `:right` within its bounding box. +Creates a tooltip pointing at `position` displaying the given `string """ -@recipe(Tooltip, position) do scene - Attributes(; - # General - text = "", - offset = 10, - placement = :above, - align = 0.5, - xautolimits = false, - yautolimits = false, - zautolimits = false, - overdraw = false, - depth_shift = 0f0, - transparency = false, - visible = true, - inspectable = false, - space = :data, - - # Text - textpadding = (4, 4, 4, 4), # LRBT - textcolor = theme(scene, :textcolor), - fontsize = 16, - font = theme(scene, :font), - strokewidth = 0, - strokecolor = :white, - justification = :left, +@recipe Tooltip position begin + # General + text = "" + "Sets the offset between the given `position` and the tip of the triangle pointing at that position." + offset = 10 + "Sets where the tooltip should be placed relative to `position`. Can be `:above`, `:below`, `:left`, `:right`." + placement = :above + "Sets the alignment of the tooltip relative `position`. With `align = 0.5` the tooltip is centered above/below/left/right the `position`." + align = 0.5 + xautolimits = false + yautolimits = false + zautolimits = false - # Background - backgroundcolor = :white, - triangle_size = 10, + # Text + "Sets the padding around text in the tooltip. This is given as `(left, right, bottom, top)` offsets." + textpadding = (4, 4, 4, 4) # LRBT + "Sets the text color." + textcolor = @inherit textcolor + "Sets the text size in screen units." + fontsize = 16 + "Sets the font." + font = @inherit font + "Gives text an outline if set to a positive value." + strokewidth = 0 + "Sets the text outline color." + strokecolor = :white + "Sets whether text is aligned to the `:left`, `:center` or `:right` within its bounding box." + justification = :left + + # Background + "Sets the background color of the tooltip." + backgroundcolor = :white + "Sets the size of the triangle pointing at `position`." + triangle_size = 10 - # Outline - outline_color = :black, - outline_linewidth = 2f0, - outline_linestyle = nothing, - ) + # Outline + "Sets the color of the tooltip outline." + outline_color = :black + "Sets the linewidth of the tooltip outline." + outline_linewidth = 2f0 + "Sets the linestyle of the tooltip outline." + outline_linestyle = nothing + + MakieCore.mixin_generic_plot_attributes()... + inspectable = false end convert_arguments(::Type{<: Tooltip}, x::Real, y::Real, str::AbstractString) = (Point2f(x, y), str) From 4d5776632c4cb65961c3980955eab12e05cc9ca4 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 17:38:15 +0100 Subject: [PATCH 086/106] convert tricontourf --- src/basic_recipes/tricontourf.jl | 83 +++++++++++++++++--------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/src/basic_recipes/tricontourf.jl b/src/basic_recipes/tricontourf.jl index e711345735d..0a1be854f5e 100644 --- a/src/basic_recipes/tricontourf.jl +++ b/src/basic_recipes/tricontourf.jl @@ -7,47 +7,50 @@ struct DelaunayTriangulation end Plots a filled tricontour of the height information in `zs` at the horizontal positions `xs` and vertical positions `ys`. A `Triangulation` from DelaunayTriangulation.jl can also be provided instead of `xs` and `ys` for specifying the triangles, otherwise an unconstrained triangulation of `xs` and `ys` is computed. - -## Attributes - -### Specific to `Tricontourf` - -- `levels = 10` can be either an `Int` which results in n bands delimited by n+1 equally spaced levels, or it can be an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 bands. -- `mode = :normal` sets the way in which a vector of levels is interpreted, if it's set to `:relative`, each number is interpreted as a fraction between the minimum and maximum values of `zs`. For example, `levels = 0.1:0.1:1.0` would exclude the lower 10% of data. -- `extendlow = nothing`. This sets the color of an optional additional band from `minimum(zs)` to the lowest value in `levels`. If it's `:auto`, the lower end of the colormap is picked and the remaining colors are shifted accordingly. If it's any color representation, this color is used. If it's `nothing`, no band is added. -- `extendhigh = nothing`. This sets the color of an optional additional band from the highest value of `levels` to `maximum(zs)`. If it's `:auto`, the high end of the colormap is picked and the remaining colors are shifted accordingly. If it's any color representation, this color is used. If it's `nothing`, no band is added. -- `triangulation = DelaunayTriangulation()`. The mode with which the points in `xs` and `ys` are triangulated. Passing `DelaunayTriangulation()` performs a Delaunay triangulation. You can also pass a preexisting triangulation as an `AbstractMatrix{<:Int}` with size (3, n), where each column specifies the vertex indices of one triangle, or as a `Triangulation` from DelaunayTriangulation.jl. - -### Generic - -- `visible::Bool = true` sets whether the plot will be rendered or not. -- `overdraw::Bool = false` sets whether the plot will draw over other plots. This specifically means ignoring depth checks in GL backends. -- `transparency::Bool = false` adjusts how the plot deals with transparency. In GLMakie `transparency = true` results in using Order Independent Transparency. -- `fxaa::Bool = false` adjusts whether the plot is rendered with fxaa (anti-aliasing). -- `inspectable::Bool = true` sets whether this plot should be seen by `DataInspector`. -- `depth_shift::Float32 = 0f0` adjusts the depth value of a plot after all other transformations, i.e. in clip space, where `0 <= depth <= 1`. This only applies to GLMakie and WGLMakie and can be used to adjust render order (like a tunable overdraw). -- `model::Makie.Mat4f` sets a model matrix for the plot. This replaces adjustments made with `translate!`, `rotate!` and `scale!`. -- `color` sets the color of the plot. It can be given as a named color `Symbol` or a `Colors.Colorant`. Transparency can be included either directly as an alpha value in the `Colorant` or as an additional float in a tuple `(color, alpha)`. The color can also be set for each scattered marker by passing a `Vector` of colors or be used to index the `colormap` by passing a `Real` number or `Vector{<: Real}`. -- `colormap::Union{Symbol, Vector{<:Colorant}} = :viridis` sets the colormap from which the band colors are sampled. -- `colorscale::Function = identity` color transform function. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Tricontourf) do scene - Theme( - levels = 10, - mode = :normal, - colormap = theme(scene, :colormap), - colorscale = identity, - extendlow = nothing, - extendhigh = nothing, - nan_color = :transparent, - inspectable = theme(scene, :inspectable), - transparency = false, - triangulation = DelaunayTriangulation(), - edges = nothing, - ) +@recipe Tricontourf begin + "Can be either an `Int` which results in n bands delimited by n+1 equally spaced levels, or it can be an `AbstractVector{<:Real}` that lists n consecutive edges from low to high, which result in n-1 bands." + levels = 10 + """ + Sets the way in which a vector of levels is interpreted, + if it's set to `:relative`, each number is interpreted as a fraction + between the minimum and maximum values of `zs`. + For example, `levels = 0.1:0.1:1.0` would exclude the lower 10% of data. + """ + mode = :normal + "Sets the colormap from which the band colors are sampled." + colormap = @inherit colormap + "Color transform function" + colorscale = identity + """ + This sets the color of an optional additional band from + `minimum(zs)` to the lowest value in `levels`. + If it's `:auto`, the lower end of the colormap is picked + and the remaining colors are shifted accordingly. + If it's any color representation, this color is used. + If it's `nothing`, no band is added. + """ + extendlow = nothing + """ + This sets the color of an optional additional band from + the highest value of `levels` to `maximum(zs)`. + If it's `:auto`, the high end of the colormap is picked + and the remaining colors are shifted accordingly. + If it's any color representation, this color is used. + If it's `nothing`, no band is added. + """ + extendhigh = nothing + nan_color = :transparent + """ + The mode with which the points in `xs` and `ys` are triangulated. + Passing `DelaunayTriangulation()` performs a Delaunay triangulation. + You can also pass a preexisting triangulation as an `AbstractMatrix{<:Int}` + with size (3, n), where each column specifies the vertex indices of one triangle, + or as a `Triangulation` from DelaunayTriangulation.jl. + """ + triangulation = DelaunayTriangulation() + edges = nothing + MakieCore.mixin_generic_plot_attributes()... end function Makie.used_attributes(::Type{<:Tricontourf}, ::AbstractVector{<:Real}, ::AbstractVector{<:Real}, ::AbstractVector{<:Real}) From 36d3ec1d9a7024b408ac37857935cbbe18429968 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 18:01:46 +0100 Subject: [PATCH 087/106] add transformation to allowlist --- MakieCore/src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index d2490715794..6b446cd3bbf 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -676,7 +676,7 @@ function Base.showerror(io::IO, i::InvalidAttributeError) end function attribute_name_allowlist() - (:xautolimits, :yautolimits, :zautolimits, :label, :rasterize) + (:xautolimits, :yautolimits, :zautolimits, :label, :rasterize, :transformation) end function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) From 793b75df6e689672c75b4e80311aed8c0c0f2dae Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:26:23 +0100 Subject: [PATCH 088/106] convert triplot --- src/basic_recipes/triplot.jl | 121 ++++++++++++++++------------------- 1 file changed, 56 insertions(+), 65 deletions(-) diff --git a/src/basic_recipes/triplot.jl b/src/basic_recipes/triplot.jl index 917e3ff4265..c746f6e101a 100644 --- a/src/basic_recipes/triplot.jl +++ b/src/basic_recipes/triplot.jl @@ -4,72 +4,63 @@ triplot(triangles::Triangulation; kwargs...) Plots a triangulation based on the provided position or `Triangulation` from DelaunayTriangulation.jl. - -## Attributes - -- `show_points = false` determines whether to plot the individual points. Note that this will only plot points included in the triangulation. -- `show_convex_hull = false` determines whether to plot the convex hull. -- `show_ghost_edges = false` determines whether to plot the ghost edges. -- `show_constrained_edges = false` determines whether to plot the constrained edges. -- `recompute_centers = false` determines whether to recompute the representative points for the ghost edge orientation. Note that this will mutate `tri.representative_point_list` directly. - -- `markersize = 12` sets the size of the points. -- `marker = :circle` sets the shape of the points. -- `markercolor = :black` sets the color of the points. -- `strokecolor = :black` sets the color of triangle edges. -- `strokewidth = 1` sets the linewidth of triangle edges. -- `linestyle = :solid` sets the linestyle of triangle edges. -- `triangle_color = (:white, 0.0)` sets the color of the triangles. - -- `convex_hull_color = :red` sets the color of the convex hull. -- `convex_hull_linestyle = :dash` sets the linestyle of the convex hull. -- `convex_hull_linewidth = 1` sets the width of the convex hull. - -- `ghost_edge_color = :blue` sets the color of the ghost edges. -- `ghost_edge_linestyle = :solid` sets the linestyle of the ghost edges. -- `ghost_edge_linewidth = 1` sets the width of the ghost edges. -- `ghost_edge_extension_factor = 0.1` sets the extension factor for the rectangle that the exterior ghost edges are extended onto. -- `bounding_box::Union{Automatic, Rect2, Tuple} = automatic`: Sets the bounding box for truncating ghost edges which can be a `Rect2` (or `BBox`) or a tuple of the form `(xmin, xmax, ymin, ymax)`. By default, the rectangle will be given by `[a - eΔx, b + eΔx] × [c - eΔy, d + eΔy]` where `e` is the `ghost_edge_extension_factor`, `Δx = b - a` and `Δy = d - c` are the lengths of the sides of the rectangle, and `[a, b] × [c, d]` is the bounding box of the points in the triangulation. - -- `constrained_edge_color = :magenta` sets the color of the constrained edges. -- `constrained_edge_linestyle = :solid` sets the linestyle of the constrained edges. -- `constrained_edge_linewidth = 1` sets the width of the constrained edges. """ -@recipe(Triplot, triangles) do scene - sc = default_theme(scene, Scatter) - return Attributes(; - # Toggles - show_points=false, - show_convex_hull=false, - show_ghost_edges=false, - show_constrained_edges=false, - recompute_centers=false, - - # Mesh settings - markersize=theme(scene, :markersize), - marker=theme(scene, :marker), - markercolor=sc.color, - strokecolor=theme(scene, :patchstrokecolor), - strokewidth=1, - linestyle=:solid, - triangle_color=(:white, 0.0), - - # Convex hull settings - convex_hull_color=:red, - convex_hull_linestyle=:dash, - convex_hull_linewidth=theme(scene, :linewidth), - - # Ghost edge settings - ghost_edge_color=:blue, - ghost_edge_linestyle=theme(scene, :linestyle), - ghost_edge_linewidth=theme(scene, :linewidth), - ghost_edge_extension_factor=0.1, - bounding_box=automatic, - - # Constrained edge settings - constrained_edge_color=:magenta, - constrained_edge_linestyle=theme(scene, :linestyle), - constrained_edge_linewidth=theme(scene, :linewidth)) +@recipe Triplot triangles begin + # Toggles + "Determines whether to plot the individual points. Note that this will only plot points included in the triangulation." + show_points=false + "Determines whether to plot the convex hull." + show_convex_hull=false + "Determines whether to plot the ghost edges." + show_ghost_edges=false + "Determines whether to plot the constrained edges." + show_constrained_edges=false + "Determines whether to recompute the representative points for the ghost edge orientation. Note that this will mutate `tri.representative_point_list` directly." + recompute_centers=false + + # Mesh settings + "Sets the size of the points." + markersize= @inherit markersize + "Sets the shape of the points." + marker= @inherit marker + "Sets the color of the points." + markercolor= @inherit markercolor + "Sets the color of triangle edges." + strokecolor= @inherit patchstrokecolor + "Sets the linewidth of triangle edges." + strokewidth=1 + "Sets the linestyle of triangle edges." + linestyle=:solid + "Sets the color of the triangles." + triangle_color= :transparent + + # Convex hull settings + "Sets the color of the convex hull." + convex_hull_color=:red + "Sets the linestyle of the convex hull." + convex_hull_linestyle=:dash + "Sets the width of the convex hull." + convex_hull_linewidth= @inherit linewidth + + # Ghost edge settings + "Sets the color of the ghost edges." + ghost_edge_color=:blue + "Sets the linestyle of the ghost edges." + ghost_edge_linestyle= @inherit linestyle + "Sets the width of the ghost edges." + ghost_edge_linewidth= @inherit linewidth + "Sets the extension factor for the rectangle that the exterior ghost edges are extended onto." + ghost_edge_extension_factor=0.1 + "Sets the bounding box for truncating ghost edges which can be a `Rect2` (or `BBox`) or a tuple of the form `(xmin, xmax, ymin, ymax)`. By default, the rectangle will be given by `[a - eΔx, b + eΔx] × [c - eΔy, d + eΔy]` where `e` is the `ghost_edge_extension_factor`, `Δx = b - a` and `Δy = d - c` are the lengths of the sides of the rectangle, and `[a, b] × [c, d]` is the bounding box of the points in the triangulation." + bounding_box=automatic + + # Constrained edge settings + "Sets the color of the constrained edges." + constrained_edge_color=:magenta + "Sets the linestyle of the constrained edges." + constrained_edge_linestyle= @inherit linestyle + "Sets the width of the constrained edges." + constrained_edge_linewidth= @inherit linewidth end function get_all_triangulation_points!(points, tri) From ec62a5664a478376991ac3981503b267a212490d Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:28:29 +0100 Subject: [PATCH 089/106] convert volumeslices --- src/basic_recipes/volumeslices.jl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/basic_recipes/volumeslices.jl b/src/basic_recipes/volumeslices.jl index a43598099b5..4a8b19bf3a2 100644 --- a/src/basic_recipes/volumeslices.jl +++ b/src/basic_recipes/volumeslices.jl @@ -5,16 +5,11 @@ VolumeSlices volumeslices(x, y, z, v) Draws heatmap slices of the volume v - -## Attributes -$(ATTRIBUTES) """ -@recipe(VolumeSlices, x, y, z, volume) do scene - Attributes(; - default_theme(scene, Heatmap)..., - bbox_visible = true, - bbox_color = RGBAf(0.5, 0.5, 0.5, 0.5) - ) +@recipe VolumeSlices x y z volume begin + MakieCore.documented_attributes(Heatmap)... + bbox_visible = true + bbox_color = RGBAf(0.5, 0.5, 0.5, 0.5) end function plot!(plot::VolumeSlices) From 5a1294c74088122f9d6de8d255de496fd9d2ae0c Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:33:01 +0100 Subject: [PATCH 090/106] convert voronoiplot --- MakieCore/src/recipes.jl | 2 +- src/basic_recipes/voronoiplot.jl | 62 +++++++++++++------------------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 6b446cd3bbf..0df1fe9cd30 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -676,7 +676,7 @@ function Base.showerror(io::IO, i::InvalidAttributeError) end function attribute_name_allowlist() - (:xautolimits, :yautolimits, :zautolimits, :label, :rasterize, :transformation) + (:xautolimits, :yautolimits, :zautolimits, :label, :rasterize, :model, :transformation) end function validate_attribute_keys(P::Type{<:Plot}, kw::Dict{Symbol}) diff --git a/src/basic_recipes/voronoiplot.jl b/src/basic_recipes/voronoiplot.jl index 7ce3d6f87b2..2d6963a2f6b 100644 --- a/src/basic_recipes/voronoiplot.jl +++ b/src/basic_recipes/voronoiplot.jl @@ -8,44 +8,32 @@ Generates and plots a Voronoi tessalation from `heatmap`- or point-like data. The tessellation can also be passed directly as a `VoronoiTessellation` from DelaunayTriangulation.jl. - -## Attributes - -- `show_generators = true` determines whether to plot the individual generators. - -- `markersize = 12` sets the size of the points. -- `marker = :circle` sets the shape of the points. -- `markercolor = :black` sets the color of the points. - -- `strokecolor = :black` sets the strokecolor of the polygons. -- `strokewidth = 1` sets the width of the polygon stroke. -- `color = automatic` sets the color of the polygons. If `automatic`, the polygons will be individually colored according to the colormap. -- `unbounded_edge_extension_factor = 0.1` sets the extension factor for the unbounded edges, used in `DelaunayTriangulation.polygon_bounds`. -- `clip::Union{Automatic, Rect2, Circle, Tuple} = automatic` sets the clipping area for the generated polygons which can be a `Rect2` (or `BBox`), `Tuple` with entries `(xmin, xmax, ymin, ymax)` or as a `Circle`. Anything outside the specified area will be removed. If the `clip` is not set it is automatically determined using `unbounded_edge_extension_factor` as a `Rect`. - -$(Base.Docs.doc(MakieCore.colormap_attributes!)) """ -@recipe(Voronoiplot, vorn) do scene - th = default_theme(scene, Mesh) - sc = default_theme(scene, Scatter) - attr = Attributes(; - # Toggles - show_generators=true, - smooth=false, - - # Point settings - markersize=sc.markersize, - marker=sc.marker, - markercolor=sc.color, - - # Polygon settings - strokecolor=theme(scene, :patchstrokecolor), - strokewidth=1.0, - color=automatic, - unbounded_edge_extension_factor=0.1, - clip=automatic) - MakieCore.colormap_attributes!(attr, theme(scene, :colormap)) - return attr +@recipe Voronoiplot vorn begin + "Determines whether to plot the individual generators." + show_generators=true + smooth=false + + # Point settings + "Sets the size of the points." + markersize= @inherit markersize + "Sets the shape of the points." + marker= @inherit marker + "Sets the color of the points." + markercolor= @inherit markercolor + + # Polygon settings + "Sets the strokecolor of the polygons." + strokecolor= @inherit patchstrokecolor + "Sets the width of the polygon stroke." + strokewidth=1.0 + "Sets the color of the polygons. If `automatic`, the polygons will be individually colored according to the colormap." + color=automatic + "Sets the extension factor for the unbounded edges, used in `DelaunayTriangulation.polygon_bounds`." + unbounded_edge_extension_factor=0.1 + "Sets the clipping area for the generated polygons which can be a `Rect2` (or `BBox`), `Tuple` with entries `(xmin, xmax, ymin, ymax)` or as a `Circle`. Anything outside the specified area will be removed. If the `clip` is not set it is automatically determined using `unbounded_edge_extension_factor` as a `Rect`." + clip=automatic + MakieCore.mixin_colormap_attributes()... end function _clip_polygon(poly::Polygon, circle::Circle) From 05782e5d4cbf041097aebeacce5d38c6643cd97e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:37:13 +0100 Subject: [PATCH 091/106] convert waterfall --- src/basic_recipes/waterfall.jl | 40 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/basic_recipes/waterfall.jl b/src/basic_recipes/waterfall.jl index 8f5b5fd01de..562eb301ae4 100644 --- a/src/basic_recipes/waterfall.jl +++ b/src/basic_recipes/waterfall.jl @@ -4,30 +4,24 @@ Plots a [waterfall chart](https://en.wikipedia.org/wiki/Waterfall_chart) to visualize individual positive and negative components that add up to a net result as a barplot with stacked bars next to each other. - -## Attributes -$(ATTRIBUTES) - -Furthermore the same attributes as for `barplot` are supported. """ -@recipe(Waterfall, x, y) do scene - return Attributes(; - dodge=automatic, - n_dodge=automatic, - gap=0.2, - dodge_gap=0.03, - width=automatic, - cycle=[:color => :patchcolor], - stack=automatic, - show_direction=false, - marker_pos=:utriangle, - marker_neg=:dtriangle, - direction_color=theme(scene, :backgroundcolor), - show_final=false, - final_color=plot_color(:grey90, 0.5), - final_gap=automatic, - final_dodge_gap=0, - ) +@recipe Waterfall x y begin + color = @inherit patchcolor + dodge=automatic + n_dodge=automatic + gap=0.2 + dodge_gap=0.03 + width=automatic + cycle=[:color => :patchcolor] + stack=automatic + show_direction=false + marker_pos=:utriangle + marker_neg=:dtriangle + direction_color= @inherit backgroundcolor + show_final=false + final_color=plot_color(:grey90, 0.5) + final_gap=automatic + final_dodge_gap=0 end conversion_trait(::Type{<:Waterfall}) = PointBased() From a923b2a49bc36da86e1d996f24742b0598dc1835 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:43:00 +0100 Subject: [PATCH 092/106] convert boxplot --- src/stats/boxplot.jl | 102 +++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/src/stats/boxplot.jl b/src/stats/boxplot.jl index e6cbe36c2a0..eeb80996792 100644 --- a/src/stats/boxplot.jl +++ b/src/stats/boxplot.jl @@ -13,62 +13,58 @@ The boxplot has 3 components: median - an `errorbar` whose whiskers span `range * iqr` - points marking outliers, that is, data outside the whiskers -# Arguments +## Arguments - `x`: positions of the categories - `y`: variables within the boxes -# Keywords -- `weights`: vector of statistical weights (length of data). By default, each observation has weight `1`. -- `orientation=:vertical`: orientation of box (`:vertical` or `:horizontal`) -- `width=1`: width of the box before shrinking -- `gap=0.2`: shrinking factor, `width -> width * (1 - gap)` -- `show_notch=false`: draw the notch -- `notchwidth=0.5`: multiplier of `width` for narrowest width of notch -- `show_median=true`: show median as midline -- `range`: multiple of IQR controlling whisker length -- `whiskerwidth`: multiplier of `width` for width of T's on whiskers, or - `:match` to match `width` -- `show_outliers`: show outliers as points -- `dodge`: vector of `Integer` (length of data) of grouping variable to create multiple side-by-side boxes at the same `x` position -- `dodge_gap = 0.03`: spacing between dodged boxes """ -@recipe(BoxPlot, x, y) do scene - Theme( - weights = automatic, - color = theme(scene, :patchcolor), - colormap = theme(scene, :colormap), - colorscale=identity, - colorrange = automatic, - orientation = :vertical, - # box and dodging - width = automatic, - dodge = automatic, - n_dodge = automatic, - gap = 0.2, - dodge_gap = 0.03, - strokecolor = theme(scene, :patchstrokecolor), - strokewidth = theme(scene, :patchstrokewidth), - # notch - show_notch = false, - notchwidth = 0.5, - # median line - show_median = true, - mediancolor = theme(scene, :linecolor), - medianlinewidth = theme(scene, :linewidth), - # whiskers - range = 1.5, - whiskerwidth = 0.0, - whiskercolor = theme(scene, :linecolor), - whiskerlinewidth = theme(scene, :linewidth), - # outliers points - show_outliers = true, - marker = theme(scene, :marker), - markersize = theme(scene, :markersize), - outliercolor = automatic, - outlierstrokecolor = theme(scene, :markerstrokecolor), - outlierstrokewidth = theme(scene, :markerstrokewidth), - cycle = [:color => :patchcolor], - inspectable = theme(scene, :inspectable) - ) +@recipe BoxPlot x y begin + "Vector of statistical weights (length of data). By default, each observation has weight `1`." + weights = automatic + color = @inherit patchcolor + colormap = @inherit colormap + colorscale=identity + colorrange = automatic + "Orientation of box (`:vertical` or `:horizontal`)." + orientation = :vertical + # box and dodging + "Width of the box before shrinking." + width = automatic + "Vector of `Integer` (length of data) of grouping variable to create multiple side-by-side boxes at the same `x` position." + dodge = automatic + n_dodge = automatic + "Shrinking factor, `width -> width * (1 - gap)`." + gap = 0.2 + "Spacing between dodged boxes." + dodge_gap = 0.03 + strokecolor = @inherit patchstrokecolor + strokewidth = @inherit patchstrokewidth + # notch + "Draw the notch." + show_notch = false + "Multiplier of `width` for narrowest width of notch." + notchwidth = 0.5 + # median line + "Show median as midline." + show_median = true + mediancolor = @inherit linecolor + medianlinewidth = @inherit linewidth + # whiskers + "Multiple of IQR controlling whisker length." + range = 1.5 + "Multiplier of `width` for width of T's on whiskers, or `:match` to match `width`." + whiskerwidth = 0.0 + whiskercolor = @inherit linecolor + whiskerlinewidth = @inherit linewidth + # outliers points + "Show outliers as points." + show_outliers = true + marker = @inherit marker + markersize = @inherit markersize + outliercolor = automatic + outlierstrokecolor = @inherit markerstrokecolor + outlierstrokewidth = @inherit markerstrokewidth + cycle = [:color => :patchcolor] + inspectable = @inherit inspectable end conversion_trait(x::Type{<:BoxPlot}) = SampleBased() From 661f8ac42d3ead0251c6e8200b298d0e3fccb967 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:46:26 +0100 Subject: [PATCH 093/106] convert crossbar --- src/stats/crossbar.jl | 66 ++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/src/stats/crossbar.jl b/src/stats/crossbar.jl index 5fb77c29f0f..bd60b5abde4 100644 --- a/src/stats/crossbar.jl +++ b/src/stats/crossbar.jl @@ -6,49 +6,45 @@ The StatMakie.jl package is licensed under the MIT "Expat" License: crossbar(x, y, ymin, ymax; kwargs...) Draw a crossbar. A crossbar represents a range with a (potentially notched) box. It is most commonly used as part of the `boxplot`. -# Arguments +## Arguments - `x`: position of the box - `y`: position of the midline within the box - `ymin`: lower limit of the box - `ymax`: upper limit of the box -# Keywords -- `orientation=:vertical`: orientation of box (`:vertical` or `:horizontal`) -- `width=1`: width of the box before shrinking -- `gap=0.2`: shrinking factor, `width -> width * (1 - gap)` -- `show_notch=false`: draw the notch -- `notchmin=automatic`: lower limit of the notch -- `notchmax=automatic`: upper limit of the notch -- `notchwidth=0.5`: multiplier of `width` for narrowest width of notch -- `show_midline=true`: show midline """ -@recipe(CrossBar, x, y, ymin, ymax) do scene - t = Theme( - color=theme(scene, :patchcolor), - colormap=theme(scene, :colormap), - colorscale=identity, - colorrange=automatic, - orientation=:vertical, +@recipe CrossBar x y ymin ymax begin + color= @inherit patchcolor + colormap= @inherit colormap + colorscale=identity + colorrange=automatic + "Orientation of box (`:vertical` or `:horizontal`)." + orientation=:vertical # box and dodging - width = automatic, - dodge = automatic, - n_dodge = automatic, - gap = 0.2, - dodge_gap = 0.03, - strokecolor = theme(scene, :patchstrokecolor), - strokewidth = theme(scene, :patchstrokewidth), + "Width of the box before shrinking." + width = automatic + dodge = automatic + n_dodge = automatic + "Shrinking factor, `width -> width * (1 - gap)`." + gap = 0.2 + dodge_gap = 0.03 + strokecolor = @inherit patchstrokecolor + strokewidth = @inherit patchstrokewidth # notch - show_notch=false, - notchmin=automatic, - notchmax=automatic, - notchwidth=0.5, + "Whether to draw the notch." + show_notch=false + "Lower limit of the notch." + notchmin=automatic + "Upper limit of the notch." + notchmax=automatic + "Multiplier of `width` for narrowest width of notch." + notchwidth=0.5 # median line - show_midline=true, - midlinecolor=automatic, - midlinewidth=theme(scene, :linewidth), - inspectable = theme(scene, :inspectable), - cycle = [:color => :patchcolor], -) - t + "Show midline." + show_midline=true + midlinecolor=automatic + midlinewidth= @inherit linewidth + inspectable = @inherit inspectable + cycle = [:color => :patchcolor] end function Makie.plot!(plot::CrossBar) From fdd564571f6f47f3e5cb86632d6ddf9bf40eeb89 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:52:26 +0100 Subject: [PATCH 094/106] convert density --- src/stats/density.jl | 61 +++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/src/stats/density.jl b/src/stats/density.jl index 82034cce2e3..36d35bb8dc1 100644 --- a/src/stats/density.jl +++ b/src/stats/density.jl @@ -17,41 +17,38 @@ function convert_arguments(P::PlotFunc, d::KernelDensity.BivariateKDE) end """ - density(values; npoints = 200, offset = 0.0, direction = :x) + density(values) Plot a kernel density estimate of `values`. -`npoints` controls the resolution of the estimate, the baseline can be -shifted with `offset` and the `direction` set to `:x` or `:y`. -`bandwidth` and `boundary` are determined automatically by default. - -Statistical weights can be provided via the `weights` keyword argument. - -`color` is usually set to a single color, but can also be set to `:x` or -`:y` to color with a gradient. If you use `:y` when `direction = :x` (or vice versa), -note that only 2-element colormaps can work correctly. - -## Attributes -$(ATTRIBUTES) """ -@recipe(Density) do scene - Theme( - color = theme(scene, :patchcolor), - colormap = theme(scene, :colormap), - colorscale = identity, - colorrange = Makie.automatic, - strokecolor = theme(scene, :patchstrokecolor), - strokewidth = theme(scene, :patchstrokewidth), - linestyle = nothing, - strokearound = false, - npoints = 200, - offset = 0.0, - direction = :x, - boundary = automatic, - bandwidth = automatic, - weights = automatic, - cycle = [:color => :patchcolor], - inspectable = theme(scene, :inspectable) - ) +@recipe Density begin + """ + Usually set to a single color, but can also be set to `:x` or + `:y` to color with a gradient. If you use `:y` when `direction = :x` (or vice versa), + note that only 2-element colormaps can work correctly. + """ + color = @inherit patchcolor + colormap = @inherit colormap + colorscale = identity + colorrange = Makie.automatic + strokecolor = @inherit patchstrokecolor + strokewidth = @inherit patchstrokewidth + linestyle = nothing + strokearound = false + "The resolution of the estimated curve along the dimension set in `direction`." + npoints = 200 + "Shift the density baseline, for layering multiple densities on top of each other." + offset = 0.0 + "The dimension along which the `values` are distributed. Can be `:x` or `:y`." + direction = :x + "Boundary of the density estimation, determined automatically if `automatic`." + boundary = automatic + "Kernel density bandwidth, determined automatically if `automatic`." + bandwidth = automatic + "Assign a vector of statistical weights to `values`." + weights = automatic + cycle = [:color => :patchcolor] + inspectable = @inherit inspectable end function plot!(plot::Density{<:Tuple{<:AbstractVector}}) From 13566a4614b45f3fd9e0fed5daf63e913cf0a396 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:57:58 +0100 Subject: [PATCH 095/106] convert qqplot and qqnorm --- src/stats/distributions.jl | 41 +++++++++++++------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/src/stats/distributions.jl b/src/stats/distributions.jl index 6f2221119f3..0586f590800 100644 --- a/src/stats/distributions.jl +++ b/src/stats/distributions.jl @@ -44,32 +44,19 @@ Possible values are the following. Broadly speaking, `qqline = :identity` is useful to see if `x` and `y` follow the same distribution, whereas `qqline = :fit` and `qqline = :fitrobust` are useful to see if the distribution of `y` can be obtained from the distribution of `x` via an affine transformation. - -Graphical attributes are -- `color` to control color of both line and markers (if `markercolor` is not specified) -- `linestyle` -- `linewidth` -- `markercolor` -- `strokecolor` -- `strokewidth` -- `marker` -- `markersize` """ -@recipe(QQPlot) do scene - s_theme = default_theme(scene, Scatter) - l_theme = default_theme(scene, Lines) - Attributes( - color = l_theme.color, - linestyle = l_theme.linestyle, - linewidth = l_theme.linewidth, - markercolor = automatic, - markersize = s_theme.markersize, - strokecolor = s_theme.strokecolor, - strokewidth = s_theme.strokewidth, - marker = s_theme.marker, - inspectable = theme(scene, :inspectable), - cycle = [:color], - ) +@recipe QQPlot begin + "Control color of both line and markers (if `markercolor` is not specified)." + color = @inherit linecolor + linestyle = nothing + linewidth = @inherit linewidth + markercolor = automatic + markersize = @inherit markersize + strokecolor = @inherit markerstrokecolor + strokewidth = @inherit markerstrokewidth + marker = @inherit marker + MakieCore.mixin_generic_plot_attributes()... + cycle = [:color] end """ @@ -78,8 +65,8 @@ end Shorthand for `qqplot(Normal(0,1), y)`, i.e., draw a Q-Q plot of `y` against the standard normal distribution. See `qqplot` for more details. """ -@recipe(QQNorm) do scene - default_theme(scene, QQPlot) +@recipe QQNorm begin + MakieCore.documented_attributes(QQPlot)... end # Compute points and line for the qqplot From c57f4d18761c776e517d34bea2d74658636ab494 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 20:59:41 +0100 Subject: [PATCH 096/106] convert ecdfplot --- src/stats/ecdf.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/stats/ecdf.jl b/src/stats/ecdf.jl index f8038456a9e..9c89e3cc5b7 100644 --- a/src/stats/ecdf.jl +++ b/src/stats/ecdf.jl @@ -44,12 +44,9 @@ Plot the empirical cumulative distribution function (ECDF) of `values`. `npoints` controls the resolution of the plot. If `weights` for the values are provided, a weighted ECDF is plotted. - -## Attributes -$(ATTRIBUTES) """ -@recipe(ECDFPlot) do scene - default_theme(scene, Stairs) +@recipe ECDFPlot begin + MakieCore.documented_attributes(Stairs)... end used_attributes(::Type{<:ECDFPlot}, ::AbstractVector) = (:npoints, :weights) From 422f2e3773370fa7f343fe780316fdb4e712df8b Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 21:02:59 +0100 Subject: [PATCH 097/106] convert hexbin --- src/stats/hexbin.jl | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/stats/hexbin.jl b/src/stats/hexbin.jl index c163f29bf0a..0cd4b9411eb 100644 --- a/src/stats/hexbin.jl +++ b/src/stats/hexbin.jl @@ -2,36 +2,19 @@ hexbin(xs, ys; kwargs...) Plots a heatmap with hexagonal bins for the observations `xs` and `ys`. - -## Attributes - -### Specific to `Hexbin` - -- `weights = nothing`: Weights for each observation. Can be `nothing` (each observation carries weight 1) or any `AbstractVector{<: Real}` or `StatsBase.AbstractWeights`. -- `bins = 20`: If an `Int`, sets the number of bins in x and y direction. If a `Tuple{Int, Int}`, sets the number of bins for x and y separately. -- `cellsize = nothing`: If a `Real`, makes equally-sided hexagons with width `cellsize`. If a `Tuple{Real, Real}` specifies hexagon width and height separately. -- `threshold::Int = 1`: The minimal number of observations in the bin to be shown. If 0, all zero-count hexagons fitting into the data limits will be shown. -- `colorscale = identity`: A function to scale the number of observations in a bin, eg. log10. - -### Generic - -- `colormap::Union{Symbol, Vector{<:Colorant}} = :viridis` -- `colorrange::Tuple(<:Real,<:Real} = Makie.automatic` sets the values representing the start and end points of `colormap`. """ -@recipe(Hexbin) do scene - return Attributes(; - colormap=theme(scene, :colormap), - colorscale=identity, - colorrange=Makie.automatic, - lowclip = automatic, - highclip = automatic, - nan_color = :transparent, - bins=20, - weights=nothing, - cellsize=nothing, - threshold=1, - strokewidth=0, - strokecolor=:black) +@recipe Hexbin begin + "If an `Int`, sets the number of bins in x and y direction. If a `Tuple{Int, Int}`, sets the number of bins for x and y separately." + bins=20 + "Weights for each observation. Can be `nothing` (each observation carries weight 1) or any `AbstractVector{<: Real}` or `StatsBase.AbstractWeights`." + weights=nothing + "If a `Real`, makes equally-sided hexagons with width `cellsize`. If a `Tuple{Real, Real}` specifies hexagon width and height separately." + cellsize=nothing + "The minimal number of observations in the bin to be shown. If 0, all zero-count hexagons fitting into the data limits will be shown." + threshold=1 + strokewidth=0 + strokecolor=:black + MakieCore.mixin_colormap_attributes()... end function spacings_offsets_nbins(bins::Tuple{Int,Int}, cellsize::Nothing, xmi, xma, ymi, yma) From bbdab830e9a7ff394a3d3adc7f978c7a8032d6d0 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 21:14:27 +0100 Subject: [PATCH 098/106] convert hist --- src/stats/hist.jl | 158 +++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 80 deletions(-) diff --git a/src/stats/hist.jl b/src/stats/hist.jl index d02b2325ba7..0feb0024219 100644 --- a/src/stats/hist.jl +++ b/src/stats/hist.jl @@ -21,34 +21,35 @@ function _hist_center_weights(values, edges, normalization, scale_to, wgts) end """ - stephist(values; bins = 15, normalization = :none) + stephist(values) -Plot a step histogram of `values`. `bins` can be an `Int` to create that -number of equal-width bins over the range of `values`. -Alternatively, it can be a sorted iterable of bin edges. The histogram -can be normalized by setting `normalization`. - -Shares most options with `hist` plotting function. - -Statistical weights can be provided via the `weights` keyword argument. - -The following attributes can move the histogram around, -which comes in handy when placing multiple histograms into one plot: -* `scale_to = nothing`: allows to scale all values to a certain height - -## Attributes -$(ATTRIBUTES) +Plot a step histogram of `values`. """ -@recipe(StepHist, values) do scene - Attributes( - bins = 15, # Int or iterable of edges - normalization = :none, - weights = automatic, - cycle = [:color => :patchcolor], - color = theme(scene, :patchcolor), - linestyle = :solid, - scale_to = nothing, - ) +@recipe StepHist values begin + "Can be an `Int` to create that number of equal-width bins over the range of `values`. Alternatively, it can be a sorted iterable of bin edges." + bins = 15 # Int or iterable of edges + """Allows to apply a normalization to the histogram. + Possible values are: + + * `:pdf`: Normalize by sum of weights and bin sizes. Resulting histogram + has norm 1 and represents a PDF. + * `:density`: Normalize by bin sizes only. Resulting histogram represents + count density of input and does not have norm 1. Will not modify the + histogram if it already represents a density (`h.isdensity == 1`). + * `:probability`: Normalize by sum of weights only. Resulting histogram + represents the fraction of probability mass for each bin and does not have + norm 1. + * `:none`: Do not normalize. + """ + normalization = :none + "Allows to provide statistical weights." + weights = automatic + cycle = [:color => :patchcolor] + color = @inherit patchcolor + linewidth = @inherit linewidth + linestyle = :solid + "Allows to scale all values to a certain height." + scale_to = nothing end function Makie.plot!(plot::StepHist) @@ -83,61 +84,58 @@ function Makie.plot!(plot::StepHist) end """ - hist(values; bins = 15, normalization = :none) - -Plot a histogram of `values`. `bins` can be an `Int` to create that -number of equal-width bins over the range of `values`. -Alternatively, it can be a sorted iterable of bin edges. The histogram -can be normalized by setting `normalization`. Possible values are: - -* `:pdf`: Normalize by sum of weights and bin sizes. Resulting histogram - has norm 1 and represents a PDF. -* `:density`: Normalize by bin sizes only. Resulting histogram represents - count density of input and does not have norm 1. Will not modify the - histogram if it already represents a density (`h.isdensity == 1`). -* `:probability`: Normalize by sum of weights only. Resulting histogram - represents the fraction of probability mass for each bin and does not have - norm 1. -* `:none`: Do not normalize. - -Statistical weights can be provided via the `weights` keyword argument. - -The following attributes can move the histogram around, -which comes in handy when placing multiple histograms into one plot: -* `offset = 0.0`: adds an offset to every value -* `fillto = 0.0`: defines where the bar starts -* `scale_to = nothing`: allows to scale all values to a certain height -* `flip = false`: flips all values - -Color can either be: -* a vector of `bins` colors -* a single color -* `:values`, to color the bars with the values from the histogram - -## Attributes -$(ATTRIBUTES) + hist(values) + +Plot a histogram of `values`. """ -@recipe(Hist, values) do scene - Attributes( - bins = 15, # Int or iterable of edges - normalization = :none, - weights = automatic, - cycle = [:color => :patchcolor], - color = theme(scene, :patchcolor), - offset = 0.0, - fillto = automatic, - scale_to = nothing, - - bar_labels = nothing, - flip_labels_at = Inf, - label_color = theme(scene, :textcolor), - over_background_color = automatic, - over_bar_color = automatic, - label_offset = 5, - label_font = theme(scene, :font), - label_size = 20, - label_formatter = bar_label_formatter - ) +@recipe Hist values begin + """ + Can be an `Int` to create that number of equal-width bins over the range of `values`. Alternatively, it can be a sorted iterable of bin edges. + """ + bins = 15 + """ + Allows to normalize the histogram. Possible values are: + + * `:pdf`: Normalize by sum of weights and bin sizes. Resulting histogram + has norm 1 and represents a PDF. + * `:density`: Normalize by bin sizes only. Resulting histogram represents + count density of input and does not have norm 1. Will not modify the + histogram if it already represents a density (`h.isdensity == 1`). + * `:probability`: Normalize by sum of weights only. Resulting histogram + represents the fraction of probability mass for each bin and does not have + norm 1. + * `:none`: Do not normalize. + """ + normalization = :none + "Allows to statistically weight the observations." + weights = automatic + cycle = [:color => :patchcolor] + """ + Color can either be: + * a vector of `bins` colors + * a single color + * `:values`, to color the bars with the values from the histogram + """ + color = @inherit patchcolor + strokewidth = @inherit patchstrokewidth + strokecolor = @inherit patchstrokecolor + "Adds an offset to every value." + offset = 0.0 + "Defines where the bars start." + fillto = automatic + "Allows to scale all values to a certain height." + scale_to = nothing + bar_labels = nothing + flip_labels_at = Inf + label_color = @inherit textcolor + over_background_color = automatic + over_bar_color = automatic + label_offset = 5 + label_font = @inherit font + label_size = 20 + label_formatter = bar_label_formatter + "Set the direction of the bars." + direction = :y end function pick_hist_edges(vals, bins) From 8b081a6c7f2183d95799175cbd620ddb9de2899f Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 3 Mar 2024 21:20:18 +0100 Subject: [PATCH 099/106] convert violin --- src/stats/violin.jl | 61 +++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/stats/violin.jl b/src/stats/violin.jl index d3d7d5c9707..8ac5716fc6c 100644 --- a/src/stats/violin.jl +++ b/src/stats/violin.jl @@ -1,38 +1,39 @@ """ - violin(x, y; kwargs...) + violin(x, y) Draw a violin plot. -# Arguments +## Arguments - `x`: positions of the categories - `y`: variables whose density is computed -# Keywords -- `weights`: vector of statistical weights (length of data). By default, each observation has weight `1`. -- `orientation=:vertical`: orientation of the violins (`:vertical` or `:horizontal`) -- `width=1`: width of the box before shrinking -- `gap=0.2`: shrinking factor, `width -> width * (1 - gap)` -- `show_median=false`: show median as midline -- `side=:both`: specify `:left` or `:right` to only plot the violin on one side -- `datalimits`: specify values to trim the `violin`. Can be a `Tuple` or a `Function` (e.g. `datalimits=extrema`) """ -@recipe(Violin, x, y) do scene - Theme(; - default_theme(scene, Poly)..., - npoints = 200, - boundary = automatic, - bandwidth = automatic, - weights = automatic, - side = :both, - orientation = :vertical, - width = automatic, - dodge = automatic, - n_dodge = automatic, - gap = 0.2, - dodge_gap = 0.03, - datalimits = (-Inf, Inf), - max_density = automatic, - show_median = false, - mediancolor = theme(scene, :linecolor), - medianlinewidth = theme(scene, :linewidth), - ) +@recipe Violin x y begin + npoints = 200 + boundary = automatic + bandwidth = automatic + "vector of statistical weights (length of data). By default, each observation has weight `1`." + weights = automatic + "Specify `:left` or `:right` to only plot the violin on one side." + side = :both + "Orientation of the violins (`:vertical` or `:horizontal`)" + orientation = :vertical + "Width of the box before shrinking." + width = automatic + dodge = automatic + n_dodge = automatic + "Shrinking factor, `width -> width * (1 - gap)`." + gap = 0.2 + dodge_gap = 0.03 + "Specify values to trim the `violin`. Can be a `Tuple` or a `Function` (e.g. `datalimits=extrema`)." + datalimits = (-Inf, Inf) + max_density = automatic + "Show median as midline." + show_median = false + mediancolor = @inherit linecolor + medianlinewidth = @inherit linewidth + color = @inherit patchcolor + strokecolor = @inherit patchstrokecolor + strokewidth = @inherit patchstrokewidth + MakieCore.mixin_generic_plot_attributes()... + cycle = [:color => :patchcolor] end conversion_trait(::Type{<:Violin}) = SampleBased() From 97ef4dc5f1d18dc031eab18306f09957fa3449a7 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Mon, 4 Mar 2024 15:26:54 +0100 Subject: [PATCH 100/106] improve error message printing --- MakieCore/src/recipes.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 0df1fe9cd30..ff0431f12ec 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -653,14 +653,15 @@ function print_columns(io::IO, v::Vector{String}; gapsize = 2, row_major = true, end function Base.showerror(io::IO, i::InvalidAttributeError) - print(io, "InvalidAttributeError: ") n = length(i.attributes) - print(io, "Plot type $(i.plottype) does not recognize attribute$(n > 1 ? "s" : "") ") + print(io, "Invalid attribute$(n > 1 ? "s" : "") ") for (j, att) in enumerate(i.attributes) j > 1 && print(io, j == length(i.attributes) ? " and " : ", ") printstyled(io, att; color = :red, bold = true) end - println(".") + print(io, " for plot type ") + printstyled(io, i.plottype; color = :blue, bold = true) + println(io, ".") nameset = sort(string.(collect(attribute_names(i.plottype)))) println(io) println(io, "The available plot attributes for $(i.plottype) are:") From 2b6fb21a17d1df366eae45acefe3033bcedce09c Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Mon, 4 Mar 2024 15:49:57 +0100 Subject: [PATCH 101/106] add docstrings for mutating functions and plot types --- MakieCore/src/recipes.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index ff0431f12ec..77808f091bd 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -335,7 +335,8 @@ end macro recipe(Tsym::Symbol, args...) funcname_sym = to_func_name(Tsym) - funcname! = esc(Symbol("$(funcname_sym)!")) + funcname!_sym = Symbol("$(funcname_sym)!") + funcname! = esc(funcname!_sym) PlotType = esc(Tsym) funcname = esc(funcname_sym) @@ -417,9 +418,10 @@ macro recipe(Tsym::Symbol, args...) Dict(k => v.docstring for (k, v) in documented_attributes(T).d) end - docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(funcname_sym)), user_docstring) + docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(Tsym)), $(QuoteNode(funcname_sym)),user_docstring) @doc docstring_modified $funcname_sym - + @doc "`$($(string(Tsym)))` is the plot type associated with plotting function `$($(string(funcname_sym)))`. Check the docstring for `$($(string(funcname_sym)))` for further information." $Tsym + @doc "`$($(string(funcname!_sym)))` is the mutating variant of plotting function `$($(string(funcname_sym)))`. Check the docstring for `$($(string(funcname_sym)))` for further information." $funcname!_sym export $PlotType, $funcname, $funcname! end @@ -436,14 +438,16 @@ macro recipe(Tsym::Symbol, args...) q end -function make_recipe_docstring(P::Type{<:Plot}, funcsym, docstring) +function make_recipe_docstring(P::Type{<:Plot}, Tsym, funcname_sym, docstring) io = IOBuffer() attr_docstrings = _attribute_docs(P) print(io, docstring) - # println(io, "```") + println(io, "## Plot type") + println(io, "The plot type alias for the `$funcname_sym` function is `$Tsym`.") + println(io, "## Attributes") println(io) From c521e83cfef617299292e523ca3fc9151eb93d14 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 5 Mar 2024 11:15:24 +0100 Subject: [PATCH 102/106] add missing docstrings --- MakieCore/src/basic_plots.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 1a08ff08037..c0631398f95 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -59,7 +59,7 @@ function mixin_generic_plot_attributes() depth_shift = 0.0f0 "sets the transformation space for box encompassing the plot. See `Makie.spaces()` for possible inputs." space = :data - "adjusts whether the plot is rendered with fxaa (anti-aliasing)." + "adjusts whether the plot is rendered with fxaa (anti-aliasing, GLMakie only)." fxaa = true end end @@ -118,6 +118,7 @@ function mixin_colormap_attributes() lowclip = automatic "The color for any value above the colorrange." highclip = automatic + "The color for NaN values." nan_color = :transparent "The alpha value of the colormap or color attribute. Multiple alphas like in `plot(alpha=0.2, color=(:red, 0.5)`, will get multiplied." alpha = 1.0 @@ -246,7 +247,7 @@ Available algorithms are: * `:indexedabsorption` => IndexedAbsorptionRGBA """ @recipe Volume x y z volume begin - "Sets the volume algorithm that is used." + "Sets the volume algorithm that is used." algorithm = :mip "Sets the range of values picked up by the IsoValue algorithm." isovalue = 0.5 @@ -254,7 +255,9 @@ Available algorithms are: isorange = 0.05 "Sets whether the volume data should be sampled with interpolation." interpolate = true + "Enables depth write for Volume, so that volume correctly occludes other objects." enable_depth = true + "Absorption multiplier for algorithm=:absorption. This changes how much light each voxel absorbs." absorption = 1f0 mixin_generic_plot_attributes()... mixin_shading_attributes()... @@ -384,9 +387,11 @@ Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`. "Sets the rotation of the marker. A `Billboard` rotation is always around the depth axis." rotations = Billboard() + "The offset of the marker from the given position in `markerspace` units. Default is centered around the position (markersize * -0.5)." marker_offset = automatic "Controls whether the model matrix (without translation) applies to the marker itself, rather than just the positions. (If this is true, `scale!` and `rotate!` will affect the marker." transform_marker = false + "Optional distancefield used for e.g. font and bezier path rendering. Will get set automatically." distancefield = nothing uv_offset_width = (0.0, 0.0, 0.0, 0.0) "Sets the space in which `markersize` is given. See `Makie.spaces()` for possible inputs" From a54da66554431207316cd0974da81f24a252808d Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 5 Mar 2024 13:16:08 +0100 Subject: [PATCH 103/106] reconnect lines docstring --- MakieCore/src/basic_plots.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index c0631398f95..109864dc110 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -290,7 +290,6 @@ Creates a connected line plot for each element in `(x, y, z)`, `(x, y)` or `posi `NaN` values are displayed as gaps in the line. """ - @recipe Lines positions begin "The color of the line." color = @inherit linecolor From 1d7b844547ad8c8c571a88abbd9df38e195f9eb3 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 5 Mar 2024 13:16:17 +0100 Subject: [PATCH 104/106] move functions out of macro --- MakieCore/src/recipes.jl | 44 ++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 77808f091bd..6e6e69fc497 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -189,11 +189,6 @@ macro recipe(theme_func, Tsym::Symbol, args::Symbol...) expr end -function is_attribute end -function default_attribute_values end -function attribute_default_expressions end -function _attribute_docs end -function attribute_names end function documented_attributes end # this can be used for inheriting from other recipes attribute_names(_) = nothing @@ -331,6 +326,26 @@ macro DocumentedAttributes(expr::Expr) end end +function is_attribute(T::Type{<:Plot}, sym::Symbol) + sym in attribute_names(T) +end + +function attribute_names(T::Type{<:Plot}) + keys(documented_attributes(T).d) +end + +function default_theme(scene, T::Type{<:Plot}) + Attributes(documented_attributes(T).closure(scene)) +end + +function attribute_default_expressions(T::Type{<:Plot}) + Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) +end + +function _attribute_docs(T::Type{<:Plot}) + Dict(k => v.docstring for (k, v) in documented_attributes(T).d) +end + macro recipe(Tsym::Symbol, args...) @@ -398,25 +413,6 @@ macro recipe(Tsym::Symbol, args...) kwdict = Dict{Symbol, Any}(kw) _create_plot!($funcname, kwdict, args...) end - function MakieCore.is_attribute(T::Type{<:$(PlotType)}, sym::Symbol) - sym in MakieCore.attribute_names(T) - end - - function MakieCore.attribute_names(T::Type{<:$(PlotType)}) - keys(documented_attributes(T).d) - end - - function $(MakieCore).default_theme(scene, T::Type{<:$PlotType}) - Attributes(documented_attributes(T).closure(scene)) - end - - function MakieCore.attribute_default_expressions(T::Type{<:$PlotType}) - Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) - end - - function MakieCore._attribute_docs(T::Type{<:$PlotType}) - Dict(k => v.docstring for (k, v) in documented_attributes(T).d) - end docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(Tsym)), $(QuoteNode(funcname_sym)),user_docstring) @doc docstring_modified $funcname_sym From 9a4553050957fb343a2ce96896da2c2e73c82b51 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 5 Mar 2024 13:20:04 +0100 Subject: [PATCH 105/106] fix arrows example and adjust docs --- MakieCore/src/basic_plots.jl | 4 +-- ReferenceTests/src/tests/examples3d.jl | 42 +++++++++++++------------- src/basic_recipes/arrows.jl | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 109864dc110..113575f6fef 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -534,8 +534,8 @@ Draws a wireframe, either interpreted as a surface or as a mesh. end @recipe Arrows points directions begin + "Sets the color of arrowheads and lines. Can be overridden separately using `linecolor` and `arrowcolor`." color = :black - """Scales the size of the arrow head. This defaults to `0.3` in the 2D case and `Vec3f(0.2, 0.2, 0.3)` in the 3D case. For the latter the first two components scale the radius (in x/y direction) and the last scales @@ -582,6 +582,6 @@ end """Scales the width/diameter of the arrow tail. Defaults to `1` for 2D and `0.05` for the 3D case.""" linewidth = automatic - """Sets the color of the arrow head. Will copy `linecolor` if set to `automatic`.""" + """Sets the color of the arrow head. Will copy `color` if set to `automatic`.""" arrowcolor = automatic end diff --git a/ReferenceTests/src/tests/examples3d.jl b/ReferenceTests/src/tests/examples3d.jl index 2b15d26068f..7ed6356728a 100644 --- a/ReferenceTests/src/tests/examples3d.jl +++ b/ReferenceTests/src/tests/examples3d.jl @@ -199,27 +199,27 @@ end f, ax, p = surface(x, y, z, color=Makie.logo(), transparency=true) end -# @reference_test "Arrows on Sphere" begin -# n = 20 -# f = (x, y, z) -> x * exp(cos(y) * z) -# ∇f = (x, y, z) -> Point3f(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) - Point3f(x, y, z) * dot(Point3f(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(Point3f.(x, y, z)) -# ∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0 -# surface(x, y, z) -# arrows!( -# pts, ∇ˢF, -# arrowsize=0.03, linecolor=(:white, 0.6), linewidth=0.03 -# ) -# current_figure() -# end +@reference_test "Arrows on Sphere" begin + n = 20 + f = (x, y, z) -> x * exp(cos(y) * z) + ∇f = (x, y, z) -> Point3f(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) - Point3f(x, y, z) * dot(Point3f(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(Point3f.(x, y, z)) + ∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0 + surface(x, y, z) + arrows!( + pts, ∇ˢF, + arrowsize=0.03, linecolor=(:white, 0.6), linewidth=0.03 + ) + current_figure() +end @reference_test "surface + contour3d" begin vx = -1:0.01:1 diff --git a/src/basic_recipes/arrows.jl b/src/basic_recipes/arrows.jl index ed70e42e82f..4fdd50d7bb3 100644 --- a/src/basic_recipes/arrows.jl +++ b/src/basic_recipes/arrows.jl @@ -120,7 +120,7 @@ function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N}}, V}}) wher ) line_c = map((a, c)-> a === automatic ? c : a , arrowplot, linecolor, color) - arrow_c = map((a, c)-> a === automatic ? c : a , arrowplot, arrowcolor, line_c) + arrow_c = map((a, c)-> a === automatic ? c : a , arrowplot, arrowcolor, color) fxaa_bool = lift(fxaa -> fxaa == automatic ? N == 3 : fxaa, arrowplot, fxaa) # automatic == fxaa for 3D marker_head = lift((ah, q) -> arrow_head(N, ah, q), arrowplot, arrowhead, quality) From 098a20c9c0d299571f0257ac8a160ccfc759194e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Tue, 5 Mar 2024 13:36:59 +0100 Subject: [PATCH 106/106] put necessary functions back into macro --- MakieCore/src/recipes.jl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index 6e6e69fc497..3e52e57629d 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -189,6 +189,7 @@ macro recipe(theme_func, Tsym::Symbol, args::Symbol...) expr end +function attribute_names end function documented_attributes end # this can be used for inheriting from other recipes attribute_names(_) = nothing @@ -330,14 +331,6 @@ function is_attribute(T::Type{<:Plot}, sym::Symbol) sym in attribute_names(T) end -function attribute_names(T::Type{<:Plot}) - keys(documented_attributes(T).d) -end - -function default_theme(scene, T::Type{<:Plot}) - Attributes(documented_attributes(T).closure(scene)) -end - function attribute_default_expressions(T::Type{<:Plot}) Dict(k => v.default_expr for (k, v) in documented_attributes(T).d) end @@ -414,6 +407,14 @@ macro recipe(Tsym::Symbol, args...) _create_plot!($funcname, kwdict, args...) end + function $(MakieCore).attribute_names(T::Type{<:$(PlotType)}) + keys(documented_attributes(T).d) + end + + function $(MakieCore).default_theme(scene, T::Type{<:$(PlotType)}) + Attributes(documented_attributes(T).closure(scene)) + end + docstring_modified = make_recipe_docstring($PlotType, $(QuoteNode(Tsym)), $(QuoteNode(funcname_sym)),user_docstring) @doc docstring_modified $funcname_sym @doc "`$($(string(Tsym)))` is the plot type associated with plotting function `$($(string(funcname_sym)))`. Check the docstring for `$($(string(funcname_sym)))` for further information." $Tsym