Compare commits

...
50 Commits
Author SHA1 Message Date
Anshul SinghviandGitHub 61b5568e5e really fix saving 2020-05-13 18:59:45 +05:30
Anshul SinghviandGitHub d337c4edae fix saving 2020-05-13 18:44:12 +05:30
Anshul SinghviandGitHub 8db2de64d5 forgot a do 2020-05-13 18:17:19 +05:30
Anshul SinghviandGitHub 67a2a0f8d7 Update gr.jl 2020-05-13 14:51:37 +05:30
jamblejoeandGitHub 238aca6a78 added description for argument legendtitle (#2697) 2020-05-12 18:32:21 +02:00
Simon ChristandGitHub 1f039b3adc bump version [skip ci] 2020-05-11 16:52:42 +02:00
Simon ChristandGitHub 219465d599 fix contours (#2692)
* fix 2d-contour

* fix filled contours (colorbar is off)

* activate fixed examples
2020-05-11 16:52:00 +02:00
Simon ChristandGitHub 1963cee94a fix it again (#2694) 2020-05-11 16:51:38 +02:00
Simon ChristandGitHub ae43e05f6f bump version [skip ci] 2020-05-09 13:10:32 +02:00
Simon ChristandGitHub 5cd2ba7296 Delete tmpplotsave.hdf5 2020-05-09 13:09:53 +02:00
isentropicandGitHub 4a00018f25 pyplot hexbin (#2679)
* pyplot hexbin

* pyplot hexbin changes
2020-05-09 13:07:32 +02:00
Simon ChristandGitHub 32c725e770 error bars behind in scatterplots (#2677)
* errors behind for :scatter

* fix plots with no seriestype
2020-05-09 13:05:15 +02:00
Daniel SchwabenederandGitHub 4e2ee35125 Merge pull request #2684 from daschw/gr-ticklabel
fix numeric gr ticklabels
2020-05-08 10:15:04 +02:00
Daniel Schwabeneder 35b0751714 fix numeric gr ticklabels 2020-05-07 18:17:47 +02:00
Zh 28ebc0ccd8 pyplot hexbin 2020-05-07 03:02:00 +09:00
Simon ChristandGitHub 3d693d88e0 Change color handling of error recipes (#2675)
* fix iteration of segments

* fix error vector arg detection

* change color handling of recipes
2020-05-06 18:21:54 +02:00
Daniel SchwabenederandGitHub 6ddf31d465 Merge pull request #2673 from komi1230/master
Removed arrow3d from gr.jl in backends/
2020-05-05 20:50:40 +02:00
Yusuke Kominami 5c1ea707ca removed unnecessary args 2020-05-06 01:24:20 +09:00
Yusuke Kominami a6669f89a0 removed arrow3d 2020-05-05 23:18:03 +09:00
Simon ChristandGitHub 2a2d509c36 Version bump
[skip ci]
2020-05-05 10:26:56 +02:00
isentropicandGitHub fd4efb3f33 PyPlot: z-axis guidefontrotation only works for short labels Fix 2641 (#2667) 2020-05-05 10:26:01 +02:00
isentropicandGitHub e90ab0b898 PyPlot fix contour labels (#2668) 2020-05-05 10:25:12 +02:00
Simon ChristandGitHub 44367c54da fix quiver (#2670) 2020-05-05 10:24:15 +02:00
Daniel SchwabenederandGitHub 3273a65889 Merge pull request #2657 from mileslucas/climsfunc
allow passing a function to `clims`
2020-05-05 08:18:07 +02:00
Miles LucasandGitHub 0aa606d835 fix typo in get_clims function docstring 2020-05-04 11:05:53 -10:00
Simon ChristandGitHub 40848e7432 fix error recipes (#2665)
* fix scatterbins

* fix zerror
2020-05-04 18:16:29 +02:00
Michael Krabbe BorregaardandGitHub fe4cc4d58c update patch version 2020-05-04 18:12:20 +02:00
Daniel SchwabenederandGitHub 56f90ffaf3 Merge pull request #2663 from dietercastel/webm
Added webm support for animations.
2020-05-03 19:28:49 +02:00
Daniel SchwabenederandGitHub dfb556339f Merge pull request #2662 from daschw/plotarea
GR size fixes
2020-05-03 15:54:56 +02:00
Daniel Schwabeneder 61f5a7f437 fix extra_kwargs docs string 2020-05-03 15:39:51 +02:00
Daniel Schwabeneder 3be9b8d076 fix outer legend font size 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder 2a138dee40 fix get_size and get_thickness_scaling for series 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder 712ef74b81 remove const _gr_plot_size, _gr_point_mult and _gr_thickness_scaling 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder ba8ca424cf remove gloabal viewport_plotarea in gr 2020-05-03 15:37:12 +02:00
Dieter Castel c6784a779b Added webm support for animations. 2020-05-03 15:31:55 +02:00
Simon ChristandGitHub d667cb7e57 update documentation of extra_kwargs 2020-05-03 15:10:34 +02:00
Miles Lucas 10a5c2ed1d fix bug with Tuple clims and fix typos 2020-05-01 00:10:27 -10:00
Miles Lucas 8cce78c890 fix typos 2020-04-30 23:38:52 -10:00
Miles Lucas 294ade8aad refactor get_clims calls to use operators 2020-04-30 23:32:30 -10:00
Miles Lucas a59e8411c9 update clims arg description 2020-04-30 22:30:03 -10:00
Daniel SchwabenederandGitHub d973f437ef Merge pull request #2653 from daschw/segments
make segments for vectors of markersize and markerstrokewidth
2020-04-30 14:05:45 +02:00
Josef Heinen d5ce2c1431 Merge remote-tracking branch 'upstream/master' 2020-04-30 13:25:06 +02:00
Josef Heinen 834e2a99e3 add actual GR version 2020-04-30 13:18:32 +02:00
Daniel SchwabenederandGitHub f8e9e33347 Merge pull request #2650 from daschw/pyplot
pyplot legend marker fixes
2020-04-30 13:17:53 +02:00
Daniel Schwabeneder a0c7781296 make segments for vectors of markersize and markerstrokewidth 2020-04-30 13:16:33 +02:00
Daniel Schwabeneder 2ea998983d fix legend marker for vector of markersizes [skip ci] 2020-04-30 10:04:04 +02:00
Daniel Schwabeneder e44b220b84 fix legend marker linewidth for steppre and steppost [skip ci] 2020-04-30 10:03:21 +02:00
Daniel Schwabeneder 756cccb114 remove lines in legend markers for scatter plots in pyplot [skip ci] 2020-04-30 09:46:13 +02:00
Simon ChristandGitHub af9982b804 minor bump [skip ci] 2020-04-29 11:47:54 +02:00
1b946a18d2 passing of extra keywords to pgfplotsx (#2200)
* transfer commit

* extra_kwargs gets populated

* make extra_kwargs a series kw.

* turn extra_kwargs into Dict of Dicts

* pass to pgfplotsx-backend

* add test

* change to dict

* it even works

* cleanup

* undo pgfplots changes

* all of them

* fix tests

* add pgfplotsx tests and special handling of :add

Co-authored-by: Simon Christ <Simon.Christ@mpikg.mpg.de>
2020-04-29 11:43:57 +02:00
14 changed files with 577 additions and 393 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.1.4"
version = "1.2.4"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@@ -35,7 +35,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
Contour = "0.5"
FFMPEG = "0.2, 0.3"
FixedPointNumbers = "0.6, 0.7, 0.8"
GR = "0.46, 0.47, 0.48"
GR = "0.46, 0.47, 0.48, 0.49"
GeometryTypes = "0.7, 0.8"
JSON = "0.21"
Measures = "0.3"
+1
View File
@@ -108,6 +108,7 @@ export
gif,
mov,
mp4,
webm,
animate,
@animate,
@gif,
+4 -2
View File
@@ -24,6 +24,7 @@ end
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov")
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4")
webmfn() = (isijulia() ? "tmp.webm" : tempname()*".webm")
mutable struct FrameIterator
itr
@@ -63,6 +64,7 @@ file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim, fn, false; kw...)
webm(anim::Animation, fn = webmfn(); kw...) = buildanimation(anim, fn, false; kw...)
ffmpeg_framerate(fps) = "$fps"
ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)"
@@ -110,8 +112,8 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
ext = file_extension(agif.filename)
if ext == "gif"
html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />"
elseif ext in ("mov", "mp4")
mimetype = ext == "mov" ? "video/quicktime" : "video/mp4"
elseif ext in ("mov", "mp4","webm")
mimetype = ext == "mov" ? "video/quicktime" : "video/$ext"
html = "<video controls><source src=\"data:$mimetype;base64," *
base64encode(read(agif.filename)) *
"\" type = \"$mimetype\"></video>"
+3 -2
View File
@@ -70,7 +70,7 @@ const _arg_desc = KW(
:dpi => "Number. Dots Per Inch of output figures",
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
:extra_kwargs => "Either one of (`:plot`, `:subplot`, `:series`) to specify for which element extra keyword args are collected or a KW (Dict{Symbol,Any}) to pass a map of extra keyword args which may be specific to a backend. Default: `:series`.\n Example: `pgfplotsx(); scatter(1:5, extra_kwargs=Dict(:subplot=>Dict(\"axis line shift\" => \"10pt\"))`",
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
:warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes",
@@ -97,6 +97,7 @@ const _arg_desc = KW(
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
:legendtitle => "String. Legend title.",
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
:legendtitlefontsize => "Integer. Font pointsize the legend title.",
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
@@ -104,7 +105,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.",
+14 -8
View File
@@ -281,6 +281,7 @@ const _series_defaults = KW(
# one logical series to be broken up (path and markers, for example)
:hover => nothing, # text to display when hovering over the data points
:stride => (1,1), # array stride for wireframe/surface, the first element is the row stride and the second is the column stride.
:extra_kwargs => Dict()
)
@@ -292,7 +293,7 @@ const _plot_defaults = KW(
:fontfamily => "sans-serif",
:size => (600,400),
:pos => (0,0),
:window_title => "Plots.jl",
:window_title => "Plots.jl",
:show => false,
:layout => 1,
:link => :none,
@@ -304,8 +305,9 @@ const _plot_defaults = KW(
:dpi => DPI, # dots per inch for images, etc
:thickness_scaling => 1,
:display_type => :auto,
:extra_kwargs => KW(),
:warn_on_unsupported => true,
:extra_plot_kwargs => Dict(),
:extra_kwargs => :series, # directs collection of extra_kwargs
)
@@ -354,6 +356,7 @@ const _subplot_defaults = KW(
:colorbar_title => "",
:framestyle => :axes,
:camera => (30,30),
:extra_kwargs => Dict()
)
const _axis_defaults = KW(
@@ -656,7 +659,7 @@ function default(k::Symbol)
return _axis_defaults_byletter[letter][key]
end
k == :letter && return k # for type recipe processing
k in _suppress_warnings || error("Unknown key: ", k)
return missing
end
function default(k::Symbol, v)
@@ -1121,26 +1124,29 @@ const _already_warned = Dict{Symbol,Set{Symbol}}()
const _to_warn = Set{Symbol}()
function warn_on_unsupported_args(pkg::AbstractBackend, plotattributes)
if !get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
return
end
empty!(_to_warn)
bend = backend_name(pkg)
already_warned = get!(_already_warned, bend, Set{Symbol}())
extra_kwargs = Dict{Symbol,Any}()
for k in keys(plotattributes)
is_attr_supported(pkg, k) && continue
k in _suppress_warnings && continue
if plotattributes[k] != default(k)
default_value = default(k)
if ismissing(default_value)
extra_kwargs[k] = pop_kw!(plotattributes, k)
elseif plotattributes[k] != default(k)
k in already_warned || push!(_to_warn, k)
end
end
if !isempty(_to_warn)
if !isempty(_to_warn) &&
!get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
for k in sort(collect(_to_warn))
push!(already_warned, k)
@warn("Keyword argument $k not supported with $pkg. Choose from: $(supported_attrs(pkg))")
end
end
return extra_kwargs
end
# _markershape_supported(pkg::AbstractBackend, shape::Symbol) = shape in supported_markers(pkg)
+1
View File
@@ -828,6 +828,7 @@ const _pgfplotsx_seriestype = [
:heatmap,
:contour,
:contour3d,
:quiver,
:shape,
:steppre,
:stepmid,
+378 -320
View File
File diff suppressed because it is too large Load Diff
+36 -19
View File
@@ -86,7 +86,16 @@ end
function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
if !pgfx_plot.is_created || pgfx_plot.was_shown
pgfx_sanitize_plot!(plt)
the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options())
# extract extra kwargs
extra_plot_opt = plt[:extra_plot_kwargs]
extra_plot = nothing
if haskey(extra_plot_opt, :add)
extra_plot = wraptuple(pop!(extra_plot_opt,:add))
end
the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options(extra_plot_opt...))
if extra_plot !== nothing
push!(the_plot, extra_plot...)
end
bgc = plt.attr[:background_color_outside] == :match ?
plt.attr[:background_color] : plt.attr[:background_color_outside]
if bgc isa Colors.Colorant
@@ -243,7 +252,15 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
else
PGFPlotsX.Axis
end
axis = axisf(axis_opt)
extra_sp_opt = sp[:extra_kwargs]
extra_sp = nothing
if haskey(extra_sp_opt, :add)
extra_sp = wraptuple(pop!(extra_sp_opt,:add))
end
axis = axisf(merge(axis_opt, PGFPlotsX.Options(extra_sp_opt...)))
if extra_sp !== nothing
push!(axis, extra_sp...)
end
if sp[:legendtitle] !== nothing
push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing))
push!(
@@ -265,7 +282,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
"color" => single_color(opt[:linecolor]),
"name path" => string(series_id),
)
if RecipesPipeline.is3d(series) || st == :heatmap
extra_series_opt = series[:extra_kwargs]
extra_series = nothing
if haskey(extra_series_opt, :add)
extra_series = wraptuple(pop!(extra_series_opt,:add))
end
series_opt = merge(series_opt, PGFPlotsX.Options(extra_series_opt...))
if RecipesPipeline.is3d(series) || st in (:heatmap, :contour)
series_func = PGFPlotsX.Plot3
else
series_func = PGFPlotsX.Plot
@@ -274,7 +297,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
!isfilledcontour(series) && series[:ribbon] === nothing
push!(series_opt, "area legend" => nothing)
end
if st == :heatmap
if st in (:heatmap, :contour)
push!(axis.options, "view" => "{0}{90}")
end
# treat segments
@@ -319,12 +342,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
end
segment_opt = merge(segment_opt, pgfx_marker(opt, i))
end
if st == :shape || isfilledcontour(series)
if st == :shape
segment_opt = merge(segment_opt, pgfx_fillstyle(opt, i))
end
# add fillrange
if sf !== nothing &&
!isfilledcontour(series) && series[:ribbon] === nothing
!isfilledcontour(series) &&
series[:ribbon] === nothing
if sf isa Number || sf isa AVec
pgfx_fillrange_series!(
axis,
@@ -344,6 +368,9 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
pgfx_series_coordinates!(sp, series, segment_opt, opt, rng)
segment_plot =
series_func(merge(series_opt, segment_opt), coordinates)
if extra_series !== nothing
push!(segment_plot, extra_series...)
end
push!(axis, segment_plot)
# fill between functions
if sf isa Tuple && series[:ribbon] === nothing
@@ -570,8 +597,8 @@ function pgfx_series_coordinates!(
xs, ys, zs = collect(args)
push!(
segment_opt,
"contour filled" => PGFPlotsX.Options("labels" => opt[:contour_labels]),
"point meta" => "explicit",
"contour filled" => PGFPlotsX.Options(), # labels not supported
"patch type" => "bilinear",
"shader" => "flat",
)
if opt[:levels] isa Number
@@ -580,17 +607,7 @@ function pgfx_series_coordinates!(
push!(segment_opt["contour filled"], "levels" => opt[:levels])
end
cs = join(
[
join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") for (i, y) in enumerate(ys)
],
"\n\n",
)
"""
coordinates {
$cs
};
"""
PGFPlotsX.Coordinates(args...)
end
##
pgfx_get_linestyle(k) = get(
+15 -8
View File
@@ -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)
@@ -1307,16 +1313,17 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(series[:seriestype], get_linestyle(series))
)
elseif series[:seriestype] in (:path, :straightline, :scatter)
elseif series[:seriestype] in (:path, :straightline, :scatter, :steppre, :steppost)
hasline = get_linewidth(series) > 0
PyPlot.plt."Line2D"((0,1),(0,0),
color = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
linewidth = py_thickness_scale(plt, sp[:legendfontsize] / 8),
linewidth = py_thickness_scale(plt, hasline * sp[:legendfontsize] / 8),
linestyle = py_linestyle(:path, get_linestyle(series)),
marker = py_marker(_cycle(series[:markershape], 1)),
markersize = py_thickness_scale(plt, 0.8 * sp[:legendfontsize]),
markeredgecolor = py_color(single_color(get_markerstrokecolor(series)), get_markerstrokealpha(series)),
markerfacecolor = py_color(single_color(get_markercolor(series, clims)), get_markeralpha(series)),
markeredgewidth = py_thickness_scale(plt, 0.8 * series[:markerstrokewidth] * sp[:legendfontsize] / series[:markersize]) # retain the markersize/markerstroke ratio from the markers on the plot
markeredgewidth = py_thickness_scale(plt, 0.8 * get_markerstrokewidth(series) * sp[:legendfontsize] / first(series[:markersize])) # retain the markersize/markerstroke ratio from the markers on the plot
)
else
series[:serieshandle][1]
-2
View File
@@ -998,13 +998,11 @@ _backend_skips = Dict(
6, # images
10, # histogram2d
16, # pgfplots thinks the upper panel is too small
22, # contourf
25, # @df
30, # @df
31, # animation
32, # spy
38, # histogram2d
45, # wireframe
],
)
+30 -1
View File
@@ -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, :path) in (:xerror, :yerror, :zerror), kw_list)
for ind in err_inds
if get(kw_list[ind-1],:seriestype,:path) == :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
@@ -341,7 +357,20 @@ function _expand_subplot_extrema(sp::Subplot, plotattributes::AKW, st::Symbol)
end
function _add_the_series(plt, sp, plotattributes)
warn_on_unsupported_args(plt.backend, plotattributes)
extra_kwargs = warn_on_unsupported_args(plt.backend, plotattributes)
if (kw = plt[:extra_kwargs]) isa AbstractDict
plt[:extra_plot_kwargs] = get(kw,:plot,KW())
sp[:extra_kwargs] = get(kw,:subplot, KW())
plotattributes[:extra_kwargs] = get(kw,:series,KW())
elseif plt[:extra_kwargs] == :plot
plt[:extra_plot_kwargs] = extra_kwargs
elseif plt[:extra_kwargs] == :subplot
sp[:extra_kwargs] = extra_kwargs
elseif plt[:extra_kwargs] == :series
plotattributes[:extra_kwargs] = extra_kwargs
else
ArgumentError("Unsupported type for extra keyword arguments")
end
warn_on_unsupported(plt.backend, plotattributes)
series = Series(plotattributes)
push!(plt.series_list, series)
+13 -7
View File
@@ -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
+60 -22
View File
@@ -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)
@@ -481,7 +487,7 @@ end
hascolorbar(series::Series) = colorbar_style(series) !== nothing
hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
iscontour(series::Series) = series[:seriestype] == :contour
iscontour(series::Series) = series[:seriestype] in (:contour, :contour3d)
isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing
function contour_levels(series::Series, clims)
@@ -587,7 +593,28 @@ function has_attribute_segments(series::Series)
end
series[:seriestype] == :shape && return false
# ... else we check relevant attributes if they have multiple inputs
return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :linestyle, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z))
return any(
(typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1)
for
attr in [
:seriescolor,
:seriesalpha,
:linecolor,
:linealpha,
:linewidth,
:linestyle,
:fillcolor,
:fillalpha,
:markercolor,
:markeralpha,
:markersize,
:markerstrokecolor,
:markerstrokealpha,
:markerstrokewidth,
]
) || any(
typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z)
)
end
function get_aspect_ratio(sp)
@@ -603,6 +630,17 @@ function get_aspect_ratio(sp)
return aspect_ratio
end
get_size(kw) = get(kw, :size, default(:size))
get_size(plt::Plot) = get_size(plt.attr)
get_size(sp::Subplot) = get_size(sp.plt)
get_size(series::Series) = get_size(series.plotattributes[:subplot])
get_thickness_scaling(kw) = get(kw, :thickness_scaling, default(:thickness_scaling))
get_thickness_scaling(plt::Plot) = get_thickness_scaling(plt.attr)
get_thickness_scaling(sp::Subplot) = get_thickness_scaling(sp.plt)
get_thickness_scaling(series::Series) =
get_thickness_scaling(series.plotattributes[:subplot])
# ---------------------------------------------------------------
makekw(; kw...) = KW(kw)
+20
View File
@@ -326,3 +326,23 @@ end
# end
end # testset
end # testset
@testset "Extra kwargs" begin
pl = plot(1:5, test = "me")
@test pl[1][1].plotattributes[:extra_kwargs][:test] == "me"
pl = plot(1:5, test = "me", extra_kwargs = :subplot)
@test pl[1].attr[:extra_kwargs][:test] == "me"
pl = plot(1:5, test = "me", extra_kwargs = :plot)
@test pl.attr[:extra_plot_kwargs][:test] == "me"
pl = plot(1:5, extra_kwargs = Dict(:plot => Dict(:test => "me"), :series => Dict(:and => "me too")))
@test pl.attr[:extra_plot_kwargs][:test] == "me"
@test pl[1][1].plotattributes[:extra_kwargs][:and] == "me too"
pl = plot(
plot(1:5, title="Line"),
scatter(1:5, title="Scatter", extra_kwargs=Dict(:subplot=>Dict("axis line shift" => "10pt")))
)
Plots._update_plot_object(pl)
axes = Plots.pgfx_axes(pl.o)
@test !haskey(axes[1].options.dict, "axis line shift")
@test haskey(axes[2].options.dict, "axis line shift")
end # testset