Merge pull request #2548 from daschw/surface
Implement zerror and surface type recipe fixes
This commit is contained in:
commit
67ba06cd77
@ -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"
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -211,7 +211,7 @@ const _base_supported_args = [
|
||||
:seriestype,
|
||||
:seriescolor, :seriesalpha,
|
||||
:smooth,
|
||||
:xerror, :yerror,
|
||||
:xerror, :yerror, :zerror,
|
||||
:subplot,
|
||||
:x, :y, :z,
|
||||
:show, :size,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user