Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae43e05f6f | |||
| 5cd2ba7296 | |||
| 4a00018f25 | |||
| 32c725e770 | |||
| 4e2ee35125 | |||
| 35b0751714 | |||
| 28ebc0ccd8 | |||
| 3d693d88e0 | |||
| 6ddf31d465 | |||
| 5c1ea707ca | |||
| a6669f89a0 | |||
| 2a2d509c36 | |||
| fd4efb3f33 | |||
| e90ab0b898 | |||
| 44367c54da | |||
| 3273a65889 | |||
| 0aa606d835 | |||
| 40848e7432 | |||
| 10a5c2ed1d | |||
| 8cce78c890 | |||
| 294ade8aad | |||
| a59e8411c9 |
+1
-1
@@ -1,7 +1,7 @@
|
||||
name = "Plots"
|
||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
author = ["Tom Breloff (@tbreloff)"]
|
||||
version = "1.2.1"
|
||||
version = "1.2.3"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ const _arg_desc = KW(
|
||||
:legendtitlefontrotation => "Real. Font rotation of the legend title",
|
||||
:legendtitlefontcolor => "Color Type. Font color of the legend title",
|
||||
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
|
||||
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
|
||||
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.",
|
||||
:legendfont => "Font. Font of legend items.",
|
||||
:legendtitlefont => "Font. Font of the legend title.",
|
||||
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
|
||||
|
||||
@@ -828,6 +828,7 @@ const _pgfplotsx_seriestype = [
|
||||
:heatmap,
|
||||
:contour,
|
||||
:contour3d,
|
||||
:quiver,
|
||||
:shape,
|
||||
:steppre,
|
||||
:stepmid,
|
||||
|
||||
+4
-12
@@ -148,7 +148,7 @@ function gr_polyline(x, y, func = GR.polyline; arrowside = :none, arrowstyle = :
|
||||
end
|
||||
end
|
||||
|
||||
function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowstyle = :simple)
|
||||
function gr_polyline3d(x, y, z, func = GR.polyline3d)
|
||||
iend = 0
|
||||
n = length(x)
|
||||
while iend < n-1
|
||||
@@ -176,14 +176,6 @@ function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowst
|
||||
# if we found a start and end, draw the line segment, otherwise we're done
|
||||
if istart > 0 && iend > 0
|
||||
func(x[istart:iend], y[istart:iend], z[istart:iend])
|
||||
if arrowside in (:head,:both)
|
||||
gr_set_arrowstyle(arrowstyle)
|
||||
GR.drawarrow(x[iend-1], y[iend-1], z[iend-1], x[iend], y[iend], z[iend])
|
||||
end
|
||||
if arrowside in (:tail,:both)
|
||||
gr_set_arrowstyle(arrowstyle)
|
||||
GR.drawarrow(x[istart+1], y[istart+1], z[istart+1], x[istart], y[istart], z[istart])
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
@@ -749,9 +741,9 @@ function gr_get_ticks_size(ticks, rot)
|
||||
return w, h
|
||||
end
|
||||
|
||||
gr_tick_label(axis,label) = (axis[:formatter] in (:scientific, :auto)) ?
|
||||
gr_convert_sci_tick_label(label) :
|
||||
label
|
||||
gr_tick_label(axis, label) =
|
||||
(axis[:formatter] in (:scientific, :auto)) ? gr_convert_sci_tick_label(string(label)) :
|
||||
string(label)
|
||||
|
||||
function gr_convert_sci_tick_label(label)
|
||||
caret_split = split(label,'^')
|
||||
|
||||
+11
-5
@@ -603,14 +603,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st == :hexbin
|
||||
handle = ax."hexbin"(x, y;
|
||||
handle = ax."hexbin"(x, y,
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
gridsize = series[:bins],
|
||||
C = series[:weights],
|
||||
gridsize = series[:bins]==:auto ? 100 : series[:bins], # 100 is the default value
|
||||
linewidths = py_thickness_scale(plt, series[:linewidth]),
|
||||
edgecolors = py_color(get_linecolor(series)),
|
||||
alpha = series[:fillalpha],
|
||||
cmap = py_fillcolormap(series), # applies to the pcolorfast object
|
||||
extrakw...
|
||||
zorder = series[:series_plotindex],
|
||||
# extrakw... # We are not supporting clims for hexbin as calculation of bins is not trivial
|
||||
)
|
||||
push!(handles, handle)
|
||||
end
|
||||
@@ -643,7 +645,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
extrakw...
|
||||
)
|
||||
if series[:contour_labels] == true
|
||||
PyPlot."clabel"(handle, handle.levels)
|
||||
ax."clabel"(handle, handle.levels)
|
||||
end
|
||||
push!(handles, handle)
|
||||
|
||||
@@ -1074,6 +1076,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
end
|
||||
pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize]))
|
||||
pyaxis."label"."set_family"(axis[:guidefontfamily])
|
||||
|
||||
if (RecipesPipeline.is3d(sp))
|
||||
pyaxis."set_rotate_label"(false)
|
||||
end
|
||||
|
||||
if (letter == :y && !RecipesPipeline.is3d(sp))
|
||||
pyaxis."label"."set_rotation"(axis[:guidefontrotation] + 90)
|
||||
|
||||
@@ -155,8 +155,23 @@ RecipesPipeline.type_alias(plt::Plot) = get(_typeAliases, st, st)
|
||||
function RecipesPipeline.plot_setup!(plt::Plot, plotattributes, kw_list)
|
||||
_plot_setup(plt, plotattributes, kw_list)
|
||||
_subplot_setup(plt, plotattributes, kw_list)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_list)
|
||||
# swap errors
|
||||
err_inds = findall(kw -> get(kw, :seriestype, nothing) in (:xerror, :yerror, :zerror), kw_list)
|
||||
for ind in err_inds
|
||||
if kw_list[ind-1][:seriestype] == :scatter
|
||||
tmp = copy(kw_list[ind])
|
||||
kw_list[ind] = copy(kw_list[ind-1])
|
||||
kw_list[ind-1] = tmp
|
||||
end
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
|
||||
# TODO: Should some of this logic be moved to RecipesPipeline?
|
||||
function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
|
||||
# merge in anything meant for the Plot
|
||||
@@ -274,6 +289,7 @@ function RecipesPipeline.slice_series_attributes!(plt::Plot, kw_list, kw)
|
||||
# in series attributes given as vector with one element per series,
|
||||
# select the value for current series
|
||||
_slice_series_args!(kw, plt, sp, series_idx(kw_list, kw))
|
||||
return nothing
|
||||
end
|
||||
|
||||
RecipesPipeline.series_defaults(plt::Plot) = _series_defaults # in args.jl
|
||||
|
||||
+13
-7
@@ -71,8 +71,9 @@ const POTENTIAL_VECTOR_ARGUMENTS = [
|
||||
:marker_z,
|
||||
:markerstrokecolor,
|
||||
:markerstrokealpha,
|
||||
:xerror,
|
||||
:yerror,
|
||||
:yerror,
|
||||
:zerror,
|
||||
:series_annotations,
|
||||
:fillrange,
|
||||
]
|
||||
@@ -459,7 +460,7 @@ end
|
||||
@deps plots_heatmap shape
|
||||
is_3d(::Type{Val{:plots_heatmap}}) = true
|
||||
RecipesPipeline.is_surface(::Type{Val{:plots_heatmap}}) = true
|
||||
|
||||
RecipesPipeline.is_surface(::Type{Val{:hexbin}}) = true
|
||||
# ---------------------------------------------------------------------------
|
||||
# Histograms
|
||||
|
||||
@@ -537,14 +538,19 @@ end
|
||||
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
||||
edge, weights, xscale, yscale, baseline =
|
||||
_preprocess_binlike(plotattributes, x, y)
|
||||
xerror := diff(edge) / 2
|
||||
@series begin
|
||||
x := _bin_centers(edge)
|
||||
xerror := diff(edge) / 2
|
||||
primary := false
|
||||
seriestype := :xerror
|
||||
()
|
||||
end
|
||||
x := _bin_centers(edge)
|
||||
y := weights
|
||||
seriestype := :scatter
|
||||
()
|
||||
end
|
||||
@deps scatterbins scatter
|
||||
|
||||
@deps scatterbins xerror scatter
|
||||
|
||||
function _stepbins_path(
|
||||
edge,
|
||||
@@ -1022,7 +1028,7 @@ end
|
||||
|
||||
function error_style!(plotattributes::AKW)
|
||||
plotattributes[:seriestype] = :path
|
||||
plotattributes[:linecolor] = plotattributes[:markerstrokecolor]
|
||||
plotattributes[:markercolor] = plotattributes[:markerstrokecolor]
|
||||
plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
|
||||
plotattributes[:label] = ""
|
||||
end
|
||||
@@ -1094,7 +1100,7 @@ end
|
||||
end
|
||||
()
|
||||
end
|
||||
@deps xerror path
|
||||
@deps zerror path
|
||||
|
||||
|
||||
# TODO: move quiver to PlotRecipes
|
||||
|
||||
+26
-20
@@ -75,7 +75,11 @@ function iter_segments(series::Series)
|
||||
if series[:seriestype] in (:scatter, :scatter3d)
|
||||
return [[i] for i in eachindex(y)]
|
||||
else
|
||||
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
||||
if any(isnan,y)
|
||||
return [iter_segments(y)...]
|
||||
else
|
||||
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
||||
end
|
||||
end
|
||||
else
|
||||
segs = UnitRange{Int}[]
|
||||
@@ -410,44 +414,46 @@ xlims(sp_idx::Int = 1) = xlims(current(), sp_idx)
|
||||
ylims(sp_idx::Int = 1) = ylims(current(), sp_idx)
|
||||
zlims(sp_idx::Int = 1) = zlims(current(), sp_idx)
|
||||
|
||||
# These functions return an operator for use in `get_clims(::Seres, op)`
|
||||
process_clims(lims::NTuple{2,<:Number}) = (zlims -> ifelse.(isfinite.(lims), lims, zlims)) ∘ ignorenan_extrema
|
||||
process_clims(s::Union{Symbol,Nothing,Missing}) = ignorenan_extrema
|
||||
# don't specialize on ::Function otherwise python functions won't work
|
||||
process_clims(f) = f
|
||||
|
||||
function get_clims(sp::Subplot)
|
||||
function get_clims(sp::Subplot, op=process_clims(sp[:clims]))
|
||||
zmin, zmax = Inf, -Inf
|
||||
for series in series_list(sp)
|
||||
if series[:colorbar_entry]
|
||||
zmin, zmax = _update_clims(zmin, zmax, get_clims(series)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, get_clims(series, op)...)
|
||||
end
|
||||
end
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
end
|
||||
|
||||
function get_clims(sp::Subplot, series::Series)
|
||||
function get_clims(sp::Subplot, series::Series, op=process_clims(sp[:clims]))
|
||||
zmin, zmax = if series[:colorbar_entry]
|
||||
get_clims(sp)
|
||||
get_clims(sp, op)
|
||||
else
|
||||
get_clims(series)
|
||||
end
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
get_clims(series, op)
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
end
|
||||
|
||||
function get_clims(series::Series)
|
||||
"""
|
||||
get_clims(::Series, op=Plots.ignorenan_extrema)
|
||||
|
||||
Finds the limits for the colorbar by taking the "z-values" for the series and passing them into `op`,
|
||||
which must return the tuple `(zmin, zmax)`. The default op is the extrema of the finite
|
||||
values of the input.
|
||||
"""
|
||||
function get_clims(series::Series, op=ignorenan_extrema)
|
||||
zmin, zmax = Inf, -Inf
|
||||
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface)
|
||||
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface, :hexbin)
|
||||
for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
|
||||
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real})
|
||||
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, op(vals.surf)...)
|
||||
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
|
||||
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, op(vals)...)
|
||||
end
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user