Merge pull request #2548 from daschw/surface

Implement zerror and surface type recipe fixes
This commit is contained in:
Daniel Schwabeneder 2020-04-07 17:50:32 +02:00 committed by GitHub
commit 67ba06cd77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 39 deletions

View File

@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.0.3"
version = "1.0.4"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

View File

@ -267,6 +267,7 @@ const _series_defaults = KW(
:bar_edges => false,
:xerror => nothing,
:yerror => nothing,
:zerror => nothing,
:ribbon => nothing,
:quiver => nothing,
:arrow => nothing, # allows for adding arrows to line/path... call `arrow(args...)`
@ -594,6 +595,7 @@ add_aliases(:color_palette, :palette)
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
add_aliases(:xerror, :xerr, :xerrorbar)
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
add_aliases(:zerror, :zerr, :zerrorbar)
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized)
add_aliases(:show_empty_bins, :showemptybins, :showempty, :show_empty)

View File

@ -211,7 +211,7 @@ const _base_supported_args = [
:seriestype,
:seriescolor, :seriesalpha,
:smooth,
:xerror, :yerror,
:xerror, :yerror, :zerror,
:subplot,
:x, :y, :z,
:show, :size,

View File

@ -946,6 +946,43 @@ const _examples = PlotExample[
end,
],
),
PlotExample(
"Error bars and array type recipes",
"",
[
quote
begin
struct Measurement <: Number
val::Float64
err::Float64
end
value(m::Measurement) = m.val
uncertainty(m::Measurement) = m.err
@recipe function f(::Type{T}, m::T) where T <: AbstractArray{<:Measurement}
if !(get(plotattributes, :seriestype, :path) in [:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image])
error_sym = Symbol(plotattributes[:letter], :error)
plotattributes[error_sym] = uncertainty.(m)
end
value.(m)
end
x = Measurement.(10sort(rand(10)), rand(10))
y = Measurement.(10sort(rand(10)), rand(10))
z = Measurement.(10sort(rand(10)), rand(10))
surf = Measurement.((1:10) .* (1:10)', rand(10,10))
plot(
scatter(x, [x y], msw = 0),
scatter(x, y, z, msw = 0),
heatmap(x, y, surf),
wireframe(x, y, surf),
legend = :topleft
)
end
end,
],
),
]
# Some constants for PlotDocs and PlotReferenceImages

View File

@ -159,7 +159,7 @@ end
function _add_errorbar_kw(kw_list::Vector{KW}, kw::AKW)
# handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror)
for esym in (:xerror, :yerror, :zerror)
if get(kw, esym, nothing) !== nothing
# we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw)

View File

@ -1012,49 +1012,62 @@ function error_zipit(ebar)
end
end
function error_coords(xorig, yorig, ebar)
# init empty x/y, and zip errors if passed Tuple{Vector,Vector}
x, y = Array{float_extended_type(xorig)}(undef, 0), Array{Float64}(undef, 0)
# for each point, create a line segment from the bottom to the top of the errorbar
for i = 1:max(length(xorig), length(yorig))
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
ebi = _cycle(ebar, i)
nanappend!(x, [xi, xi])
e1, e2 = if istuple(ebi)
first(ebi), last(ebi)
elseif isscalar(ebi)
ebi, ebi
else
error("unexpected ebi type $(typeof(ebi)) for errorbar: $ebi")
error_tuple(x) = x, x
error_tuple(x::Tuple) = x
function error_coords(errorbar, errordata, otherdata...)
ed = Vector{float_extended_type(errordata)}(undef, 0)
od = [Float64[] for _ in otherdata]
for (i, edi) in enumerate(errordata)
for (j, odj) in enumerate(otherdata)
odi = _cycle(odj, i)
nanappend!(od[j], [odi, odi])
end
nanappend!(y, [yi - e1, yi + e2])
e1, e2 = error_tuple(_cycle(errorbar, i))
nanappend!(ed, [edi - e1, edi + e2])
end
x, y
return (ed, od...)
end
# we will create a series of path segments, where each point represents one
# side of an errorbar
@recipe function f(::Type{Val{:yerror}}, x, y, z)
error_style!(plotattributes)
markershape := :hline
plotattributes[:x], plotattributes[:y] = error_coords(
plotattributes[:x],
plotattributes[:y],
error_zipit(plotattributes[:yerror]),
)
()
end
@deps yerror path
@recipe function f(::Type{Val{:xerror}}, x, y, z)
error_style!(plotattributes)
markershape := :vline
plotattributes[:y], plotattributes[:x] = error_coords(
plotattributes[:y],
plotattributes[:x],
error_zipit(plotattributes[:xerror]),
)
xerr = error_zipit(plotattributes[:xerror])
if z === nothing
plotattributes[:x], plotattributes[:y] = error_coords(xerr, x, y)
else
plotattributes[:x], plotattributes[:y], plotattributes[:z] =
error_coords(xerr, x, y, z)
end
()
end
@deps xerror path
@recipe function f(::Type{Val{:yerror}}, x, y, z)
error_style!(plotattributes)
markershape := :hline
yerr = error_zipit(plotattributes[:yerror])
if z === nothing
plotattributes[:y], plotattributes[:x] = error_coords(yerr, y, x)
else
plotattributes[:y], plotattributes[:x], plotattributes[:z] =
error_coords(yerr, y, x, z)
end
()
end
@deps yerror path
@recipe function f(::Type{Val{:zerror}}, x, y, z)
error_style!(plotattributes)
markershape := :hline
if z !== nothing
zerr = error_zipit(plotattributes[:zerror])
plotattributes[:z], plotattributes[:x], plotattributes[:y] =
error_coords(zerr, z, x, y)
end
()
end
@deps xerror path

View File

@ -219,13 +219,14 @@ end
_apply_type_recipe(
plotattributes,
v::Surface{<:AMat{<:Union{AbstractFloat, Integer, AbstractString, Missing}}},
letter,
) = v
function _apply_type_recipe(plotattributes, v::Surface)
ret = _apply_type_recipe(plotattributes, v.surf)
function _apply_type_recipe(plotattributes, v::Surface, letter)
ret = _apply_type_recipe(plotattributes, v.surf, letter)
if typeof(ret) <: Formatted
Formatted(Surface(ret.data), ret.formatter)
else
Surface(ret.data)
Surface(ret)
end
end