Skip to content

Commit cf1a0c2

Browse files
Provide errorbars as callable recipes (#4362)
* export (x/y/z)error(!) * let markershape be overrideble * more specific condition
1 parent f6b91b4 commit cf1a0c2

4 files changed

Lines changed: 47 additions & 20 deletions

File tree

src/pipeline.jl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,18 @@ end
9898
function _add_errorbar_kw(kw_list::Vector{KW}, kw::AKW)
9999
# handle error bars by creating new recipedata data... these will have
100100
# the same recipedata index as the recipedata they are copied from
101-
for esym in (:xerror, :yerror, :zerror)
102-
if get(kw, esym, nothing) !== nothing
103-
# we make a copy of the KW and apply an errorbar recipe
104-
errkw = copy(kw)
105-
errkw[:seriestype] = esym
106-
errkw[:label] = ""
107-
errkw[:primary] = false
108-
push!(kw_list, errkw)
101+
st = get(kw, :seriestype, :none)
102+
errors = (:xerror, :yerror, :zerror)
103+
if st errors
104+
for esym in errors
105+
if get(kw, esym, nothing) !== nothing
106+
# we make a copy of the KW and apply an errorbar recipe
107+
errkw = copy(kw)
108+
errkw[:seriestype] = esym
109+
errkw[:label] = ""
110+
errkw[:primary] = false
111+
push!(kw_list, errkw)
112+
end
109113
end
110114
end
111115
end
@@ -138,7 +142,7 @@ RecipesPipeline.get_axis_limits(plt::Plot, letter) = axis_limits(plt[1], letter,
138142

139143
## Plot recipes
140144

141-
RecipesPipeline.type_alias(plt::Plot) = get(_typeAliases, st, st)
145+
RecipesPipeline.type_alias(plt::Plot, st) = get(_typeAliases, st, st)
142146

143147
## Plot setup
144148

@@ -153,7 +157,7 @@ function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_l
153157
err_inds =
154158
findall(kw -> get(kw, :seriestype, :path) in (:xerror, :yerror, :zerror), kw_list)
155159
for ind in err_inds
156-
if get(kw_list[ind - 1], :seriestype, :path) === :scatter
160+
if ind > 1 && get(kw_list[ind - 1], :seriestype, :path) === :scatter
157161
tmp = copy(kw_list[ind])
158162
kw_list[ind] = copy(kw_list[ind - 1])
159163
kw_list[ind - 1] = tmp

src/recipes.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ end
11341134
# ---------------------------------------------------------------------------
11351135
# Error Bars
11361136

1137-
function error_style!(plotattributes::AKW)
1137+
@attributes function error_style!(plotattributes::AKW)
11381138
# errorbar color should soley determined by markerstrokecolor
11391139
if haskey(plotattributes, :marker_z)
11401140
reset_kw!(plotattributes, :marker_z)
@@ -1156,12 +1156,12 @@ function error_style!(plotattributes::AKW)
11561156
msc
11571157
end
11581158

1159-
plotattributes[:seriestype] = :path
1160-
plotattributes[:markerstrokecolor] = msc
1161-
plotattributes[:markercolor] = msc
1162-
plotattributes[:linecolor] = msc
1163-
plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
1164-
plotattributes[:label] = ""
1159+
seriestype := :path
1160+
markerstrokecolor --> msc
1161+
markercolor --> msc
1162+
linecolor --> msc
1163+
linewidth --> plotattributes[:markerstrokewidth]
1164+
label --> ""
11651165
end
11661166

11671167
# if we're passed a tuple of vectors, convert to a vector of tuples
@@ -1194,7 +1194,7 @@ clamp_to_eps!(ary) = (replace!(x -> x <= 0.0 ? Base.eps(Float64) : x, ary); noth
11941194

11951195
@recipe function f(::Type{Val{:xerror}}, x, y, z)
11961196
error_style!(plotattributes)
1197-
markershape := :vline
1197+
markershape --> :vline
11981198
xerr = error_zipit(plotattributes[:xerror])
11991199
if z === nothing
12001200
plotattributes[:x], plotattributes[:y] = error_coords(xerr, x, y)
@@ -1211,7 +1211,7 @@ end
12111211

12121212
@recipe function f(::Type{Val{:yerror}}, x, y, z)
12131213
error_style!(plotattributes)
1214-
markershape := :hline
1214+
markershape --> :hline
12151215
yerr = error_zipit(plotattributes[:yerror])
12161216
if z === nothing
12171217
plotattributes[:y], plotattributes[:x] = error_coords(yerr, y, x)
@@ -1228,7 +1228,7 @@ end
12281228

12291229
@recipe function f(::Type{Val{:zerror}}, x, y, z)
12301230
error_style!(plotattributes)
1231-
markershape := :hline
1231+
markershape --> :hline
12321232
if z !== nothing
12331233
zerr = error_zipit(plotattributes[:zerror])
12341234
plotattributes[:z], plotattributes[:x], plotattributes[:y] =

src/shorthands.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,16 @@ for letter in ("x", "y", "z")
487487
$(Symbol(letter, :grid!))(plt::PlotOrSubplot, args...; kw...) =
488488
plot!(plt; $(Symbol(letter, :grid)) = args, kw...)
489489
export $(Symbol(letter, :grid!))
490+
491+
"""
492+
$($letter)error(x, y [, z]; $($letter)error = vals)
493+
$($letter)error!(x, y [, z]; $($letter)error = vals)
494+
495+
Create or add a series of $($letter)errorbars at the positions defined by `x`, `y` and `z` with the lenghts defined in `vals`.
496+
497+
Markerstrokecolor will color the whole errorbars if not specified otherwise.
498+
"""
499+
@shorthands $(Symbol(letter, :error))
490500
end
491501
end
492502

test/test_recipes.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,16 @@ end
6565
@test Plots.seriestype_supported(Plots.UnicodePlotsBackend(), :hspan) === :recipe
6666
@test Plots.seriestype_supported(Plots.NoBackend(), :line) === :no
6767
end
68+
69+
@testset "error bars" begin
70+
x = y = 1:10
71+
yerror = fill(1, length(y))
72+
xerror = fill(0.2, length(x))
73+
p = Plots.xerror(x, y; xerror, linestyle = :solid)
74+
plot!(p, x, y; linestyle = :dash)
75+
yerror!(p, x, y; yerror, linestyle = :dot)
76+
@test length(p.series_list) == 3
77+
@test p[1][1][:linestyle] == :solid
78+
@test p[1][2][:linestyle] == :dash
79+
@test p[1][3][:linestyle] == :dot
80+
end

0 commit comments

Comments
 (0)