From 4e9e94eba72083a0d66fa263c1ace84a03331f42 Mon Sep 17 00:00:00 2001 From: yha Date: Wed, 23 Mar 2022 02:10:31 +0200 Subject: [PATCH] Annotation at discrete locations + docs updates --- src/args.jl | 3 ++- src/components.jl | 7 +++++-- src/examples.jl | 27 +++++++++++++++++++++++---- src/shorthands.jl | 15 ++++++++------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/args.jl b/src/args.jl index 5efbe506..0c8db97b 100644 --- a/src/args.jl +++ b/src/args.jl @@ -2062,7 +2062,6 @@ function _update_subplot_args( slice_arg!(plotattributes_in, sp.attr, k, subplot_index, remove_pair) end - _update_subplot_periphery(sp, anns) _update_subplot_colors(sp) lims_warned = false @@ -2078,6 +2077,8 @@ function _update_subplot_args( lims_warned = true end end + + _update_subplot_periphery(sp, anns) end # ----------------------------------------------------------------------------- diff --git a/src/components.jl b/src/components.jl index f82500f5..7100222a 100644 --- a/src/components.jl +++ b/src/components.jl @@ -578,6 +578,9 @@ _annotation(sp::Subplot, font, lab, pos...; alphabet = "abcdefghijklmnopqrstuvwx lab == :auto ? text("($(alphabet[sp[:subplot_index]]))", font) : _text_label(lab, font), ) +assign_annotation_coord!(axis, x) = discrete_value!(axis, x)[1] +assign_annotation_coord!(axis, x::TimeType) = assign_annotation_coord!(axis, Dates.value(x)) + # Expand arrays of coordinates, positions and labels into individual annotations # and make sure labels are of type PlotText function process_annotation(sp::Subplot, xs, ys, labs, font = _annotationfont(sp)) @@ -587,8 +590,8 @@ function process_annotation(sp::Subplot, xs, ys, labs, font = _annotationfont(sp ylength = length(methods(length, (typeof(ys),))) == 0 ? 1 : length(ys) for i in 1:max(xlength, ylength, length(labs)) x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i) - x = typeof(x) <: TimeType ? Dates.value(x) : x - y = typeof(y) <: TimeType ? Dates.value(y) : y + x = assign_annotation_coord!(sp[:xaxis], x) + y = assign_annotation_coord!(sp[:yaxis], y) push!(anns, _annotation(sp, font, lab, x, y)) end anns diff --git a/src/examples.jl b/src/examples.jl index 76842d58..ccd7c9dc 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -355,9 +355,10 @@ const _examples = PlotExample[ PlotExample( # 20 "Annotations", """ - The `annotations` keyword is used for text annotations in data-coordinates. Pass in a - tuple `(x, y, text)`, a vector of annotations, each of which is a tuple of `x`, `y` - and `text`. You can position annotations using relative coordinates with the syntax + The `annotations` keyword is used for text annotations in data-coordinates. + Pass in a 3-tuple of vectors `(x, y, text)`, or a vector of annotations, + each of which is a tuple of `x`, `y` and `text`. + You can position annotations using relative coordinates with the syntax `((px, py), text)`, where for example `px=.25` positions the annotation at `25%` of the subplot's axis width. `text` may be a simple `String`, or a `PlotText` object, which can be built with the @@ -366,7 +367,8 @@ const _examples = PlotExample[ `text` may also be a tuple `(string, attrs...)` of arguments which are passed to `Plots.text`. - `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`. + `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`, + and `annotate!(x, y, txt)` for `plot!(; annotation=(x,y,txt))`. Series annotations are used for annotating individual data points. They require only the annotation; x/y values are computed. Series annotations @@ -381,10 +383,13 @@ const _examples = PlotExample[ annotations = (3, y[3], Plots.text("this is #3", :left)), leg = false, ) + # single vector of annotation tuples annotate!([ (5, y[5], ("this is #5", 16, :red, :center)), (10, y[10], ("this is #10", :right, 20, "courier")), ]) + # `x, y, text` vectors + annotate!([2,8], y[[2,8]], ["#2", "#8"]) scatter!( range(2, stop = 8, length = 6), rand(6), @@ -1273,6 +1278,20 @@ const _examples = PlotExample[ end )], ), + PlotExample( # 58 + "Annotations at discrete locations", + """ + """, + [:( + begin + x, y = ["a","b","c"], [1,5,15] + p = scatter(["a", "b"], ["q", "r"], ms=8, legend=false, tickfontsize=20) + annotate!(["a","b"], ["r", "q"], + [text("ar", :top, :left,50), text("bq", :bottom, :right,20)]) + end + )], + ), + ] # Some constants for PlotDocs and PlotReferenceImages diff --git a/src/shorthands.jl b/src/shorthands.jl index d8963443..3617440b 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -443,21 +443,22 @@ yticks!(ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString plot!(; yticks = (ticks, labels), kw...) """ - annotate!(anns...) + annotate!(anns) + annotate!(anns::Tuple...) + annotate!(x, y, txt) Add annotations to an existing plot. - -# Arguments - -- `anns`: An `AbstractVector` of tuples of the form `(x,y,text)`. The `text` object - can be a `String`, `PlotText` PlotText (created with `text(args...)`), - or a tuple of arguments to `text` (e.g., `("Label", 8, :red, :top)`). +Annotations are specified either as a vector of tuples, each of the form `(x,y,txt)`, +or as three vectors, `x, y, txt`. +Each `txt` can be a `String`, `PlotText` PlotText (created with `text(args...)`), +or a tuple of arguments to `text` (e.g., `("Label", 8, :red, :top)`). # Example ```julia-repl julia> plot(1:10) julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))]) julia> annotate!([(4, 4, ("More text", 8, 45.0, :bottom, :red))]) +julia> annotate!([2,5], [6,3], ["text at (2,6)", "text at (5,3)"]) ``` """ annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)