From b3db49b4ae1b036fb08de6ca50b24c5907139b6e Mon Sep 17 00:00:00 2001 From: Jonathan Anderson Date: Tue, 18 Apr 2017 10:39:50 -0500 Subject: [PATCH 001/230] Update gr.jl in v0.6 so inline plots work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I wanted to switch from using GR directly to using Plots, but the inline plots were not working for me. The following change is sufficient to generate inline plots in iterm for me. See the method in GR.jl: https://github.com/jheinen/GR.jl/blob/0f167b2be921a0014c405f760a1e1bc22b222751/src/GR.jl#L3014 julia> versioninfo() Julia Version 0.6.0-pre.beta.187 Commit 55c97fb* (2017-04-17 23:06 UTC) Platform Info: OS: Linux (x86_64-redhat-linux) CPU: Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz WORD_SIZE: 64 BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell) LAPACK: libopenblas64_ LIBM: libopenlibm LLVM: libLLVM-3.9.1 (ORCJIT, haswell) julia> using TerminalExtensions julia> using Plots julia> gr(display_type=:inline); julia> z=[sin(sqrt(x^2+y^2)) for x in linspace(-2π,2π,50), y in linspace(-2π,2π,50)]; julia> contour(z) --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b092edd7..4fc31a90 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1101,7 +1101,7 @@ function _display(plt::Plot{GRBackend}) ENV["GKS_FILEPATH"] = filepath gr_display(plt) GR.emergencyclosegks() - content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(readbytes, filepath)), "\a") + content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(read, filepath)), "\a") println(content) rm(filepath) else From 1a67ca897c6c734c125138567c5250735526e9e2 Mon Sep 17 00:00:00 2001 From: Oliver Evans Date: Wed, 21 Mar 2018 12:25:06 -0400 Subject: [PATCH 002/230] Remove cache-busting from gif animation. Should be done by the frontend. --- src/animation.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/animation.jl b/src/animation.jl index 6c1f880f..6746262b 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -93,13 +93,13 @@ end -# write out html to view the gif... note the rand call which is a hack so the image doesn't get cached +# write out html to view the gif function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) ext = file_extension(agif.filename) write(io, if ext == "gif" - "\" />" + "" elseif ext in ("mov", "mp4") - "" + "" else error("Cannot show animation with extension $ext: $agif") end) From a731ef6e2d6b745d19b660346ce9d1fd0f753e0e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 2 Sep 2018 22:28:34 +0200 Subject: [PATCH 003/230] plotlyjs, pyplot and test fixes --- src/backends.jl | 22 +++++++--------- src/backends/plotlyjs.jl | 5 +++- src/backends/pyplot.jl | 2 +- test/add_packages.jl | 13 +++++++++- test/imgcomp.jl | 2 +- test/runtests.jl | 56 +++++++++++++++++++++------------------- 6 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 6a5dea31..55c37cdf 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -347,16 +347,6 @@ function _initialize_backend(::GLVisualizeBackend; kw...) end end -# ------------------------------------------------------------------------------ -# hdf5 - -function _initialize_backend(::HDF5Backend) - @eval Main begin - import HDF5 - export HDF5 - end -end - # ------------------------------------------------------------------------------ # PGFPLOTS @@ -371,11 +361,19 @@ end # ------------------------------------------------------------------------------ # plotlyjs +function _initialize_backend(pkg::PlotlyJSBackend) + sym = backend_package_name(pkg) + @eval Main begin + import PlotlyJS, ORCA + export PlotlyJS + end +end + function add_backend_string(::PlotlyJSBackend) """ using Pkg - Pkg.add("PlotlyJS") - Pkg.add("Rsvg") + Pkg.add(["PlotlyJS", "Blink"]) + Pkg.add(PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master")) import Blink Blink.AtomShell.install() """ diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 98e626c1..6e06ce71 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -12,7 +12,10 @@ const _plotlyjs_scale = _plotly_scale function _create_backend_figure(plt::Plot{PlotlyJSBackend}) if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot) - PlotlyJS.SyncPlot(PlotlyJS.Plot(), current().o.view) + PlotlyJS.SyncPlot(PlotlyJS.Plot(), + events = current().o.events, + options = current().o.options, + ) else PlotlyJS.plot() end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index f6fc6ee4..4d171847 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1061,7 +1061,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis) # don't show the 0 tick label for the origin framestyle if sp[:framestyle] == :origin && length(ticks) > 1 - ticks[2][ticks[1] .== 0] = "" + ticks[2][ticks[1] .== 0] .= "" end axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in") diff --git a/test/add_packages.jl b/test/add_packages.jl index 260707d3..1b143c46 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -4,7 +4,6 @@ using Pkg # ENV["PYTHON"] = "" to_add = [ - PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"), # PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"), PackageSpec(name="PlotUtils", rev="master"), PackageSpec(name="RecipesBase", rev="master"), @@ -17,12 +16,24 @@ to_add = [ ] if isinteractive() + Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) append!(to_add, [ PackageSpec(name="FileIO"), PackageSpec(name="ImageMagick"), PackageSpec(name="UnicodePlots"), PackageSpec(name="VisualRegressionTests"), + PackageSpec(name="Gtk"), + # PlotlyJS: + # PackageSpec(name="PlotlyJS", rev="master"), + # PackageSpec(name="Blink"), + # PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + # PyPlot: + # PackageSpec(name="PyPlot"), + # PackageSpec(name="PyCall"), + # PackageSpec(name="LaTeXStrings"), ]) +else + push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) end Pkg.add(to_add) diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 1145f272..8d289f55 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -29,7 +29,7 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) -const _current_plots_version = v"0.17.4" +const _current_plots_version = v"0.20.1" function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) diff --git a/test/runtests.jl b/test/runtests.jl index 543b8ea3..43ffdac4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,40 +17,42 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end - -#@testset "PyPlot" begin -# @test pyplot() == Plots.PyPlotBackend() -# @test backend() == Plots.PyPlotBackend() +# @static if isinteractive() +# @testset "PyPlot" begin +# @test pyplot() == Plots.PyPlotBackend() +# @test backend() == Plots.PyPlotBackend() # -# image_comparison_facts(:pyplot, tol=img_tol) -#end +# image_comparison_facts(:pyplot, tol=img_tol, skip = [25, 30]) +# end +# end -@testset "UnicodePlots" begin - @test unicodeplots() == Plots.UnicodePlotsBackend() - @test backend() == Plots.UnicodePlotsBackend() - - # lets just make sure it runs without error - @test isa(plot(rand(10)), Plots.Plot) == true -end +# @testset "UnicodePlots" begin +# @test unicodeplots() == Plots.UnicodePlotsBackend() +# @test backend() == Plots.UnicodePlotsBackend() +# +# # lets just make sure it runs without error +# @test isa(plot(rand(10)), Plots.Plot) == true +# end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) -# @testset "PlotlyJS" begin -# @test plotlyjs() == Plots.PlotlyJSBackend() -# @test backend() == Plots.PlotlyJSBackend() -# -# if Sys.islinux() && isinteractive() -# image_comparison_facts(:plotlyjs, -# skip=[ -# 2, # animation (skipped for speed) -# 27, # (polar plots) takes very long / not working -# 31, # animation (skipped for speed) -# ], -# tol=img_tol) -# end -# end +@static if isinteractive() + @testset "PlotlyJS" begin + @test plotlyjs() == Plots.PlotlyJSBackend() + @test backend() == Plots.PlotlyJSBackend() + image_comparison_facts(:plotlyjs, + skip=[ + 2, # animation (skipped for speed) + 25, + 27, # (polar plots) takes very long / not working + 30, + 31, # animation (skipped for speed) + ], + tol=img_tol) + end +end # InspectDR returns that error on travis: # ERROR: LoadError: InitError: Cannot open display: From 1bbe800dcd6f9a423459fc84ebd94b996f8f7826 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 3 Sep 2018 17:30:50 +0200 Subject: [PATCH 004/230] move _current_plots_version from PlotDocs to Plots --- src/Plots.jl | 2 ++ test/imgcomp.jl | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Plots.jl b/src/Plots.jl index f6e4b19f..16fe38c6 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,5 +1,7 @@ module Plots +_current_plots_version = v"0.20.1" + using Reexport import StaticArrays diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 8d289f55..526d695e 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -29,7 +29,7 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) -const _current_plots_version = v"0.20.1" +import Plots._current_plots_version function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) From f0f90d87afe51cf2ca74b7a5728d00cc31f07639 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 4 Sep 2018 19:08:48 +0200 Subject: [PATCH 005/230] move supported backend attr to backends.jl --- src/backends.jl | 389 ++++++++++++++++++++++++++++++++++- src/backends/glvisualize.jl | 48 +---- src/backends/gr.jl | 59 ------ src/backends/hdf5.jl | 41 ---- src/backends/inspectdr.jl | 53 ----- src/backends/pgfplots.jl | 41 ---- src/backends/plotly.jl | 54 ----- src/backends/plotlyjs.jl | 6 - src/backends/pyplot.jl | 49 ----- src/backends/unicodeplots.jl | 22 -- src/examples.jl | 8 + test/add_packages.jl | 12 +- test/runtests.jl | 32 +-- 13 files changed, 419 insertions(+), 395 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 55c37cdf..c6ecaf2a 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -330,6 +330,126 @@ function add_backend_string(pkg::AbstractBackend) """ end +# ------------------------------------------------------------------------------ +# gr + +const _gr_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, + :layout, + :title, :window_title, + :guide, :lims, :ticks, :scale, :flip, + :match_dimensions, + :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, + :titlefontrotation, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign, + :legendfontrotation, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign, + :tickfontrotation, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, + :guidefontrotation, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legendtitle, :colorbar, :colorbar_title, + :fill_z, :line_z, :marker_z, :levels, + :ribbon, :quiver, + :orientation, + :overwrite_figure, + :polar, + :aspect_ratio, + :normalize, :weights, + :inset_subplots, + :bar_width, + :arrow, + :framestyle, + :tick_direction, + :camera, + :contour_labels, +]) +const _gr_seriestype = [ + :path, :scatter, :straightline, + :heatmap, :pie, :image, + :contour, :path3d, :scatter3d, :surface, :wireframe, + :shape +] +const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] +const _gr_marker = _allMarkers +const _gr_scale = [:identity, :log10] +is_marker_supported(::GRBackend, shape::Shape) = true + +function add_backend_string(::GRBackend) + """ + Pkg.add("GR") + Pkg.build("GR") + """ +end + +# ------------------------------------------------------------------------------ +# plotly + +const _plotly_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_legend, :foreground_color_guide, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :foreground_color_title, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, + :fillrange, :fillcolor, :fillalpha, + :bins, + :title, :title_location, + :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, + :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :gridalpha, :gridlinewidth, + :legend, :colorbar, :colorbar_title, + :marker_z, :fill_z, :line_z, :levels, + :ribbon, :quiver, + :orientation, + # :overwrite_figure, + :polar, + :normalize, :weights, + # :contours, + :aspect_ratio, + :hover, + :inset_subplots, + :bar_width, + :clims, + :framestyle, + :tick_direction, + :camera, + :contour_labels, + ]) + +const _plotly_seriestype = [ + :path, :scatter, :pie, :heatmap, + :contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl, + :straightline +] +const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot] +const _plotly_marker = [ + :none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, + :cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline +] +const _plotly_scale = [:identity, :log10] + # ------------------------------------------------------------------------------ # glvisualize @@ -347,8 +467,56 @@ function _initialize_backend(::GLVisualizeBackend; kw...) end end +const _glvisualize_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :titlefontsize, :titlefontcolor, + :legendfontsize, :legendfontcolor, + :tickfontsize, + :guidefontsize, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :colorbar, + :marker_z, + :line_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + #:polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :hover, + :framestyle, + :tick_direction, +]) +const _glvisualize_seriestype = [ + :path, :shape, :straightline, + :scatter, :hexbin, + :bar, :boxplot, + :heatmap, :image, :volume, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe +] +const _glvisualize_style = [:auto, :solid, :dash, :dot, :dashdot] +const _glvisualize_marker = _allMarkers +const _glvisualize_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ -# PGFPLOTS +# pgfplots function add_backend_string(::PGFPlotsBackend) """ @@ -358,6 +526,46 @@ function add_backend_string(::PGFPlotsBackend) """ end +const _pgfplots_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, + :background_color_inside, + # :background_color_outside, + # :foreground_color_legend, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, + :fillrange, :fillcolor, :fillalpha, + :bins, + # :bar_width, :bar_edges, + :title, + # :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :legend, + :colorbar, :colorbar_title, + :fill_z, :line_z, :marker_z, :levels, + # :ribbon, :quiver, :arrow, + # :orientation, + # :overwrite_figure, + :polar, + # :normalize, :weights, :contours, + :aspect_ratio, + # :match_dimensions, + :tick_direction, + :framestyle, + :camera, + :contour_labels, + ]) +const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] +const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] +const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) +const _pgfplots_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ # plotlyjs @@ -379,6 +587,12 @@ function add_backend_string(::PlotlyJSBackend) """ end +const _plotlyjs_attr = _plotly_attr +const _plotlyjs_seriestype = _plotly_seriestype +const _plotlyjs_style = _plotly_style +const _plotlyjs_marker = _plotly_marker +const _plotlyjs_scale = _plotly_scale + # ------------------------------------------------------------------------------ # pyplot @@ -407,8 +621,59 @@ function add_backend_string(::PyPlotBackend) """ end +const _pyplot_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, :titlefont, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legendtitle, :colorbar, + :marker_z, :line_z, :fill_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + :polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :colorbar_title, + :stride, + :framestyle, + :tick_direction, + :camera, + :contour_labels, + ]) +const _pyplot_seriestype = [ + :path, :steppre, :steppost, :shape, :straightline, + :scatter, :hexbin, #:histogram2d, :histogram, + # :bar, + :heatmap, :pie, :image, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe + ] +const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot] +const _pyplot_marker = vcat(_allMarkers, :pixel) +const _pyplot_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ # unicodeplots + function add_backend_string(::UnicodePlotsBackend) """ using Pkg @@ -416,3 +681,125 @@ function add_backend_string(::UnicodePlotsBackend) Pkg.build("UnicodePlots") """ end + +const _unicodeplots_attr = merge_with_base_supported([ + :label, + :legend, + :seriescolor, + :seriesalpha, + :linestyle, + :markershape, + :bins, + :title, + :guide, :lims, + ]) +const _unicodeplots_seriestype = [ + :path, :scatter, :straightline, + # :bar, + :shape, + :histogram2d, + :spy +] +const _unicodeplots_style = [:auto, :solid] +const _unicodeplots_marker = [:none, :auto, :circle] +const _unicodeplots_scale = [:identity] + +# ------------------------------------------------------------------------------ +# hdf5 + +const _hdf5_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, :titlefont, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :legend, :colorbar, + :marker_z, :line_z, :fill_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + :polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :colorbar_title, + ]) +const _hdf5_seriestype = [ + :path, :steppre, :steppost, :shape, :straightline, + :scatter, :hexbin, #:histogram2d, :histogram, + # :bar, + :heatmap, :pie, :image, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe + ] +const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] +const _hdf5_marker = vcat(_allMarkers, :pixel) +const _hdf5_scale = [:identity, :ln, :log2, :log10] + +# ------------------------------------------------------------------------------ +# inspectdr + +const _inspectdr_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + # :foreground_color_grid, + :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :markerstrokestyle, #Causes warning not to have it... what is this? + :fillcolor, :fillalpha, #:fillrange, +# :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, + :window_title, + :guide, :lims, :scale, #:ticks, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, :legend, #:colorbar, +# :marker_z, +# :line_z, +# :levels, + # :ribbon, :quiver, :arrow, +# :orientation, + :overwrite_figure, + :polar, +# :normalize, :weights, +# :contours, :aspect_ratio, + :match_dimensions, +# :clims, +# :inset_subplots, + :dpi, +# :colorbar_title, + ]) +const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot] +const _inspectdr_seriestype = [ + :path, :scatter, :shape, :straightline, #, :steppre, :steppost + ] +#see: _allMarkers, _shape_keys +const _inspectdr_marker = Symbol[ + :none, :auto, + :circle, :rect, :diamond, + :cross, :xcross, + :utriangle, :dtriangle, :rtriangle, :ltriangle, + :pentagon, :hexagon, :heptagon, :octagon, + :star4, :star5, :star6, :star7, :star8, + :vline, :hline, :+, :x, +] + +const _inspectdr_scale = [:identity, :ln, :log2, :log10] diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index 72288380..72f7c74e 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -9,53 +9,7 @@ TODO * fix units in all visuals (e.g dotted lines, marker scale, surfaces) =# -const _glvisualize_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :titlefontsize, :titlefontcolor, - :legendfontsize, :legendfontcolor, - :tickfontsize, - :guidefontsize, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :colorbar, - :marker_z, - :line_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - #:polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :hover, - :framestyle, - :tick_direction, -]) -const _glvisualize_seriestype = [ - :path, :shape, :straightline, - :scatter, :hexbin, - :bar, :boxplot, - :heatmap, :image, :volume, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe -] -const _glvisualize_style = [:auto, :solid, :dash, :dot, :dashdot] -const _glvisualize_marker = _allMarkers -const _glvisualize_scale = [:identity, :ln, :log2, :log10] + slice_arg(img::Matrix{C}, idx::Int) where {C<:Colorant} = img is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 2534e5f2..891434a1 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -3,65 +3,6 @@ # significant contributions by @jheinen -const _gr_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, - :layout, - :title, :window_title, - :guide, :lims, :ticks, :scale, :flip, - :match_dimensions, - :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, - :titlefontrotation, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign, - :legendfontrotation, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign, - :tickfontrotation, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, - :guidefontrotation, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, :colorbar_title, - :fill_z, :line_z, :marker_z, :levels, - :ribbon, :quiver, - :orientation, - :overwrite_figure, - :polar, - :aspect_ratio, - :normalize, :weights, - :inset_subplots, - :bar_width, - :arrow, - :framestyle, - :tick_direction, - :camera, - :contour_labels, -]) -const _gr_seriestype = [ - :path, :scatter, :straightline, - :heatmap, :pie, :image, - :contour, :path3d, :scatter3d, :surface, :wireframe, - :shape -] -const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -const _gr_marker = _allMarkers -const _gr_scale = [:identity, :log10] -is_marker_supported(::GRBackend, shape::Shape) = true - -function add_backend_string(::GRBackend) - """ - Pkg.add("GR") - Pkg.build("GR") - """ -end - import GR export GR diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl index 28dd767d..95b83874 100644 --- a/src/backends/hdf5.jl +++ b/src/backends/hdf5.jl @@ -62,47 +62,6 @@ const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox, #== ===============================================================================# - -const _hdf5_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, :titlefont, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :legend, :colorbar, - :marker_z, :line_z, :fill_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - :polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :colorbar_title, - ]) -const _hdf5_seriestype = [ - :path, :steppre, :steppost, :shape, :straightline, - :scatter, :hexbin, #:histogram2d, :histogram, - # :bar, - :heatmap, :pie, :image, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe - ] -const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] -const _hdf5_marker = vcat(_allMarkers, :pixel) -const _hdf5_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::HDF5Backend, shape::Shape) = true if length(HDF5PLOT_MAP_TELEM2STR) < 1 diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index 5825630f..8ef26f90 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -14,59 +14,6 @@ Add in functionality to Plots.jl: =# # --------------------------------------------------------------------------- -#TODO: remove features -const _inspectdr_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - # :foreground_color_grid, - :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :markerstrokestyle, #Causes warning not to have it... what is this? - :fillcolor, :fillalpha, #:fillrange, -# :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, - :window_title, - :guide, :lims, :scale, #:ticks, :flip, :rotation, - :titlefontfamily, :titlefontsize, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :grid, :legend, #:colorbar, -# :marker_z, -# :line_z, -# :levels, - # :ribbon, :quiver, :arrow, -# :orientation, - :overwrite_figure, - :polar, -# :normalize, :weights, -# :contours, :aspect_ratio, - :match_dimensions, -# :clims, -# :inset_subplots, - :dpi, -# :colorbar_title, - ]) -const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot] -const _inspectdr_seriestype = [ - :path, :scatter, :shape, :straightline, #, :steppre, :steppost - ] -#see: _allMarkers, _shape_keys -const _inspectdr_marker = Symbol[ - :none, :auto, - :circle, :rect, :diamond, - :cross, :xcross, - :utriangle, :dtriangle, :rtriangle, :ltriangle, - :pentagon, :hexagon, :heptagon, :octagon, - :star4, :star5, :star6, :star7, :star8, - :vline, :hline, :+, :x, -] - -const _inspectdr_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::InspectDRBackend, shape::Shape) = true diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index b3480a9b..9cca4703 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -2,47 +2,6 @@ # significant contributions by: @pkofod -const _pgfplots_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, - :background_color_inside, - # :background_color_outside, - # :foreground_color_legend, - :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, - :fillrange, :fillcolor, :fillalpha, - :bins, - # :bar_width, :bar_edges, - :title, - # :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :legend, - :colorbar, :colorbar_title, - :fill_z, :line_z, :marker_z, :levels, - # :ribbon, :quiver, :arrow, - # :orientation, - # :overwrite_figure, - :polar, - # :normalize, :weights, :contours, - :aspect_ratio, - # :match_dimensions, - :tick_direction, - :framestyle, - :camera, - :contour_labels, - ]) -const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] -const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) -const _pgfplots_scale = [:identity, :ln, :log2, :log10] - - # -------------------------------------------------------------------------------------- const _pgfplots_linestyles = KW( diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3e525b5b..2cba0061 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -1,60 +1,6 @@ # https://plot.ly/javascript/getting-started -const _plotly_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_legend, :foreground_color_guide, - :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :foreground_color_title, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, - :fillrange, :fillcolor, :fillalpha, - :bins, - :title, :title_location, - :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, - :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :gridalpha, :gridlinewidth, - :legend, :colorbar, :colorbar_title, - :marker_z, :fill_z, :line_z, :levels, - :ribbon, :quiver, - :orientation, - # :overwrite_figure, - :polar, - :normalize, :weights, - # :contours, - :aspect_ratio, - :hover, - :inset_subplots, - :bar_width, - :clims, - :framestyle, - :tick_direction, - :camera, - :contour_labels, - ]) - -const _plotly_seriestype = [ - :path, :scatter, :pie, :heatmap, - :contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl, - :straightline -] -const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot] -const _plotly_marker = [ - :none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, - :cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline -] -const _plotly_scale = [:identity, :log10] is_subplot_supported(::PlotlyBackend) = true # is_string_supported(::PlotlyBackend) = true const _plotly_framestyles = [:box, :axes, :zerolines, :grid, :none] diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 6e06ce71..c77800dc 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -1,12 +1,6 @@ # https://github.com/spencerlyon2/PlotlyJS.jl -const _plotlyjs_attr = _plotly_attr -const _plotlyjs_seriestype = _plotly_seriestype -const _plotlyjs_style = _plotly_style -const _plotlyjs_marker = _plotly_marker -const _plotlyjs_scale = _plotly_scale - # -------------------------------------------------------------------------------------- diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 4d171847..b1467639 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1,55 +1,6 @@ # https://github.com/stevengj/PyPlot.jl -const _pyplot_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, :titlefont, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :titlefontfamily, :titlefontsize, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, - :marker_z, :line_z, :fill_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - :polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :colorbar_title, - :stride, - :framestyle, - :tick_direction, - :camera, - :contour_labels, - ]) -const _pyplot_seriestype = [ - :path, :steppre, :steppost, :shape, :straightline, - :scatter, :hexbin, #:histogram2d, :histogram, - # :bar, - :heatmap, :pie, :image, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe - ] -const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot] -const _pyplot_marker = vcat(_allMarkers, :pixel) -const _pyplot_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::PyPlotBackend, shape::Shape) = true diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index afdd08cc..370c9a87 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -1,28 +1,6 @@ # https://github.com/Evizero/UnicodePlots.jl -const _unicodeplots_attr = merge_with_base_supported([ - :label, - :legend, - :seriescolor, - :seriesalpha, - :linestyle, - :markershape, - :bins, - :title, - :guide, :lims, - ]) -const _unicodeplots_seriestype = [ - :path, :scatter, :straightline, - # :bar, - :shape, - :histogram2d, - :spy -] -const _unicodeplots_style = [:auto, :solid] -const _unicodeplots_marker = [:none, :auto, :circle] -const _unicodeplots_scale = [:identity] - # don't warn on unsupported... there's just too many warnings!! warnOnUnsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing diff --git a/src/examples.jl b/src/examples.jl index e9155d0e..a53707d9 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -437,6 +437,14 @@ each line segment or marker in the plot. ] +# Some constants for PlotDocs and PlotReferenceImages +_animation_examples = [2, 30] +_backend_skips = Dict( + :gr => [25, 30], + :pyplot => [25, 30], + :plotlyjs => [2, 21, 25, 30, 31], +) + # --------------------------------------------------------------------------------- # make and display one plot diff --git a/test/add_packages.jl b/test/add_packages.jl index 1b143c46..954fecb1 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -24,13 +24,13 @@ if isinteractive() PackageSpec(name="VisualRegressionTests"), PackageSpec(name="Gtk"), # PlotlyJS: - # PackageSpec(name="PlotlyJS", rev="master"), - # PackageSpec(name="Blink"), - # PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + PackageSpec(name="PlotlyJS", rev="master"), + PackageSpec(name="Blink"), + PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), # PyPlot: - # PackageSpec(name="PyPlot"), - # PackageSpec(name="PyCall"), - # PackageSpec(name="LaTeXStrings"), + PackageSpec(name="PyPlot"), + PackageSpec(name="PyCall"), + PackageSpec(name="LaTeXStrings"), ]) else push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) diff --git a/test/runtests.jl b/test/runtests.jl index 43ffdac4..62dc73e1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,25 +14,25 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 @test gr() == Plots.GRBackend() @test backend() == Plots.GRBackend() - image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) + # image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end -# @static if isinteractive() -# @testset "PyPlot" begin -# @test pyplot() == Plots.PyPlotBackend() -# @test backend() == Plots.PyPlotBackend() -# -# image_comparison_facts(:pyplot, tol=img_tol, skip = [25, 30]) -# end -# end +@static if isinteractive() + @testset "PyPlot" begin + @test pyplot() == Plots.PyPlotBackend() + @test backend() == Plots.PyPlotBackend() -# @testset "UnicodePlots" begin -# @test unicodeplots() == Plots.UnicodePlotsBackend() -# @test backend() == Plots.UnicodePlotsBackend() -# -# # lets just make sure it runs without error -# @test isa(plot(rand(10)), Plots.Plot) == true -# end + image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) + end +end + +@testset "UnicodePlots" begin + @test unicodeplots() == Plots.UnicodePlotsBackend() + @test backend() == Plots.UnicodePlotsBackend() + + # lets just make sure it runs without error + @test isa(plot(rand(10)), Plots.Plot) == true +end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) From 5f5019d31015c3b849db4dfe2210d75789e09ee3 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:04:44 +0200 Subject: [PATCH 006/230] fix plotlyjs (fix #1728) --- src/backends.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index c6ecaf2a..17b9f1c9 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -580,8 +580,7 @@ end function add_backend_string(::PlotlyJSBackend) """ using Pkg - Pkg.add(["PlotlyJS", "Blink"]) - Pkg.add(PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master")) + Pkg.add(["PlotlyJS", "Blink", "ORCA"]) import Blink Blink.AtomShell.install() """ From 192020a93af68a4e43819891a46fbe962c118065 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:08:32 +0200 Subject: [PATCH 007/230] skip visual regression tests on windows --- test/runtests.jl | 52 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 62dc73e1..f98f877c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,18 +14,20 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 @test gr() == Plots.GRBackend() @test backend() == Plots.GRBackend() - # image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) -end - -@static if isinteractive() - @testset "PyPlot" begin - @test pyplot() == Plots.PyPlotBackend() - @test backend() == Plots.PyPlotBackend() - - image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) + @static if Sys.islinux() + image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end end +# @static if isinteractive() +# @testset "PyPlot" begin +# @test pyplot() == Plots.PyPlotBackend() +# @test backend() == Plots.PyPlotBackend() +# +# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) +# end +# end + @testset "UnicodePlots" begin @test unicodeplots() == Plots.UnicodePlotsBackend() @test backend() == Plots.UnicodePlotsBackend() @@ -37,22 +39,22 @@ end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) -@static if isinteractive() - @testset "PlotlyJS" begin - @test plotlyjs() == Plots.PlotlyJSBackend() - @test backend() == Plots.PlotlyJSBackend() - - image_comparison_facts(:plotlyjs, - skip=[ - 2, # animation (skipped for speed) - 25, - 27, # (polar plots) takes very long / not working - 30, - 31, # animation (skipped for speed) - ], - tol=img_tol) - end -end +# @static if isinteractive() +# @testset "PlotlyJS" begin +# @test plotlyjs() == Plots.PlotlyJSBackend() +# @test backend() == Plots.PlotlyJSBackend() +# +# image_comparison_facts(:plotlyjs, +# skip=[ +# 2, # animation (skipped for speed) +# 25, +# 27, # (polar plots) takes very long / not working +# 30, +# 31, # animation (skipped for speed) +# ], +# tol=img_tol) +# end +# end # InspectDR returns that error on travis: # ERROR: LoadError: InitError: Cannot open display: From 59e7213c96464ba80098eb36406e86b3f76c7475 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:30:42 +0200 Subject: [PATCH 008/230] one more fix for plotlyjs --- src/backends/plotlyjs.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index c77800dc..791016d7 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -6,10 +6,7 @@ function _create_backend_figure(plt::Plot{PlotlyJSBackend}) if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot) - PlotlyJS.SyncPlot(PlotlyJS.Plot(), - events = current().o.events, - options = current().o.options, - ) + PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options) else PlotlyJS.plot() end From fc51c355a5c1db860ae18146a33f17f784031a4b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:53:32 +0200 Subject: [PATCH 009/230] don't add PyPlot and PlotlyJS in tests --- test/add_packages.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/add_packages.jl b/test/add_packages.jl index 954fecb1..4e27bb30 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -24,13 +24,13 @@ if isinteractive() PackageSpec(name="VisualRegressionTests"), PackageSpec(name="Gtk"), # PlotlyJS: - PackageSpec(name="PlotlyJS", rev="master"), - PackageSpec(name="Blink"), - PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + # PackageSpec(name="PlotlyJS"), + # PackageSpec(name="Blink"), + # PackageSpec(name="ORCA"), # PyPlot: - PackageSpec(name="PyPlot"), - PackageSpec(name="PyCall"), - PackageSpec(name="LaTeXStrings"), + # PackageSpec(name="PyPlot"), + # PackageSpec(name="PyCall"), + # PackageSpec(name="LaTeXStrings"), ]) else push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) From 3c2cfa333c39b85155d6febd3818c534acf5f8ca Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 4 Oct 2018 15:20:21 +0200 Subject: [PATCH 010/230] allow to not host plotly from local file --- .gitignore | 1 + deps/build.jl | 23 +++++++++++++++----- src/Plots.jl | 6 ++++++ src/backends/plotly.jl | 49 +++++++++++++++++------------------------- src/backends/web.jl | 6 ++++++ src/init.jl | 17 +++++++++++++-- 6 files changed, 66 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 69fe281c..8b7142dd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ examples/.ipynb_checkpoints/* examples/meetup/.ipynb_checkpoints/* deps/plotly-latest.min.js deps/build.log +deps/deps.jl diff --git a/deps/build.jl b/deps/build.jl index ad328049..6993b263 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -1,8 +1,21 @@ #TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist - -local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") -if !isfile(local_fn) - @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") - download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) +file_path = "" +if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "true") == "true" + global file_path + local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") + if !isfile(local_fn) + @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") + download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) + @show local_fn isfile(local_fn) + if isfile(local_fn) + file_path = local_fn + end + else + file_path = local_fn + end +end + +open("deps.jl", "w") do io + println(io, "const plotly_local_file_path = $(repr(file_path))") end diff --git a/src/Plots.jl b/src/Plots.jl index 35b16001..8c4fd730 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -18,6 +18,12 @@ import JSON using Requires +if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) + include(joinpath(@__DIR__, "..", "deps", "deps.jl")) +else + error("Plots not build, please run Pkg.build(\"Plots\")") +end + export grid, bbox, diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3e525b5b..33a0d3f6 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -71,27 +71,22 @@ end # -------------------------------------------------------------------------------------- +const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js" - -const _plotly_js_path = joinpath(dirname(@__FILE__), "..", "..", "deps", "plotly-latest.min.js") -const _plotly_js_path_remote = "https://cdn.plot.ly/plotly-latest.min.js" - -_js_code = open(read, _plotly_js_path, "r") - -# borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 -_js_script = """ - -""" - -# if we're in IJulia call setupnotebook to load js and css -if isijulia() +if isfile(plotly_local_file_path) && isijulia() + _js_code = open(read, plotly_local_file_path, "r") + # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 + _js_script = """ + + """ + # if we're in IJulia call setupnotebook to load js and css display("text/html", _js_script) end @@ -102,8 +97,6 @@ end using UUIDs push!(_initialized_backends, :plotly) - - # ---------------------------------------------------------------- const _plotly_legend_pos = KW( @@ -115,7 +108,7 @@ const _plotly_legend_pos = KW( :bottomright => [1., 0.], :topright => [1., 1.], :topleft => [0., 1.] - ) +) plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.]) plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v @@ -882,11 +875,9 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) # ---------------------------------------------------------------- -const _use_remote = Ref(false) - function html_head(plt::Plot{PlotlyBackend}) - jsfilename = _use_remote[] ? _plotly_js_path_remote : ("file://" * _plotly_js_path) - # "" + local_file = ("file://" * plotly_local_file_path) + jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path "" end @@ -908,8 +899,8 @@ end function js_body(plt::Plot{PlotlyBackend}, uuid) js = """ - PLOT = document.getElementById('$(uuid)'); - Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt))); + PLOT = document.getElementById('$(uuid)'); + Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt))); """ end diff --git a/src/backends/web.jl b/src/backends/web.jl index 55984167..336cdeb0 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -42,8 +42,14 @@ function write_temp_html(plt::AbstractPlot) end function standalone_html_window(plt::AbstractPlot) + old = use_local_dependencies[] # save state to restore afterwards + # if we open a browser ourself, we can host local files, so we + # when we have a local plotly downloaded this is the way to go! + use_local_dependencies[] = isfile(plotly_local_file_path) filename = write_temp_html(plt) open_browser_window(filename) + # restore for other backends + use_local_dependencies[] = old end # uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html diff --git a/src/init.jl b/src/init.jl index 08d1dd2b..fd6fce03 100644 --- a/src/init.jl +++ b/src/init.jl @@ -1,4 +1,7 @@ +const use_local_dependencies = Ref(false) + function __init__() + if isdefined(Main, :PLOTS_DEFAULTS) if haskey(Main.PLOTS_DEFAULTS, :theme) theme(Main.PLOTS_DEFAULTS[:theme]) @@ -27,10 +30,11 @@ function __init__() # --------------------------------------------------------- # IJulia # --------------------------------------------------------- - + use_local = false @require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin if IJulia.inited - + # IJulia is more stable with local file + use_local = isfile(plotly_local_file_path) """ Add extra jupyter mimetypes to display_dict based on the plot backed. @@ -80,4 +84,13 @@ function __init__() ENV["MPLBACKEND"] = "Agg" end end + if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL") + use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true" + use_local_dependencies[] = isfile(plotly_local_file_path) && use_local + if use_local && !isfile(plotly_local_file_path) + @warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true") + end + else + use_local_dependencies[] = use_local + end end From f5de5f58ce89f3337596a7bfc3e7ffc760e349db Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 4 Oct 2018 15:39:59 +0200 Subject: [PATCH 011/230] make ijulia plotly integration precompile save --- src/backends/plotly.jl | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 33a0d3f6..60d01669 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -73,22 +73,6 @@ end # -------------------------------------------------------------------------------------- const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js" -if isfile(plotly_local_file_path) && isijulia() - _js_code = open(read, plotly_local_file_path, "r") - # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 - _js_script = """ - - """ - # if we're in IJulia call setupnotebook to load js and css - display("text/html", _js_script) -end # if isatom() # import Atom @@ -875,7 +859,26 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) # ---------------------------------------------------------------- +const ijulia_initialized = Ref(false) + function html_head(plt::Plot{PlotlyBackend}) + if isfile(plotly_local_file_path) && isijulia() && !ijulia_initialized[] + js_code = read(plotly_local_file_path, String) + # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 + js_script = """ + + """ + # if we're in IJulia call setupnotebook to load js and css + display("text/html", js_script) + ijulia_initialized[] = true + end local_file = ("file://" * plotly_local_file_path) jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path "" From 6b46e81fbd03033754f14e1fcaf662dd4d2527de Mon Sep 17 00:00:00 2001 From: Jack Dunn Date: Thu, 4 Oct 2018 09:50:43 -0400 Subject: [PATCH 012/230] Update backends.jl --- src/backends.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends.jl b/src/backends.jl index 6a5dea31..9a5a7e1c 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -149,7 +149,7 @@ function pickDefaultBackend() @warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.") end else - @warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t", + @warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" * join(sort(_backends), "\n\t")) end end From 15739bc0ee8ef342b29f2351b59f5e308c988631 Mon Sep 17 00:00:00 2001 From: djsegal Date: Thu, 4 Oct 2018 17:20:14 -0400 Subject: [PATCH 013/230] Allow vectors of markers for pyplot scatter --- src/backends/pyplot.jl | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 92f33fd5..5ba5b086 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -603,6 +603,66 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) extrakw... )) end + push!(handles, handle) + elseif isa(series[:markershape], AbstractVector{Symbol}) + handle = [] + x,y = xyargs + shapes = series[:markershape] + + prev_marker = py_marker(_cycle(shapes,1)) + + cur_x_list = [] + cur_y_list = [] + + cur_color_list = [] + cur_scale_list = [] + + delete!(extrakw, :c) + + for i=1:length(y) + cur_marker = py_marker(_cycle(shapes,i)) + + push!(cur_x_list, _cycle(x,i)) + push!(cur_y_list, _cycle(y,i)) + + push!(cur_color_list, _cycle(markercolor, i)) + push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)) + + ( cur_marker == prev_marker ) && continue + + push!(handle, ax[:scatter](cur_x_list, cur_y_list; + label = series[:label], + zorder = series[:series_plotindex] + 0.5, + marker = prev_marker, + s = cur_scale_list, + edgecolors = py_markerstrokecolor(series), + linewidths = py_thickness_scale(plt, series[:markerstrokewidth]), + facecolors = cur_color_list, + extrakw... + )) + + cur_x_list = [] + cur_y_list = [] + + cur_color_list = [] + cur_scale_list = [] + + prev_marker = cur_marker + end + + if !isempty(cur_color_list) + push!(handle, ax[:scatter](cur_x_list, cur_y_list; + label = series[:label], + zorder = series[:series_plotindex] + 0.5, + marker = prev_marker, + s = cur_scale_list, + edgecolors = py_markerstrokecolor(series), + linewidths = py_thickness_scale(plt, series[:markerstrokewidth]), + facecolors = cur_color_list, + extrakw... + )) + end + push!(handles, handle) else # do a normal scatter plot From 268c2861c974cf666ff8ec65c04da80fdba5b9ee Mon Sep 17 00:00:00 2001 From: djsegal Date: Thu, 4 Oct 2018 17:29:37 -0400 Subject: [PATCH 014/230] Fix off-by-one error in pyplot scatter building --- src/backends/pyplot.jl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 5ba5b086..5c0f84f0 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -622,13 +622,15 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) for i=1:length(y) cur_marker = py_marker(_cycle(shapes,i)) - push!(cur_x_list, _cycle(x,i)) - push!(cur_y_list, _cycle(y,i)) + if ( cur_marker == prev_marker ) + push!(cur_x_list, _cycle(x,i)) + push!(cur_y_list, _cycle(y,i)) - push!(cur_color_list, _cycle(markercolor, i)) - push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)) + push!(cur_color_list, _cycle(markercolor, i)) + push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)) - ( cur_marker == prev_marker ) && continue + continue + end push!(handle, ax[:scatter](cur_x_list, cur_y_list; label = series[:label], @@ -641,11 +643,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) extrakw... )) - cur_x_list = [] - cur_y_list = [] + cur_x_list = [_cycle(x,i)] + cur_y_list = [_cycle(y,i)] - cur_color_list = [] - cur_scale_list = [] + cur_color_list = [_cycle(markercolor, i)] + cur_scale_list = [py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)] prev_marker = cur_marker end From ee4fc2803b489e9aa9ae30b0d1c409316657ca56 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:27:01 +0200 Subject: [PATCH 015/230] dont download by default --- deps/build.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/deps/build.jl b/deps/build.jl index 6993b263..a8cf81ff 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -1,16 +1,13 @@ #TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist file_path = "" -if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "true") == "true" +if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true" global file_path local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") if !isfile(local_fn) @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) - @show local_fn isfile(local_fn) - if isfile(local_fn) - file_path = local_fn - end + isfile(local_fn) && (file_path = local_fn) else file_path = local_fn end From 7e0960e7a0d6a2ca1bee980916104b45a98b50db Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:27:09 +0200 Subject: [PATCH 016/230] fix IJulia --- src/Plots.jl | 6 +++++- src/backends/plotly.jl | 30 ++++++++++++++---------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 8c4fd730..6f40334f 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -21,7 +21,11 @@ using Requires if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) include(joinpath(@__DIR__, "..", "deps", "deps.jl")) else - error("Plots not build, please run Pkg.build(\"Plots\")") + # This is a bit dirty, but I don't really see why anyone should be forced + # to build Plots, while it will just include exactly the below line + # as long as now ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true" is given + # If the above env is set + plotly_local_file_path = "", it will warn in the __init__ functtion + const plotly_local_file_path = "" end export diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 60d01669..5c12ba4b 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -862,26 +862,24 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) const ijulia_initialized = Ref(false) function html_head(plt::Plot{PlotlyBackend}) - if isfile(plotly_local_file_path) && isijulia() && !ijulia_initialized[] - js_code = read(plotly_local_file_path, String) - # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 - js_script = """ - - """ - # if we're in IJulia call setupnotebook to load js and css - display("text/html", js_script) + """) ijulia_initialized[] = true end - local_file = ("file://" * plotly_local_file_path) - jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path - "" + # IJulia just needs one initialization + isijulia() && return "" + return "" end function html_body(plt::Plot{PlotlyBackend}, style = nothing) From 9ccb699fca1add6201ad3ddada095971b6597cd5 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:33:13 +0200 Subject: [PATCH 017/230] improve comments --- src/Plots.jl | 5 +++-- src/backends/web.jl | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 6f40334f..448bdfec 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -23,8 +23,9 @@ if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) else # This is a bit dirty, but I don't really see why anyone should be forced # to build Plots, while it will just include exactly the below line - # as long as now ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true" is given - # If the above env is set + plotly_local_file_path = "", it will warn in the __init__ functtion + # as long as `ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true"` is not set. + # If the above env is set + `plotly_local_file_path == ""``, + # it will warn in the __init__ function to run build const plotly_local_file_path = "" end diff --git a/src/backends/web.jl b/src/backends/web.jl index 336cdeb0..b1663435 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -43,7 +43,7 @@ end function standalone_html_window(plt::AbstractPlot) old = use_local_dependencies[] # save state to restore afterwards - # if we open a browser ourself, we can host local files, so we + # if we open a browser ourself, we can host local files, so # when we have a local plotly downloaded this is the way to go! use_local_dependencies[] = isfile(plotly_local_file_path) filename = write_temp_html(plt) From 16cc743d26df1af358ac85c41b7b9806da1e6bba Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Mon, 8 Oct 2018 06:54:01 -0700 Subject: [PATCH 018/230] Add support for annotations and "Shape"s. Also build plot attributes list after series are read in to avoid having the internal mechanisms overwrite data. --- src/backends/hdf5.jl | 71 +++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl index 28dd767d..2bf8281b 100644 --- a/src/backends/hdf5.jl +++ b/src/backends/hdf5.jl @@ -16,16 +16,19 @@ Read from .hdf5 file using: #==TODO =============================================================================== - 1. Support more features - - SeriesAnnotations & GridLayout known to be missing. - 3. Improve error handling. + 1. Support more features. + - GridLayout known not to be working. + 2. Improve error handling. - Will likely crash if file format is off. - 2. Save data in a folder parallel to "plot". + 3. Save data in a folder parallel to "plot". - Will make it easier for users to locate data. - Use HDF5 reference to link data? - 3. Develop an actual versioned file format. + 4. Develop an actual versioned file format. - Should have some form of backward compatibility. - Should be reliable for archival purposes. + 5. Fix construction of plot object with hdf5plot_read. + - Not building object correctly when backends do not natively support + a certain feature (ex: :steppre) ==# import FixedPointNumbers: N0f8 #In core Julia @@ -56,7 +59,8 @@ const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing) #Simple sub-structures that can just be written out using _hdf5plot_gwritefields: const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox, - GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText + GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText, + Shape, } @@ -125,7 +129,8 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1 "GRIDLAYOUT" => GridLayout, "ROOTLAYOUT" => RootLayout, "SERIESANNOTATIONS" => SeriesAnnotations, -# "PLOTTEXT" => PlotText, + "PLOTTEXT" => PlotText, + "SHAPE" => Shape, "COLORGRADIENT" => ColorGradient, "AXIS" => Axis, "SURFACE" => Surface, @@ -284,6 +289,14 @@ end # ---------------------------------------------------------------- function _hdf5plot_gwrite(grp, k::String, v) #Default + T = typeof(v) + if !(T <: Number || T <: String) + tstr = string(T) + path = HDF5.name(grp) * "/" * k + @info("Type not supported: $tstr\npath: $path") +# @show v + return + end grp[k] = v _hdf5plot_writetype(grp, k, HDF5PlotNative) end @@ -338,10 +351,6 @@ function _hdf5plot_gwrite(grp, k::String, v::Colorant) end #Custom vector (when not using simple numeric type): function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T - if "annotations" == k; - return #Hack. Does not yet support annotations. - end - vgrp = HDF5.g_create(grp, k) _hdf5plot_writetype(vgrp, Array) #ANY sz = size(v) @@ -351,7 +360,7 @@ function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T coord = lidx[iter] elem = v[iter] idxstr = join(coord, "_") - _hdf5plot_gwrite(vgrp, "v$idxstr", v[iter]) + _hdf5plot_gwrite(vgrp, "v$idxstr", elem) end _hdf5plot_gwrite(vgrp, "dim", [sz...]) @@ -402,10 +411,6 @@ end # return # end -function _hdf5plot_gwrite(grp, k::String, v::SeriesAnnotations) - #Currently no support for SeriesAnnotations - return -end function _hdf5plot_gwrite(grp, k::String, v::Subplot) grp = HDF5.g_create(grp, k) _hdf5plot_gwrite(grp, "index", v[:subplot_index]) @@ -528,6 +533,29 @@ function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid) v = _hdf5plot_read(grp, k, Array, dtid) return tuple(v...) end +function _hdf5plot_read(grp, k::String, T::Type{PlotText}, dtid) + grp = HDF5.g_open(grp, k) + + str = _hdf5plot_read(grp, "str") + font = _hdf5plot_read(grp, "font") + return PlotText(str, font) +end +function _hdf5plot_read(grp, k::String, T::Type{SeriesAnnotations}, dtid) + grp = HDF5.g_open(grp, k) + + strs = _hdf5plot_read(grp, "strs") + font = _hdf5plot_read(grp, "font") + baseshape = _hdf5plot_read(grp, "baseshape") + scalefactor = _hdf5plot_read(grp, "scalefactor") + return SeriesAnnotations(strs, font, baseshape, scalefactor) +end +function _hdf5plot_read(grp, k::String, T::Type{Shape}, dtid) + grp = HDF5.g_open(grp, k) + + x = _hdf5plot_read(grp, "x") + y = _hdf5plot_read(grp, "y") + return Shape(x, y) +end function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid) grp = HDF5.g_open(grp, k) @@ -601,11 +629,6 @@ end function _hdf5plot_read(sp::Subplot, subpath::String, f) f = f::HDF5.HDF5File #Assert - grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr")) - kwlist = KW() - _hdf5plot_read(grp, kwlist) - _hdf5_merge!(sp.attr, kwlist) - grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list")) nseries = _hdf5plot_readcount(grp) @@ -617,6 +640,12 @@ function _hdf5plot_read(sp::Subplot, subpath::String, f) _hdf5_merge!(sp.series_list[end].plotattributes, kwlist) end + #Perform after adding series... otherwise values get overwritten: + grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr")) + kwlist = KW() + _hdf5plot_read(grp, kwlist) + _hdf5_merge!(sp.attr, kwlist) + return end From d3e1a423fde038f9212d263bb0a3133839e6e3f6 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 8 Oct 2018 16:17:01 +0200 Subject: [PATCH 019/230] update news for release --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 81c8b5a0..57d2e2d2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,12 @@ ## (current master) - All new development should target Julia 1.x! +## 0.20.5 +- fix precompilation issue when depending on Plots + +## 0.20.4 +- honour `html_output_format` in Juno + ## 0.20.3 - implement guide position in gr, pyplot and pgfplots - inspectdr fixes From 87c471c0f5ea0b409f5d88b6d64d5d8f80882472 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 2 Sep 2018 22:28:34 +0200 Subject: [PATCH 020/230] plotlyjs, pyplot and test fixes --- src/backends.jl | 22 +++++++--------- src/backends/plotlyjs.jl | 5 +++- src/backends/pyplot.jl | 2 +- test/add_packages.jl | 13 +++++++++- test/runtests.jl | 56 +++++++++++++++++++++------------------- 5 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 9a5a7e1c..4a3aa4f2 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -347,16 +347,6 @@ function _initialize_backend(::GLVisualizeBackend; kw...) end end -# ------------------------------------------------------------------------------ -# hdf5 - -function _initialize_backend(::HDF5Backend) - @eval Main begin - import HDF5 - export HDF5 - end -end - # ------------------------------------------------------------------------------ # PGFPLOTS @@ -371,11 +361,19 @@ end # ------------------------------------------------------------------------------ # plotlyjs +function _initialize_backend(pkg::PlotlyJSBackend) + sym = backend_package_name(pkg) + @eval Main begin + import PlotlyJS, ORCA + export PlotlyJS + end +end + function add_backend_string(::PlotlyJSBackend) """ using Pkg - Pkg.add("PlotlyJS") - Pkg.add("Rsvg") + Pkg.add(["PlotlyJS", "Blink"]) + Pkg.add(PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master")) import Blink Blink.AtomShell.install() """ diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 98e626c1..6e06ce71 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -12,7 +12,10 @@ const _plotlyjs_scale = _plotly_scale function _create_backend_figure(plt::Plot{PlotlyJSBackend}) if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot) - PlotlyJS.SyncPlot(PlotlyJS.Plot(), current().o.view) + PlotlyJS.SyncPlot(PlotlyJS.Plot(), + events = current().o.events, + options = current().o.options, + ) else PlotlyJS.plot() end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 4524e967..4933406d 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1064,7 +1064,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis) # don't show the 0 tick label for the origin framestyle if sp[:framestyle] == :origin && length(ticks) > 1 - ticks[2][ticks[1] .== 0] = "" + ticks[2][ticks[1] .== 0] .= "" end axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in") diff --git a/test/add_packages.jl b/test/add_packages.jl index 260707d3..1b143c46 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -4,7 +4,6 @@ using Pkg # ENV["PYTHON"] = "" to_add = [ - PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"), # PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"), PackageSpec(name="PlotUtils", rev="master"), PackageSpec(name="RecipesBase", rev="master"), @@ -17,12 +16,24 @@ to_add = [ ] if isinteractive() + Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) append!(to_add, [ PackageSpec(name="FileIO"), PackageSpec(name="ImageMagick"), PackageSpec(name="UnicodePlots"), PackageSpec(name="VisualRegressionTests"), + PackageSpec(name="Gtk"), + # PlotlyJS: + # PackageSpec(name="PlotlyJS", rev="master"), + # PackageSpec(name="Blink"), + # PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + # PyPlot: + # PackageSpec(name="PyPlot"), + # PackageSpec(name="PyCall"), + # PackageSpec(name="LaTeXStrings"), ]) +else + push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) end Pkg.add(to_add) diff --git a/test/runtests.jl b/test/runtests.jl index 543b8ea3..43ffdac4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,40 +17,42 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end - -#@testset "PyPlot" begin -# @test pyplot() == Plots.PyPlotBackend() -# @test backend() == Plots.PyPlotBackend() +# @static if isinteractive() +# @testset "PyPlot" begin +# @test pyplot() == Plots.PyPlotBackend() +# @test backend() == Plots.PyPlotBackend() # -# image_comparison_facts(:pyplot, tol=img_tol) -#end +# image_comparison_facts(:pyplot, tol=img_tol, skip = [25, 30]) +# end +# end -@testset "UnicodePlots" begin - @test unicodeplots() == Plots.UnicodePlotsBackend() - @test backend() == Plots.UnicodePlotsBackend() - - # lets just make sure it runs without error - @test isa(plot(rand(10)), Plots.Plot) == true -end +# @testset "UnicodePlots" begin +# @test unicodeplots() == Plots.UnicodePlotsBackend() +# @test backend() == Plots.UnicodePlotsBackend() +# +# # lets just make sure it runs without error +# @test isa(plot(rand(10)), Plots.Plot) == true +# end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) -# @testset "PlotlyJS" begin -# @test plotlyjs() == Plots.PlotlyJSBackend() -# @test backend() == Plots.PlotlyJSBackend() -# -# if Sys.islinux() && isinteractive() -# image_comparison_facts(:plotlyjs, -# skip=[ -# 2, # animation (skipped for speed) -# 27, # (polar plots) takes very long / not working -# 31, # animation (skipped for speed) -# ], -# tol=img_tol) -# end -# end +@static if isinteractive() + @testset "PlotlyJS" begin + @test plotlyjs() == Plots.PlotlyJSBackend() + @test backend() == Plots.PlotlyJSBackend() + image_comparison_facts(:plotlyjs, + skip=[ + 2, # animation (skipped for speed) + 25, + 27, # (polar plots) takes very long / not working + 30, + 31, # animation (skipped for speed) + ], + tol=img_tol) + end +end # InspectDR returns that error on travis: # ERROR: LoadError: InitError: Cannot open display: From 31004e8c128e757588b93250211786bbdba4ef9e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 3 Sep 2018 17:30:50 +0200 Subject: [PATCH 021/230] move _current_plots_version from PlotDocs to Plots --- src/Plots.jl | 2 ++ test/imgcomp.jl | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/Plots.jl b/src/Plots.jl index 35b16001..f09115e5 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,5 +1,7 @@ module Plots +_current_plots_version = v"0.20.1" + using Reexport import StaticArrays diff --git a/test/imgcomp.jl b/test/imgcomp.jl index f52e5a38..64bfbeb2 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -29,7 +29,11 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) +<<<<<<< HEAD const _current_plots_version = v"0.20.3" +======= +import Plots._current_plots_version +>>>>>>> move _current_plots_version from PlotDocs to Plots function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) From a72a23b5483a7b2eba98ee2b06abfee0b3b403b7 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 4 Sep 2018 19:08:48 +0200 Subject: [PATCH 022/230] move supported backend attr to backends.jl --- src/backends.jl | 390 ++++++++++++++++++++++++++++++++++- src/backends/glvisualize.jl | 48 +---- src/backends/gr.jl | 59 ------ src/backends/hdf5.jl | 41 ---- src/backends/inspectdr.jl | 55 ----- src/backends/pgfplots.jl | 41 ---- src/backends/plotly.jl | 54 ----- src/backends/plotlyjs.jl | 6 - src/backends/pyplot.jl | 49 ----- src/backends/unicodeplots.jl | 22 -- src/examples.jl | 8 + test/add_packages.jl | 12 +- test/runtests.jl | 32 +-- 13 files changed, 420 insertions(+), 397 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 4a3aa4f2..8046d16e 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -330,6 +330,126 @@ function add_backend_string(pkg::AbstractBackend) """ end +# ------------------------------------------------------------------------------ +# gr + +const _gr_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, + :layout, + :title, :window_title, + :guide, :lims, :ticks, :scale, :flip, + :match_dimensions, + :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, + :titlefontrotation, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign, + :legendfontrotation, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign, + :tickfontrotation, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, + :guidefontrotation, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legendtitle, :colorbar, :colorbar_title, + :fill_z, :line_z, :marker_z, :levels, + :ribbon, :quiver, + :orientation, + :overwrite_figure, + :polar, + :aspect_ratio, + :normalize, :weights, + :inset_subplots, + :bar_width, + :arrow, + :framestyle, + :tick_direction, + :camera, + :contour_labels, +]) +const _gr_seriestype = [ + :path, :scatter, :straightline, + :heatmap, :pie, :image, + :contour, :path3d, :scatter3d, :surface, :wireframe, + :shape +] +const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] +const _gr_marker = _allMarkers +const _gr_scale = [:identity, :log10] +is_marker_supported(::GRBackend, shape::Shape) = true + +function add_backend_string(::GRBackend) + """ + Pkg.add("GR") + Pkg.build("GR") + """ +end + +# ------------------------------------------------------------------------------ +# plotly + +const _plotly_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_legend, :foreground_color_guide, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :foreground_color_title, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, + :fillrange, :fillcolor, :fillalpha, + :bins, + :title, :title_location, + :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, + :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :gridalpha, :gridlinewidth, + :legend, :colorbar, :colorbar_title, + :marker_z, :fill_z, :line_z, :levels, + :ribbon, :quiver, + :orientation, + # :overwrite_figure, + :polar, + :normalize, :weights, + # :contours, + :aspect_ratio, + :hover, + :inset_subplots, + :bar_width, + :clims, + :framestyle, + :tick_direction, + :camera, + :contour_labels, + ]) + +const _plotly_seriestype = [ + :path, :scatter, :pie, :heatmap, + :contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl, + :straightline +] +const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot] +const _plotly_marker = [ + :none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, + :cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline +] +const _plotly_scale = [:identity, :log10] + # ------------------------------------------------------------------------------ # glvisualize @@ -347,8 +467,56 @@ function _initialize_backend(::GLVisualizeBackend; kw...) end end +const _glvisualize_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :titlefontsize, :titlefontcolor, + :legendfontsize, :legendfontcolor, + :tickfontsize, + :guidefontsize, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :colorbar, + :marker_z, + :line_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + #:polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :hover, + :framestyle, + :tick_direction, +]) +const _glvisualize_seriestype = [ + :path, :shape, :straightline, + :scatter, :hexbin, + :bar, :boxplot, + :heatmap, :image, :volume, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe +] +const _glvisualize_style = [:auto, :solid, :dash, :dot, :dashdot] +const _glvisualize_marker = _allMarkers +const _glvisualize_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ -# PGFPLOTS +# pgfplots function add_backend_string(::PGFPlotsBackend) """ @@ -358,6 +526,45 @@ function add_backend_string(::PGFPlotsBackend) """ end +:annotations, +:background_color_legend, +:background_color_inside, +# :background_color_outside, +# :foreground_color_legend, +:foreground_color_grid, :foreground_color_axis, +:foreground_color_text, :foreground_color_border, +:label, +:seriescolor, :seriesalpha, +:linecolor, :linestyle, :linewidth, :linealpha, +:markershape, :markercolor, :markersize, :markeralpha, +:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, +:fillrange, :fillcolor, :fillalpha, +:bins, +# :bar_width, :bar_edges, +:title, +# :window_title, +:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, +:tickfont, :guidefont, :legendfont, +:grid, :legend, +:colorbar, :colorbar_title, +:fill_z, :line_z, :marker_z, :levels, +# :ribbon, :quiver, :arrow, +# :orientation, +# :overwrite_figure, +:polar, +# :normalize, :weights, :contours, +:aspect_ratio, +# :match_dimensions, +:tick_direction, +:framestyle, +:camera, +:contour_labels, +]) +const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] +const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] +const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) +const _pgfplots_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ # plotlyjs @@ -379,6 +586,12 @@ function add_backend_string(::PlotlyJSBackend) """ end +const _plotlyjs_attr = _plotly_attr +const _plotlyjs_seriestype = _plotly_seriestype +const _plotlyjs_style = _plotly_style +const _plotlyjs_marker = _plotly_marker +const _plotlyjs_scale = _plotly_scale + # ------------------------------------------------------------------------------ # pyplot @@ -407,8 +620,59 @@ function add_backend_string(::PyPlotBackend) """ end +const _pyplot_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, :titlefont, + :window_title, + :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legendtitle, :colorbar, + :marker_z, :line_z, :fill_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + :polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :colorbar_title, + :stride, + :framestyle, + :tick_direction, + :camera, + :contour_labels, + ]) +const _pyplot_seriestype = [ + :path, :steppre, :steppost, :shape, :straightline, + :scatter, :hexbin, #:histogram2d, :histogram, + # :bar, + :heatmap, :pie, :image, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe + ] +const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot] +const _pyplot_marker = vcat(_allMarkers, :pixel) +const _pyplot_scale = [:identity, :ln, :log2, :log10] + # ------------------------------------------------------------------------------ # unicodeplots + function add_backend_string(::UnicodePlotsBackend) """ using Pkg @@ -416,3 +680,127 @@ function add_backend_string(::UnicodePlotsBackend) Pkg.build("UnicodePlots") """ end + +const _unicodeplots_attr = merge_with_base_supported([ + :label, + :legend, + :seriescolor, + :seriesalpha, + :linestyle, + :markershape, + :bins, + :title, + :guide, :lims, + ]) +const _unicodeplots_seriestype = [ + :path, :scatter, :straightline, + # :bar, + :shape, + :histogram2d, + :spy +] +const _unicodeplots_style = [:auto, :solid] +const _unicodeplots_marker = [:none, :auto, :circle] +const _unicodeplots_scale = [:identity] + +# ------------------------------------------------------------------------------ +# hdf5 + +const _hdf5_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, :titlefont, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :legend, :colorbar, + :marker_z, :line_z, :fill_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + :polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :colorbar_title, + ]) +const _hdf5_seriestype = [ + :path, :steppre, :steppost, :shape, :straightline, + :scatter, :hexbin, #:histogram2d, :histogram, + # :bar, + :heatmap, :pie, :image, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe + ] +const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] +const _hdf5_marker = vcat(_allMarkers, :pixel) +const _hdf5_scale = [:identity, :ln, :log2, :log10] + +# ------------------------------------------------------------------------------ +# inspectdr + +const _inspectdr_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + # :foreground_color_grid, + :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :markerstrokestyle, #Causes warning not to have it... what is this? + :fillcolor, :fillalpha, #:fillrange, +# :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, + :window_title, + :guide, :lims, :scale, #:ticks, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legendfontfamily, :legendfontsize, :legendfontcolor, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, #:gridalpha, :gridstyle, :gridlinewidth, #alhpa & linewidth are per plot - not per subplot + :legend, #:legendtitle, :colorbar, +# :marker_z, +# :line_z, +# :levels, + # :ribbon, :quiver, :arrow, +# :orientation, + :overwrite_figure, + :polar, +# :normalize, :weights, +# :contours, :aspect_ratio, + :match_dimensions, +# :clims, +# :inset_subplots, + :dpi, +# :colorbar_title, + ]) +const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot] +const _inspectdr_seriestype = [ + :path, :scatter, :shape, :straightline, #, :steppre, :steppost + ] +#see: _allMarkers, _shape_keys +const _inspectdr_marker = Symbol[ + :none, :auto, + :circle, :rect, :diamond, + :cross, :xcross, + :utriangle, :dtriangle, :rtriangle, :ltriangle, + :pentagon, :hexagon, :heptagon, :octagon, + :star4, :star5, :star6, :star7, :star8, + :vline, :hline, :+, :x, +] + +const _inspectdr_scale = [:identity, :ln, :log2, :log10] diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index 72288380..72f7c74e 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -9,53 +9,7 @@ TODO * fix units in all visuals (e.g dotted lines, marker scale, surfaces) =# -const _glvisualize_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :titlefontsize, :titlefontcolor, - :legendfontsize, :legendfontcolor, - :tickfontsize, - :guidefontsize, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :colorbar, - :marker_z, - :line_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - #:polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :hover, - :framestyle, - :tick_direction, -]) -const _glvisualize_seriestype = [ - :path, :shape, :straightline, - :scatter, :hexbin, - :bar, :boxplot, - :heatmap, :image, :volume, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe -] -const _glvisualize_style = [:auto, :solid, :dash, :dot, :dashdot] -const _glvisualize_marker = _allMarkers -const _glvisualize_scale = [:identity, :ln, :log2, :log10] + slice_arg(img::Matrix{C}, idx::Int) where {C<:Colorant} = img is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 267875f9..67996895 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -3,65 +3,6 @@ # significant contributions by @jheinen -const _gr_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, - :layout, - :title, :window_title, - :guide, :guide_position, :lims, :ticks, :scale, :flip, - :match_dimensions, - :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, - :titlefontrotation, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign, - :legendfontrotation, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign, - :tickfontrotation, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, - :guidefontrotation, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, :colorbar_title, - :fill_z, :line_z, :marker_z, :levels, - :ribbon, :quiver, - :orientation, - :overwrite_figure, - :polar, - :aspect_ratio, - :normalize, :weights, - :inset_subplots, - :bar_width, - :arrow, - :framestyle, - :tick_direction, - :camera, - :contour_labels, -]) -const _gr_seriestype = [ - :path, :scatter, :straightline, - :heatmap, :pie, :image, - :contour, :path3d, :scatter3d, :surface, :wireframe, - :shape -] -const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -const _gr_marker = _allMarkers -const _gr_scale = [:identity, :log10] -is_marker_supported(::GRBackend, shape::Shape) = true - -function add_backend_string(::GRBackend) - """ - Pkg.add("GR") - Pkg.build("GR") - """ -end - import GR export GR diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl index 28dd767d..95b83874 100644 --- a/src/backends/hdf5.jl +++ b/src/backends/hdf5.jl @@ -62,47 +62,6 @@ const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox, #== ===============================================================================# - -const _hdf5_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, :titlefont, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :legend, :colorbar, - :marker_z, :line_z, :fill_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - :polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :colorbar_title, - ]) -const _hdf5_seriestype = [ - :path, :steppre, :steppost, :shape, :straightline, - :scatter, :hexbin, #:histogram2d, :histogram, - # :bar, - :heatmap, :pie, :image, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe - ] -const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] -const _hdf5_marker = vcat(_allMarkers, :pixel) -const _hdf5_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::HDF5Backend, shape::Shape) = true if length(HDF5PLOT_MAP_TELEM2STR) < 1 diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index 56fd7f32..bbc268a3 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -14,61 +14,6 @@ Add in functionality to Plots.jl: =# # --------------------------------------------------------------------------- -#TODO: remove features -const _inspectdr_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - # :foreground_color_grid, - :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :markerstrokestyle, #Causes warning not to have it... what is this? - :fillcolor, :fillalpha, #:fillrange, -# :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, - :window_title, - :guide, :lims, :scale, #:ticks, :flip, :rotation, - :titlefontfamily, :titlefontsize, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :grid, #:gridalpha, :gridstyle, :gridlinewidth, #alhpa & linewidth are per plot - not per subplot - :legend, #:legendtitle, :colorbar, -# :marker_z, -# :line_z, -# :levels, - # :ribbon, :quiver, :arrow, -# :orientation, - :overwrite_figure, - :polar, -# :normalize, :weights, -# :contours, :aspect_ratio, - :match_dimensions, -# :clims, -# :inset_subplots, - :dpi, -# :colorbar_title, - ]) -const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot] -const _inspectdr_seriestype = [ - :path, :scatter, :shape, :straightline, #, :steppre, :steppost - ] -#see: _allMarkers, _shape_keys -const _inspectdr_marker = Symbol[ - :none, :auto, - :circle, :rect, :diamond, - :cross, :xcross, - :utriangle, :dtriangle, :rtriangle, :ltriangle, - :pentagon, :hexagon, :heptagon, :octagon, - :star4, :star5, :star6, :star7, :star8, - :vline, :hline, :+, :x, -] - -const _inspectdr_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::InspectDRBackend, shape::Shape) = true diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 26865bb9..9b351175 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -2,47 +2,6 @@ # significant contributions by: @pkofod -const _pgfplots_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, - :background_color_inside, - # :background_color_outside, - # :foreground_color_legend, - :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, - :fillrange, :fillcolor, :fillalpha, - :bins, - # :bar_width, :bar_edges, - :title, - # :window_title, - :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :legend, - :colorbar, :colorbar_title, - :fill_z, :line_z, :marker_z, :levels, - # :ribbon, :quiver, :arrow, - # :orientation, - # :overwrite_figure, - :polar, - # :normalize, :weights, :contours, - :aspect_ratio, - # :match_dimensions, - :tick_direction, - :framestyle, - :camera, - :contour_labels, - ]) -const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] -const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) -const _pgfplots_scale = [:identity, :ln, :log2, :log10] - - # -------------------------------------------------------------------------------------- const _pgfplots_linestyles = KW( diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3e525b5b..2cba0061 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -1,60 +1,6 @@ # https://plot.ly/javascript/getting-started -const _plotly_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_legend, :foreground_color_guide, - :foreground_color_grid, :foreground_color_axis, - :foreground_color_text, :foreground_color_border, - :foreground_color_title, - :label, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, - :fillrange, :fillcolor, :fillalpha, - :bins, - :title, :title_location, - :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, - :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :gridalpha, :gridlinewidth, - :legend, :colorbar, :colorbar_title, - :marker_z, :fill_z, :line_z, :levels, - :ribbon, :quiver, - :orientation, - # :overwrite_figure, - :polar, - :normalize, :weights, - # :contours, - :aspect_ratio, - :hover, - :inset_subplots, - :bar_width, - :clims, - :framestyle, - :tick_direction, - :camera, - :contour_labels, - ]) - -const _plotly_seriestype = [ - :path, :scatter, :pie, :heatmap, - :contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl, - :straightline -] -const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot] -const _plotly_marker = [ - :none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, - :cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline -] -const _plotly_scale = [:identity, :log10] is_subplot_supported(::PlotlyBackend) = true # is_string_supported(::PlotlyBackend) = true const _plotly_framestyles = [:box, :axes, :zerolines, :grid, :none] diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 6e06ce71..c77800dc 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -1,12 +1,6 @@ # https://github.com/spencerlyon2/PlotlyJS.jl -const _plotlyjs_attr = _plotly_attr -const _plotlyjs_seriestype = _plotly_seriestype -const _plotlyjs_style = _plotly_style -const _plotlyjs_marker = _plotly_marker -const _plotlyjs_scale = _plotly_scale - # -------------------------------------------------------------------------------------- diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 4933406d..0a581a3f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1,55 +1,6 @@ # https://github.com/stevengj/PyPlot.jl -const _pyplot_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, :titlefont, - :window_title, - :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, - :titlefontfamily, :titlefontsize, :titlefontcolor, - :legendfontfamily, :legendfontsize, :legendfontcolor, - :tickfontfamily, :tickfontsize, :tickfontcolor, - :guidefontfamily, :guidefontsize, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, - :marker_z, :line_z, :fill_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - :polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :colorbar_title, - :stride, - :framestyle, - :tick_direction, - :camera, - :contour_labels, - ]) -const _pyplot_seriestype = [ - :path, :steppre, :steppost, :shape, :straightline, - :scatter, :hexbin, #:histogram2d, :histogram, - # :bar, - :heatmap, :pie, :image, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe - ] -const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot] -const _pyplot_marker = vcat(_allMarkers, :pixel) -const _pyplot_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::PyPlotBackend, shape::Shape) = true diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index afdd08cc..370c9a87 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -1,28 +1,6 @@ # https://github.com/Evizero/UnicodePlots.jl -const _unicodeplots_attr = merge_with_base_supported([ - :label, - :legend, - :seriescolor, - :seriesalpha, - :linestyle, - :markershape, - :bins, - :title, - :guide, :lims, - ]) -const _unicodeplots_seriestype = [ - :path, :scatter, :straightline, - # :bar, - :shape, - :histogram2d, - :spy -] -const _unicodeplots_style = [:auto, :solid] -const _unicodeplots_marker = [:none, :auto, :circle] -const _unicodeplots_scale = [:identity] - # don't warn on unsupported... there's just too many warnings!! warnOnUnsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing diff --git a/src/examples.jl b/src/examples.jl index e9155d0e..a53707d9 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -437,6 +437,14 @@ each line segment or marker in the plot. ] +# Some constants for PlotDocs and PlotReferenceImages +_animation_examples = [2, 30] +_backend_skips = Dict( + :gr => [25, 30], + :pyplot => [25, 30], + :plotlyjs => [2, 21, 25, 30, 31], +) + # --------------------------------------------------------------------------------- # make and display one plot diff --git a/test/add_packages.jl b/test/add_packages.jl index 1b143c46..954fecb1 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -24,13 +24,13 @@ if isinteractive() PackageSpec(name="VisualRegressionTests"), PackageSpec(name="Gtk"), # PlotlyJS: - # PackageSpec(name="PlotlyJS", rev="master"), - # PackageSpec(name="Blink"), - # PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + PackageSpec(name="PlotlyJS", rev="master"), + PackageSpec(name="Blink"), + PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), # PyPlot: - # PackageSpec(name="PyPlot"), - # PackageSpec(name="PyCall"), - # PackageSpec(name="LaTeXStrings"), + PackageSpec(name="PyPlot"), + PackageSpec(name="PyCall"), + PackageSpec(name="LaTeXStrings"), ]) else push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) diff --git a/test/runtests.jl b/test/runtests.jl index 43ffdac4..62dc73e1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,25 +14,25 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 @test gr() == Plots.GRBackend() @test backend() == Plots.GRBackend() - image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) + # image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end -# @static if isinteractive() -# @testset "PyPlot" begin -# @test pyplot() == Plots.PyPlotBackend() -# @test backend() == Plots.PyPlotBackend() -# -# image_comparison_facts(:pyplot, tol=img_tol, skip = [25, 30]) -# end -# end +@static if isinteractive() + @testset "PyPlot" begin + @test pyplot() == Plots.PyPlotBackend() + @test backend() == Plots.PyPlotBackend() -# @testset "UnicodePlots" begin -# @test unicodeplots() == Plots.UnicodePlotsBackend() -# @test backend() == Plots.UnicodePlotsBackend() -# -# # lets just make sure it runs without error -# @test isa(plot(rand(10)), Plots.Plot) == true -# end + image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) + end +end + +@testset "UnicodePlots" begin + @test unicodeplots() == Plots.UnicodePlotsBackend() + @test backend() == Plots.UnicodePlotsBackend() + + # lets just make sure it runs without error + @test isa(plot(rand(10)), Plots.Plot) == true +end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) From 874dacd2c855562a1ac44653b02f27711130716d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:04:44 +0200 Subject: [PATCH 023/230] fix plotlyjs (fix #1728) --- src/backends.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 8046d16e..77b6d261 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -579,8 +579,7 @@ end function add_backend_string(::PlotlyJSBackend) """ using Pkg - Pkg.add(["PlotlyJS", "Blink"]) - Pkg.add(PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master")) + Pkg.add(["PlotlyJS", "Blink", "ORCA"]) import Blink Blink.AtomShell.install() """ From cccbaa0bdcea5cf812d7bc4aa60c8c4e08800d6e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:08:32 +0200 Subject: [PATCH 024/230] skip visual regression tests on windows --- test/runtests.jl | 52 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 62dc73e1..f98f877c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,18 +14,20 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 @test gr() == Plots.GRBackend() @test backend() == Plots.GRBackend() - # image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) -end - -@static if isinteractive() - @testset "PyPlot" begin - @test pyplot() == Plots.PyPlotBackend() - @test backend() == Plots.PyPlotBackend() - - image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) + @static if Sys.islinux() + image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) end end +# @static if isinteractive() +# @testset "PyPlot" begin +# @test pyplot() == Plots.PyPlotBackend() +# @test backend() == Plots.PyPlotBackend() +# +# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) +# end +# end + @testset "UnicodePlots" begin @test unicodeplots() == Plots.UnicodePlotsBackend() @test backend() == Plots.UnicodePlotsBackend() @@ -37,22 +39,22 @@ end # The plotlyjs testimages return a connection error on travis: # connect: connection refused (ECONNREFUSED) -@static if isinteractive() - @testset "PlotlyJS" begin - @test plotlyjs() == Plots.PlotlyJSBackend() - @test backend() == Plots.PlotlyJSBackend() - - image_comparison_facts(:plotlyjs, - skip=[ - 2, # animation (skipped for speed) - 25, - 27, # (polar plots) takes very long / not working - 30, - 31, # animation (skipped for speed) - ], - tol=img_tol) - end -end +# @static if isinteractive() +# @testset "PlotlyJS" begin +# @test plotlyjs() == Plots.PlotlyJSBackend() +# @test backend() == Plots.PlotlyJSBackend() +# +# image_comparison_facts(:plotlyjs, +# skip=[ +# 2, # animation (skipped for speed) +# 25, +# 27, # (polar plots) takes very long / not working +# 30, +# 31, # animation (skipped for speed) +# ], +# tol=img_tol) +# end +# end # InspectDR returns that error on travis: # ERROR: LoadError: InitError: Cannot open display: From 106ed6b953b9f60dbe20f442e55d048b2b3ade30 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:30:42 +0200 Subject: [PATCH 025/230] one more fix for plotlyjs --- src/backends/plotlyjs.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index c77800dc..791016d7 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -6,10 +6,7 @@ function _create_backend_figure(plt::Plot{PlotlyJSBackend}) if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot) - PlotlyJS.SyncPlot(PlotlyJS.Plot(), - events = current().o.events, - options = current().o.options, - ) + PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options) else PlotlyJS.plot() end From b73d7f03a74be2af0b3c3885275ab59cdc310cd3 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 6 Sep 2018 22:53:32 +0200 Subject: [PATCH 026/230] don't add PyPlot and PlotlyJS in tests --- test/add_packages.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/add_packages.jl b/test/add_packages.jl index 954fecb1..4e27bb30 100644 --- a/test/add_packages.jl +++ b/test/add_packages.jl @@ -24,13 +24,13 @@ if isinteractive() PackageSpec(name="VisualRegressionTests"), PackageSpec(name="Gtk"), # PlotlyJS: - PackageSpec(name="PlotlyJS", rev="master"), - PackageSpec(name="Blink"), - PackageSpec(url="https://github.com/sglyon/ORCA.jl.git", rev="master"), + # PackageSpec(name="PlotlyJS"), + # PackageSpec(name="Blink"), + # PackageSpec(name="ORCA"), # PyPlot: - PackageSpec(name="PyPlot"), - PackageSpec(name="PyCall"), - PackageSpec(name="LaTeXStrings"), + # PackageSpec(name="PyPlot"), + # PackageSpec(name="PyCall"), + # PackageSpec(name="LaTeXStrings"), ]) else push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) From 9c1a5548e1ce2b45417e1894d7fb22b8e222400c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 18 Sep 2018 23:50:13 +0200 Subject: [PATCH 027/230] small PGFPlots fix in backends.jl --- src/backends.jl | 67 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 77b6d261..7772b9a3 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -526,39 +526,40 @@ function add_backend_string(::PGFPlotsBackend) """ end -:annotations, -:background_color_legend, -:background_color_inside, -# :background_color_outside, -# :foreground_color_legend, -:foreground_color_grid, :foreground_color_axis, -:foreground_color_text, :foreground_color_border, -:label, -:seriescolor, :seriesalpha, -:linecolor, :linestyle, :linewidth, :linealpha, -:markershape, :markercolor, :markersize, :markeralpha, -:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, -:fillrange, :fillcolor, :fillalpha, -:bins, -# :bar_width, :bar_edges, -:title, -# :window_title, -:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, -:tickfont, :guidefont, :legendfont, -:grid, :legend, -:colorbar, :colorbar_title, -:fill_z, :line_z, :marker_z, :levels, -# :ribbon, :quiver, :arrow, -# :orientation, -# :overwrite_figure, -:polar, -# :normalize, :weights, :contours, -:aspect_ratio, -# :match_dimensions, -:tick_direction, -:framestyle, -:camera, -:contour_labels, +const _pgfplots_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, + :background_color_inside, + # :background_color_outside, + # :foreground_color_legend, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, + :label, + :seriescolor, :seriesalpha, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle, + :fillrange, :fillcolor, :fillalpha, + :bins, + # :bar_width, :bar_edges, + :title, + # :window_title, + :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :legend, + :colorbar, :colorbar_title, + :fill_z, :line_z, :marker_z, :levels, + # :ribbon, :quiver, :arrow, + # :orientation, + # :overwrite_figure, + :polar, + # :normalize, :weights, :contours, + :aspect_ratio, + # :match_dimensions, + :tick_direction, + :framestyle, + :camera, + :contour_labels, ]) const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] From b04e6ff699998bdfdcd750c918616d72ea9ee5b2 Mon Sep 17 00:00:00 2001 From: Fabian Greimel Date: Sat, 13 Oct 2018 14:07:19 +0200 Subject: [PATCH 028/230] GR: use correct attribute for axis color --- src/backends/gr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 267875f9..37c89767 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -855,12 +855,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # axis lines if xaxis[:showaxis] - gr_set_line(1, :solid, xaxis[:foreground_color_axis]) + gr_set_line(1, :solid, xaxis[:foreground_color_border]) GR.setclip(0) gr_polyline(coords(xspine_segs)...) end if yaxis[:showaxis] - gr_set_line(1, :solid, yaxis[:foreground_color_axis]) + gr_set_line(1, :solid, yaxis[:foreground_color_border]) GR.setclip(0) gr_polyline(coords(yspine_segs)...) end From d9be97fc450c2753d7c3a01d6c338fc39d3b61e1 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 14:09:43 +0200 Subject: [PATCH 029/230] fix pgfplots saving with FileIO --- src/examples.jl | 1 + src/init.jl | 24 ++++++++++++++++++++++++ src/output.jl | 24 ------------------------ test/imgcomp.jl | 4 ---- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/examples.jl b/src/examples.jl index a53707d9..762d857c 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -443,6 +443,7 @@ _backend_skips = Dict( :gr => [25, 30], :pyplot => [25, 30], :plotlyjs => [2, 21, 25, 30, 31], + :pgfplots => [2, 25, 30], ) # --------------------------------------------------------------------------------- diff --git a/src/init.jl b/src/init.jl index 08d1dd2b..545f55ea 100644 --- a/src/init.jl +++ b/src/init.jl @@ -80,4 +80,28 @@ function __init__() ENV["MPLBACKEND"] = "Agg" end end + + + + # --------------------------------------------------------- + # A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert + @require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin + PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend} + function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends}) + fn = tempname() + + # first save a pdf file + pdf(plt, fn) + + # load that pdf into a FileIO Stream + s = FileIO.load(fn * ".pdf") + + # save a png + pngfn = fn * ".png" + FileIO.save(pngfn, s) + + # now write from the file + write(io, read(open(pngfn), String)) + end + end end diff --git a/src/output.jl b/src/output.jl index 1122ab93..df6e3b84 100644 --- a/src/output.jl +++ b/src/output.jl @@ -210,30 +210,6 @@ _show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt) closeall() = closeall(backend()) -# --------------------------------------------------------- -# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert - -const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend} -if is_installed("FileIO") - @eval import FileIO - function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends}) - fn = tempname() - - # first save a pdf file - pdf(plt, fn) - - # load that pdf into a FileIO Stream - s = FileIO.load(fn * ".pdf") - - # save a png - pngfn = fn * ".png" - FileIO.save(pngfn, s) - - # now write from the file - write(io, read(open(pngfn), String)) - end -end - # function html_output_format(fmt) # if fmt == "png" # @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot) diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 64bfbeb2..526d695e 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -29,11 +29,7 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) -<<<<<<< HEAD -const _current_plots_version = v"0.20.3" -======= import Plots._current_plots_version ->>>>>>> move _current_plots_version from PlotDocs to Plots function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) From 22c3afd8a05dac8e821dc38d9e2e4e5b7716437a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 14:11:16 +0200 Subject: [PATCH 030/230] remove is_installed --- src/utils.jl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 0db12bc5..22d3df57 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -412,14 +412,6 @@ end isijulia() = :IJulia in nameof.(collect(values(Base.loaded_modules))) isatom() = :Atom in nameof.(collect(values(Base.loaded_modules))) -function is_installed(pkgstr::AbstractString) - try - Pkg.installed(pkgstr) === nothing ? false : true - catch - false - end -end - istuple(::Tuple) = true istuple(::Any) = false isvector(::AVec) = true From 04f502df8aeb8299e3e82dfeeeffa7917f7c0869 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 15:38:50 +0200 Subject: [PATCH 031/230] select pgfplots examples for docs --- src/examples.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples.jl b/src/examples.jl index 762d857c..7050b1e3 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -443,7 +443,7 @@ _backend_skips = Dict( :gr => [25, 30], :pyplot => [25, 30], :plotlyjs => [2, 21, 25, 30, 31], - :pgfplots => [2, 25, 30], + :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30], ) # --------------------------------------------------------------------------------- From 3e1ce8c2fa92fc013c1f6427a9e60860b1890803 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 15:51:02 +0200 Subject: [PATCH 032/230] really fix conflicts --- src/backends.jl | 20 -------------------- src/examples.jl | 3 --- 2 files changed, 23 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 57b55549..00ac483a 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -544,11 +544,7 @@ const _pgfplots_attr = merge_with_base_supported([ # :bar_width, :bar_edges, :title, # :window_title, -<<<<<<< HEAD :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, -======= - :guide, :lims, :ticks, :scale, :flip, :rotation, ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b :tickfont, :guidefont, :legendfont, :grid, :legend, :colorbar, :colorbar_title, @@ -564,11 +560,7 @@ const _pgfplots_attr = merge_with_base_supported([ :framestyle, :camera, :contour_labels, -<<<<<<< HEAD ]) -======= - ]) ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) @@ -641,11 +633,7 @@ const _pyplot_attr = merge_with_base_supported([ :bins, :bar_width, :bar_edges, :bar_position, :title, :title_location, :titlefont, :window_title, -<<<<<<< HEAD :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, -======= - :guide, :lims, :ticks, :scale, :flip, :rotation, ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b :titlefontfamily, :titlefontsize, :titlefontcolor, :legendfontfamily, :legendfontsize, :legendfontcolor, :tickfontfamily, :tickfontsize, :tickfontcolor, @@ -769,10 +757,7 @@ const _inspectdr_attr = merge_with_base_supported([ :foreground_color_legend, :foreground_color_title, :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, :label, -<<<<<<< HEAD :seriescolor, :seriesalpha, -======= ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b :linecolor, :linestyle, :linewidth, :linealpha, :markershape, :markercolor, :markersize, :markeralpha, :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, @@ -786,12 +771,7 @@ const _inspectdr_attr = merge_with_base_supported([ :legendfontfamily, :legendfontsize, :legendfontcolor, :tickfontfamily, :tickfontsize, :tickfontcolor, :guidefontfamily, :guidefontsize, :guidefontcolor, -<<<<<<< HEAD - :grid, #:gridalpha, :gridstyle, :gridlinewidth, #alhpa & linewidth are per plot - not per subplot - :legend, #:legendtitle, :colorbar, -======= :grid, :legend, #:colorbar, ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b # :marker_z, # :line_z, # :levels, diff --git a/src/examples.jl b/src/examples.jl index 6a757453..7050b1e3 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -443,10 +443,7 @@ _backend_skips = Dict( :gr => [25, 30], :pyplot => [25, 30], :plotlyjs => [2, 21, 25, 30, 31], -<<<<<<< HEAD :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30], -======= ->>>>>>> fc51c355a5c1db860ae18146a33f17f784031a4b ) # --------------------------------------------------------------------------------- From d3b51703f25c776cc0f00d87771db0f4d3c3e879 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 18:27:36 +0200 Subject: [PATCH 033/230] don't test for julia 0.7 on appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d2c44998..3490f07b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ environment: matrix: - - julia_version: 0.7 + # - julia_version: 0.7 - julia_version: 1 - julia_version: nightly From cb3cdbf6e71063e7223d470c0ad892c8109aba37 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 14 Oct 2018 19:10:12 +0200 Subject: [PATCH 034/230] prepare release --- NEWS.md | 6 ++++++ src/Plots.jl | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 57d2e2d2..703c2b2e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,12 @@ ## (current master) - All new development should target Julia 1.x! +## 0.20.6 +- fixes for PlotDocs.jl +- fix gr axis color argument +- Shapes for inspectdr +- don't load plotly js file by default + ## 0.20.5 - fix precompilation issue when depending on Plots diff --git a/src/Plots.jl b/src/Plots.jl index e1725084..0beda4f8 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,6 +1,6 @@ module Plots -_current_plots_version = v"0.20.1" +_current_plots_version = v"0.20.6" using Reexport From 957cea26387f5b3782b0377fed880db725716c51 Mon Sep 17 00:00:00 2001 From: yharel Date: Mon, 22 Oct 2018 03:11:26 +0300 Subject: [PATCH 035/230] function recipe: taking axis scales into account --- src/series.jl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/series.jl b/src/series.jl index bba91883..f3d22026 100644 --- a/src/series.jl +++ b/src/series.jl @@ -386,8 +386,9 @@ end xmin, xmax = try axis_limits(plt[1][:xaxis]) catch - xm = tryrange(f, [-5,-1,0,0.01]) - xm, tryrange(f, filter(x->x>xm, [5,1,0.99, 0, -0.01])) + xinv = invscalefunc(get(plotattributes, :xscale, :identity)) + xm = tryrange(f, xinv.([-5,-1,0,0.01])) + xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01]))) end f, xmin, xmax @@ -517,16 +518,23 @@ end # # # special handling... xmin/xmax with parametric function(s) @recipe function f(f::Function, xmin::Number, xmax::Number) - xs = adapted_grid(f, (xmin, xmax)) + xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)] + xs = _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) xs, f end @recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function - xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs] + xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)] + xs = Any[_scaled_adapted_grid(f, xscale, yscale, xmin, xmax) for f in fs] xs, fs end @recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u) @recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = fx, fy, range(umin, stop = umax, length = n) +function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) + (xf, xinv), (yf, yinv) = ((scalefunc(s),invscalefunc(s)) for s in (xscale,yscale)) + xinv.(adapted_grid(yf∘f∘xinv, xf.((xmin, xmax)))) +end + # # # special handling... 3D parametric function(s) @recipe function f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec) where {F<:Function,G<:Function,H<:Function} From 7062e8864bea7dab79cae9f1e5d37a9baf24a14e Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 23 Oct 2018 08:46:07 +0200 Subject: [PATCH 036/230] up GR version --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index a2a2f67f..aae86c2c 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.34.0 +GR 0.35.0 From 6e0522308a1a1ea0c3791a16234568327fbed593 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 23 Oct 2018 08:50:25 +0200 Subject: [PATCH 037/230] up GR version --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index a2a2f67f..aae86c2c 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.34.0 +GR 0.35.0 From 89d08606ade4dff8b61df8e29fc3a6b009df3b01 Mon Sep 17 00:00:00 2001 From: Filippo Vicentini Date: Tue, 23 Oct 2018 14:05:05 +0200 Subject: [PATCH 038/230] Mirror guides if :guide_position == :auto and :mirror == true Before, guides where mirrored only if guide_position was set. --- src/backends/gr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1ae84aab..d1039b53 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -903,7 +903,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:guide] != "" gr_set_font(guidefont(xaxis)) - if xaxis[:guide_position] == :top + if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide]) else @@ -915,7 +915,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:guide] != "" gr_set_font(guidefont(yaxis)) GR.setcharup(-1, 0) - if yaxis[:guide_position] == :left + if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) else From 6be79955001acd1e03d2273b7c04429f0fb2883a Mon Sep 17 00:00:00 2001 From: Filippo Vicentini Date: Tue, 23 Oct 2018 15:58:10 +0200 Subject: [PATCH 039/230] Add paddings to the side where the axis label is --- src/backends/gr.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index d1039b53..836276fd 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -602,11 +602,19 @@ function _update_min_padding!(sp::Subplot{GRBackend}) end # Add margin for x label if sp[:xaxis][:guide] != "" - bottompad += 4mm + if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true) + toppad += 4mm + else + bottompad += 4mm + end end # Add margin for y label if sp[:yaxis][:guide] != "" - leftpad += 4mm + if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true) + rightpad += 4mm + else + leftpad += 4mm + end end if sp[:colorbar_title] != "" rightpad += 4mm From 113e616d25596b748c8c13df15a7bd6476da6600 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 23 Oct 2018 17:53:25 +0200 Subject: [PATCH 040/230] remove FixedSizeArrays --- src/Plots.jl | 1 - src/components.jl | 8 ++++---- src/series.jl | 14 +++++++------- src/utils.jl | 12 ++++++------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 0beda4f8..0a6522d6 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -5,7 +5,6 @@ _current_plots_version = v"0.20.6" using Reexport import StaticArrays -using StaticArrays.FixedSizeArrays using Dates, Printf, Statistics, Base64, LinearAlgebra import SparseArrays: findnz diff --git a/src/components.jl b/src/components.jl index 8a35c95c..ddd78383 100644 --- a/src/components.jl +++ b/src/components.jl @@ -1,7 +1,7 @@ -const P2 = FixedSizeArrays.Vec{2,Float64} -const P3 = FixedSizeArrays.Vec{3,Float64} +const P2 = StaticArrays.SVector{2,Float64} +const P3 = StaticArrays.SVector{3,Float64} nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b)) nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b)) @@ -736,7 +736,7 @@ end # ----------------------------------------------------------------------- "create a BezierCurve for plotting" -mutable struct BezierCurve{T <: FixedSizeArrays.Vec} +mutable struct BezierCurve{T <: StaticArrays.SVector} control_points::Vector{T} end @@ -750,7 +750,7 @@ function (bc::BezierCurve)(t::Real) end # mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality -# mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array +# mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array @deprecate curve_points coords diff --git a/src/series.jl b/src/series.jl index bba91883..4ba187a3 100644 --- a/src/series.jl +++ b/src/series.jl @@ -539,7 +539,7 @@ end # # # # -------------------------------------------------------------------- -# # Lists of tuples and FixedSizeArrays +# # Lists of tuples and StaticArrays # # -------------------------------------------------------------------- # # # if we get an unhandled tuple, just splat it in @@ -561,14 +561,14 @@ end # -# # 2D FixedSizeArrays -@recipe f(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T<:Number} = unzip(xy) -@recipe f(xy::FixedSizeArrays.Vec{2,T}) where {T<:Number} = [xy[1]], [xy[2]] +# # 2D StaticArrays +@recipe f(xy::AVec{StaticArrays.SVector{2,T}}) where {T<:Number} = unzip(xy) +@recipe f(xy::StaticArrays.SVector{2,T}) where {T<:Number} = [xy[1]], [xy[2]] # -# # 3D FixedSizeArrays -@recipe f(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T<:Number} = unzip(xyz) -@recipe f(xyz::FixedSizeArrays.Vec{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] +# # 3D StaticArrays +@recipe f(xyz::AVec{StaticArrays.SVector{3,T}}) where {T<:Number} = unzip(xyz) +@recipe f(xyz::StaticArrays.SVector{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] # # # -------------------------------------------------------------------- diff --git a/src/utils.jl b/src/utils.jl index 22d3df57..c52ba186 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -287,14 +287,14 @@ unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz] unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv] -unzip(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy] -unzip(xy::FixedSizeArrays.Vec{2,T}) where {T} = T[xy[1]], T[xy[2]] +unzip(xy::AVec{StaticArrays.SVector{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy] +unzip(xy::StaticArrays.SVector{2,T}) where {T} = T[xy[1]], T[xy[2]] -unzip(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz] -unzip(xyz::FixedSizeArrays.Vec{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]] +unzip(xyz::AVec{StaticArrays.SVector{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz] +unzip(xyz::StaticArrays.SVector{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]] -unzip(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv] -unzip(xyuv::FixedSizeArrays.Vec{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]] +unzip(xyuv::AVec{StaticArrays.SVector{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv] +unzip(xyuv::StaticArrays.SVector{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]] # given 2-element lims and a vector of data x, widen lims to account for the extrema of x function _expand_limits(lims, x) From 5ea77cc4b66f01fb35473998b7a84d722541d92b Mon Sep 17 00:00:00 2001 From: Jonathan Anderson Date: Wed, 24 Oct 2018 16:45:23 -0500 Subject: [PATCH 041/230] Fallback to non gr3 surface call Taking an idea from @FlorianRhiem in this issue https://github.com/jheinen/GR.jl/issues/159, I figured I would fall back to GR if GR3 had an error. With this change, I was able to solve my issue in https://github.com/JuliaPlots/Plots.jl/issues/1781 --- src/backends/gr.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 836276fd..2b7fa542 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1058,7 +1058,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if length(x) == length(y) == length(z) GR.trisurface(x, y, z) else - GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH) + try + GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH) + catch + GR.surface(x, y, z, GR.OPTION_COLORED_MESH) + end end else GR.setfillcolorind(0) From 53964770827704b52dcce9b2bf395905ba780d9e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 30 Oct 2018 09:02:58 +0100 Subject: [PATCH 042/230] alow heatmap of nx1 or 1xn matrices --- src/backends/gr.jl | 4 ++-- src/utils.jl | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 836276fd..78d6bc7b 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -614,7 +614,7 @@ function _update_min_padding!(sp::Subplot{GRBackend}) rightpad += 4mm else leftpad += 4mm - end + end end if sp[:colorbar_title] != "" rightpad += 4mm @@ -671,7 +671,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) outside_ticks = true for ax in (sp[:xaxis], sp[:yaxis]) v = series[ax[:letter]] - if diff(collect(extrema(diff(v))))[1] > 1e-6*std(v) + if length(v) > 1 && diff(collect(extrema(diff(v))))[1] > 1e-6*std(v) @warn("GR: heatmap only supported with equally spaced data.") end end diff --git a/src/utils.jl b/src/utils.jl index c52ba186..2b4c5ea7 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -357,6 +357,7 @@ const _scale_base = Dict{Symbol, Real}( ) function _heatmap_edges(v::AVec) + length(v) == 1 && return v[1] .+ [-0.5, 0.5] vmin, vmax = ignorenan_extrema(v) extra_min = (v[2] - v[1]) / 2 extra_max = (v[end] - v[end - 1]) / 2 From f33d13518238ce660452d675020df54b6a701006 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 30 Oct 2018 11:41:27 +0100 Subject: [PATCH 043/230] More completely remove deprecated backends --- src/backends.jl | 7 +- src/deprecated/backends/bokeh.jl | 208 ----- src/deprecated/backends/gadfly.jl | 744 --------------- src/deprecated/backends/gadfly_shapes.jl | 93 -- src/deprecated/backends/immerse.jl | 186 ---- src/deprecated/backends/qwt.jl | 308 ------- src/deprecated/backends/winston.jl | 272 ------ src/deprecated/color_gradients.jl | 1067 ---------------------- src/deprecated/colors.jl | 415 --------- src/deprecated/contours.jl | 63 -- src/deprecated/series_args.jl | 99 -- src/utils.jl | 2 +- test/runtests.jl | 23 - 13 files changed, 2 insertions(+), 3485 deletions(-) delete mode 100644 src/deprecated/backends/bokeh.jl delete mode 100644 src/deprecated/backends/gadfly.jl delete mode 100644 src/deprecated/backends/gadfly_shapes.jl delete mode 100644 src/deprecated/backends/immerse.jl delete mode 100644 src/deprecated/backends/qwt.jl delete mode 100644 src/deprecated/backends/winston.jl delete mode 100644 src/deprecated/color_gradients.jl delete mode 100644 src/deprecated/colors.jl delete mode 100644 src/deprecated/contours.jl delete mode 100644 src/deprecated/series_args.jl diff --git a/src/backends.jl b/src/backends.jl index 00ac483a..d64db5e4 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -217,7 +217,7 @@ const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse] function warn_on_deprecated_backend(bsym::Symbol) if bsym in _deprecated_backends - @warn("Backend $bsym has been deprecated. It may not work as originally intended.") + @warn("Backend $bsym has been deprecated.") end end @@ -268,13 +268,8 @@ end -# @init_backend Immerse -# @init_backend Gadfly @init_backend PyPlot -# @init_backend Qwt @init_backend UnicodePlots -# @init_backend Winston -# @init_backend Bokeh @init_backend Plotly @init_backend PlotlyJS @init_backend GR diff --git a/src/deprecated/backends/bokeh.jl b/src/deprecated/backends/bokeh.jl deleted file mode 100644 index 9e906b75..00000000 --- a/src/deprecated/backends/bokeh.jl +++ /dev/null @@ -1,208 +0,0 @@ - -# https://github.com/bokeh/Bokeh.jl - - -supported_attrs(::BokehBackend) = merge_with_base_supported([ - # :annotations, - # :axis, - # :background_color, - :linecolor, - # :color_palette, - # :fillrange, - # :fillcolor, - # :fillalpha, - # :foreground_color, - :group, - # :label, - # :layout, - # :legend, - :seriescolor, :seriesalpha, - :linestyle, - :seriestype, - :linewidth, - # :linealpha, - :markershape, - :markercolor, - :markersize, - # :markeralpha, - # :markerstrokewidth, - # :markerstrokecolor, - # :markerstrokestyle, - # :n, - # :bins, - # :nc, - # :nr, - # :pos, - # :smooth, - # :show, - :size, - :title, - # :window_title, - :x, - # :xguide, - # :xlims, - # :xticks, - :y, - # :yguide, - # :ylims, - # :yrightlabel, - # :yticks, - # :xscale, - # :yscale, - # :xflip, - # :yflip, - # :z, - # :tickfont, - # :guidefont, - # :legendfont, - # :grid, - # :surface, - # :levels, - ]) -supported_types(::BokehBackend) = [:path, :scatter] -supported_styles(::BokehBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -supported_markers(::BokehBackend) = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] -supported_scales(::BokehBackend) = [:identity, :ln] -is_subplot_supported(::BokehBackend) = false - - -# -------------------------------------------------------------------------------------- - - - -function _initialize_backend(::BokehBackend; kw...) - @eval begin - @warn("Bokeh is no longer supported... many features will likely be broken.") - import Bokeh - export Bokeh - end -end - - -const _glyphtypes = KW( - :circle => :Circle, - :rect => :Square, - :diamond => :Diamond, - :utriangle => :Triangle, - :dtriangle => :InvertedTriangle, - # :pentagon => - # :hexagon => - # :heptagon => - # :octagon => - :cross => :Cross, - :xcross => :X, - :star5 => :Asterisk, - ) - - -function bokeh_glyph_type(plotattributes::KW) - st = plotattributes[:seriestype] - mt = plotattributes[:markershape] - if st == :scatter && mt == :none - mt = :circle - end - - # if we have a marker, use that - if st == :scatter || mt != :none - return _glyphtypes[mt] - end - - # otherwise return a line - return :Line -end - -function get_stroke_vector(linestyle::Symbol) - dash = 12 - dot = 3 - gap = 2 - linestyle == :solid && return Int[] - linestyle == :dash && return Int[dash, gap] - linestyle == :dot && return Int[dot, gap] - linestyle == :dashdot && return Int[dash, gap, dot, gap] - linestyle == :dashdotdot && return Int[dash, gap, dot, gap, dot, gap] - error("unsupported linestyle: ", linestyle) -end - -# --------------------------------------------------------------------------- - -# function _create_plot(pkg::BokehBackend, plotattributes::KW) -function _create_backend_figure(plt::Plot{BokehBackend}) - # TODO: create the window/canvas/context that is the plot within the backend (call it `o`) - # TODO: initialize the plot... title, xlabel, bgcolor, etc - - datacolumns = Bokeh.BokehDataSet[] - tools = Bokeh.tools() - filename = tempname() * ".html" - title = plt.attr[:title] - w, h = plt.attr[:size] - xaxis_type = plt.attr[:xscale] == :log10 ? :log : :auto - yaxis_type = plt.attr[:yscale] == :log10 ? :log : :auto - # legend = plt.attr[:legend] ? xxxx : nothing - legend = nothing - extra_args = KW() # TODO: we'll put extra settings (xlim, etc) here - Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args) - - # Plot(bplt, pkg, 0, plotattributes, KW[]) -end - - -# function _series_added(::BokehBackend, plt::Plot, plotattributes::KW) -function _series_added(plt::Plot{BokehBackend}, series::Series) - bdata = Dict{Symbol, Vector}(:x => collect(series.plotattributes[:x]), :y => collect(series.plotattributes[:y])) - - glyph = Bokeh.Bokehjs.Glyph( - glyphtype = bokeh_glyph_type(plotattributes), - linecolor = webcolor(plotattributes[:linecolor]), # shape's stroke or line color - linewidth = plotattributes[:linewidth], # shape's stroke width or line width - fillcolor = webcolor(plotattributes[:markercolor]), - size = ceil(Int, plotattributes[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends - dash = get_stroke_vector(plotattributes[:linestyle]) - ) - - legend = nothing # TODO - push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend)) - - # push!(plt.seriesargs, plotattributes) - # plt -end - -# ---------------------------------------------------------------- - -# TODO: override this to update plot items (title, xlabel, etc) after creation -function _update_plot_object(plt::Plot{BokehBackend}, plotattributes::KW) -end - -# ---------------------------------------------------------------- - -# accessors for x/y data - -# function getxy(plt::Plot{BokehBackend}, i::Int) -# series = plt.o.datacolumns[i].data -# series[:x], series[:y] -# end -# -# function setxy!(plt::Plot{BokehBackend}, xy::Tuple{X,Y}, i::Integer) -# series = plt.o.datacolumns[i].data -# series[:x], series[:y] = xy -# plt -# end - - - -# ---------------------------------------------------------------- - - -# ---------------------------------------------------------------- - -function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{BokehBackend}) - # TODO: write a png to io - @warn("mime png not implemented") -end - -function Base.display(::PlotsDisplay, plt::Plot{BokehBackend}) - Bokeh.showplot(plt.o) -end - -# function Base.display(::PlotsDisplay, plt::Subplot{BokehBackend}) -# # TODO: display/show the subplot -# end diff --git a/src/deprecated/backends/gadfly.jl b/src/deprecated/backends/gadfly.jl deleted file mode 100644 index 37dac678..00000000 --- a/src/deprecated/backends/gadfly.jl +++ /dev/null @@ -1,744 +0,0 @@ - -# https://github.com/dcjones/Gadfly.jl - - -supported_attrs(::GadflyBackend) = merge_with_base_supported([ - :annotations, - :background_color, :foreground_color, :color_palette, - :group, :label, :seriestype, - :seriescolor, :seriesalpha, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :n, :nc, :nr, :layout, :smooth, - :title, :window_title, :show, :size, - :x, :xguide, :xlims, :xticks, :xscale, :xflip, - :y, :yguide, :ylims, :yticks, :yscale, :yflip, - :z, - :tickfont, :guidefont, :legendfont, - :grid, :legend, :colorbar, - :marker_z, :levels, - :xerror, :yerror, - :ribbon, :quiver, - :orientation, - ]) -supported_types(::GadflyBackend) = [ - :path, - :scatter, :hexbin, - :bar, - :contour, :shape - ] -supported_styles(::GadflyBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -supported_markers(::GadflyBackend) = vcat(_allMarkers, Shape) -supported_scales(::GadflyBackend) = [:identity, :ln, :log2, :log10, :asinh, :sqrt] -is_subplot_supported(::GadflyBackend) = true - - -# -------------------------------------------------------------------------------------- - -function _initialize_backend(::GadflyBackend; kw...) - @eval begin - import Gadfly, Compose - export Gadfly, Compose - include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl")) - end -end - -# --------------------------------------------------------------------------- - -# immutable MissingVec <: AbstractVector{Float64} end -# Base.size(v::MissingVec) = (1,) -# Base.getindex(v::MissingVec, i::Integer) = 0.0 - -function createGadflyPlotObject(plotattributes::KW) - gplt = Gadfly.Plot() - gplt.mapping = Dict() - gplt.data_source = Gadfly.DataFrames.DataFrame() - # gplt.layers = gplt.layers[1:0] - gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());] - gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(plotattributes[:xguide]), - Gadfly.Guide.ylabel(plotattributes[:yguide]), - Gadfly.Guide.title(plotattributes[:title])] - gplt -end - -# --------------------------------------------------------------------------- - - -function getLineGeom(plotattributes::KW) - st = plotattributes[:seriestype] - xbins, ybins = maketuple(plotattributes[:bins]) - if st == :hexb - Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins) - elseif st == :histogram2d - Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins) - elseif st == :histogram - Gadfly.Geom.histogram(bincount = xbins, - orientation = isvertical(plotattributes) ? :vertical : :horizontal, - position = plotattributes[:bar_position] == :stack ? :stack : :dodge) - elseif st == :path - Gadfly.Geom.path - elseif st in (:bar, :sticks) - Gadfly.Geom.bar - elseif st == :steppost - Gadfly.Geom.step - elseif st == :steppre - Gadfly.Geom.step(direction = :vh) - elseif st == :hline - Gadfly.Geom.hline - elseif st == :vline - Gadfly.Geom.vline - elseif st == :contour - Gadfly.Geom.contour(levels = plotattributes[:levels]) - # elseif st == :shape - # Gadfly.Geom.polygon(fill = true, preserve_order = true) - else - nothing - end -end - -function get_extra_theme_args(plotattributes::KW, k::Symbol) - # gracefully handles old Gadfly versions - extra_theme_args = KW() - try - extra_theme_args[:line_style] = Gadfly.get_stroke_vector(plotattributes[k]) - catch err - if string(err) == "UndefVarError(:get_stroke_vector)" - Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?") - else - rethrow() - end - end - extra_theme_args -end - -function getGadflyLineTheme(plotattributes::KW) - st = plotattributes[:seriestype] - lc = convertColor(getColor(plotattributes[:linecolor]), plotattributes[:linealpha]) - fc = convertColor(getColor(plotattributes[:fillcolor]), plotattributes[:fillalpha]) - - Gadfly.Theme(; - default_color = (st in (:histogram,:histogram2d,:hexbin,:bar,:sticks) ? fc : lc), - line_width = (st == :sticks ? 1 : plotattributes[:linewidth]) * Gadfly.px, - # line_style = Gadfly.get_stroke_vector(plotattributes[:linestyle]), - lowlight_color = x->RGB(fc), # fill/ribbon - lowlight_opacity = alpha(fc), # fill/ribbon - bar_highlight = RGB(lc), # bars - get_extra_theme_args(plotattributes, :linestyle)... - ) -end - -# add a line as a new layer -function addGadflyLine!(plt::Plot, numlayers::Int, plotattributes::KW, geoms...) - gplt = getGadflyContext(plt) - gfargs = vcat(geoms..., getGadflyLineTheme(plotattributes)) - kwargs = KW() - st = plotattributes[:seriestype] - - # add a fill? - if plotattributes[:fillrange] != nothing && st != :contour - fillmin, fillmax = map(makevec, maketuple(plotattributes[:fillrange])) - nmin, nmax = length(fillmin), length(fillmax) - kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])] - kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])] - push!(gfargs, Gadfly.Geom.ribbon) - end - - if st in (:hline, :vline) - kwargs[st == :hline ? :yintercept : :xintercept] = plotattributes[:y] - - else - if st == :sticks - w = 0.01 * mean(diff(plotattributes[:x])) - kwargs[:xmin] = plotattributes[:x] - w - kwargs[:xmax] = plotattributes[:x] + w - elseif st == :contour - kwargs[:z] = plotattributes[:z].surf - addGadflyContColorScale(plt, plotattributes[:linecolor]) - end - - kwargs[:x] = plotattributes[st == :histogram ? :y : :x] - kwargs[:y] = plotattributes[:y] - - end - - # # add the layer - Gadfly.layer(gfargs...; order=numlayers, kwargs...) -end - - -# --------------------------------------------------------------------------- - -get_shape(sym::Symbol) = _shapes[sym] -get_shape(shape::Shape) = shape - -# extract the underlying ShapeGeometry object(s) -getMarkerGeom(shapes::AVec) = gadflyshape(map(get_shape, shapes)) -getMarkerGeom(other) = gadflyshape(get_shape(other)) - -# getMarkerGeom(shape::Shape) = gadflyshape(shape) -# getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape]) -# getMarkerGeom(shapes::AVec) = gadflyshape(map(gadflyshape, shapes)) # map(getMarkerGeom, shapes) -function getMarkerGeom(plotattributes::KW) - if plotattributes[:seriestype] == :shape - Gadfly.Geom.polygon(fill = true, preserve_order = true) - else - getMarkerGeom(plotattributes[:markershape]) - end -end - -function getGadflyMarkerTheme(plotattributes::KW, attr::KW) - c = getColor(plotattributes[:markercolor]) - α = plotattributes[:markeralpha] - if α != nothing - c = RGBA(RGB(c), α) - end - - ms = plotattributes[:markersize] - ms = if typeof(ms) <: AVec - @warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))") - mean(ms) * Gadfly.px - else - ms * Gadfly.px - end - - Gadfly.Theme(; - default_color = c, - default_point_size = ms, - discrete_highlight_color = c -> RGB(getColor(plotattributes[:markerstrokecolor])), - highlight_width = plotattributes[:markerstrokewidth] * Gadfly.px, - line_width = plotattributes[:markerstrokewidth] * Gadfly.px, - # get_extra_theme_args(plotattributes, :markerstrokestyle)... - ) -end - -function addGadflyContColorScale(plt::Plot{GadflyBackend}, c) - plt.attr[:colorbar] == :none && return - if !isa(c, ColorGradient) - c = default_gradient() - end - push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p)))) -end - -function addGadflyMarker!(plt::Plot, numlayers::Int, plotattributes::KW, attr::KW, geoms...) - gfargs = vcat(geoms..., getGadflyMarkerTheme(plotattributes, attr), getMarkerGeom(plotattributes)) - kwargs = KW() - - # handle continuous color scales for the markers - zcolor = plotattributes[:marker_z] - if zcolor != nothing && typeof(zcolor) <: AVec - kwargs[:color] = zcolor - addGadflyContColorScale(plt, plotattributes[:markercolor]) - end - - Gadfly.layer(gfargs...; x = plotattributes[:x], y = plotattributes[:y], order=numlayers, kwargs...) -end - - -# --------------------------------------------------------------------------- - -function addToGadflyLegend(plt::Plot, plotattributes::KW) - if plt.attr[:legend] != :none && plotattributes[:label] != "" - gplt = getGadflyContext(plt) - - # add the legend if needed - if all(g -> !isa(g, Gadfly.Guide.ManualColorKey), gplt.guides) - pushfirst!(gplt.guides, Gadfly.Guide.manual_color_key("", AbstractString[], Color[])) - end - - # now add the series to the legend - for guide in gplt.guides - if isa(guide, Gadfly.Guide.ManualColorKey) - # TODO: there's a BUG in gadfly if you pass in the same color more than once, - # since gadfly will call unique(colors), but doesn't also merge the rows that match - # Should ensure from this side that colors which are the same are merged together - - c = getColor(plotattributes[plotattributes[:markershape] == :none ? :linecolor : :markercolor]) - foundit = false - - # extend the label if we found this color - for i in 1:length(guide.colors) - if RGB(c) == guide.colors[i] - guide.labels[i] *= ", " * plotattributes[:label] - foundit = true - end - end - - # didn't find the color, so add a new entry into the legend - if !foundit - push!(guide.labels, plotattributes[:label]) - push!(guide.colors, c) - end - end - end - end -end - -getGadflySmoothing(smooth::Bool) = smooth ? [Gadfly.Geom.smooth(method=:lm)] : Any[] -getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))] - - -function addGadflySeries!(plt::Plot, plotattributes::KW) - layers = Gadfly.Layer[] - gplt = getGadflyContext(plt) - - # add a regression line? - # TODO: make more flexible - smooth = getGadflySmoothing(plotattributes[:smooth]) - - # lines - geom = getLineGeom(plotattributes) - if geom != nothing - prepend!(layers, addGadflyLine!(plt, length(gplt.layers), plotattributes, geom, smooth...)) - smooth = Any[] # don't add a regression for markers too - end - - # special handling for ohlc and scatter - st = plotattributes[:seriestype] - # if st == :ohlc - # error("Haven't re-implemented after refactoring") - if st in (:histogram2d, :hexbin) && (isa(plotattributes[:fillcolor], ColorGradient) || isa(plotattributes[:fillcolor], ColorFunction)) - push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(plotattributes[:fillcolor], p)))) - elseif st == :scatter && plotattributes[:markershape] == :none - plotattributes[:markershape] = :circle - end - - # markers - if plotattributes[:markershape] != :none || st == :shape - prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), plotattributes, plt.attr, smooth...)) - end - - st in (:histogram2d, :hexbin, :contour) || addToGadflyLegend(plt, plotattributes) - - # now save the layers that apply to this series - plotattributes[:gadflylayers] = layers - prepend!(gplt.layers, layers) -end - - -# --------------------------------------------------------------------------- - -# NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments - -# # colorgroup -# z = plotattributes[:z] - -# # handle line segments of different colors -# cscheme = plotattributes[:linecolor] -# if isa(cscheme, ColorVector) -# # create a color scale, and set the color group to the index of the color -# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...)) - -# # this is super weird, but... oh well... for some reason this creates n separate line segments... -# # create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y) -# # then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n] -# csindices = Int[mod1(i,length(cscheme.v)) for i in 1:length(plotattributes[:y])] -# cs = collect(repeat(csindices', 2, 1))[1:end-1] -# grp = collect(repeat((1:length(plotattributes[:y]))', 2, 1))[1:end-1] -# plotattributes[:x], plotattributes[:y] = map(createSegments, (plotattributes[:x], plotattributes[:y])) -# colorgroup = [(:linecolor, cs), (:group, grp)] - - -# --------------------------------------------------------------------------- - - -function addGadflyTicksGuide(gplt, ticks, isx::Bool) - ticks == :auto && return - - # remove the ticks? - if ticks in (:none, false, nothing) - return addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false) - end - - ttype = ticksType(ticks) - - # just the values... put ticks here, but use standard labels - if ttype == :ticks - gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks - replaceType(gplt.guides, gtype(ticks = collect(ticks))) - - # set the ticks and the labels - # Note: this is pretty convoluted, but I think it works. We set the ticks using Gadfly.Guide, - # and then set the label function (wraps a dict lookup) through a continuous Gadfly.Scale. - elseif ttype == :ticks_and_labels - gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks - replaceType(gplt.guides, gtype(ticks = collect(ticks[1]))) - - # # TODO add xtick_label function (given tick, return label??) - # # Scale.x_discrete(; labels=nothing, levels=nothing, order=nothing) - # filterGadflyScale(gplt, isx) - # gfunc = isx ? Gadfly.Scale.x_discrete : Gadfly.Scale.y_discrete - # labelmap = Dict(zip(ticks...)) - # labelfunc = val -> labelmap[val] - # push!(gplt.scales, gfunc(levels = collect(ticks[1]), labels = labelfunc)) - - filterGadflyScale(gplt, isx) - gfunc = isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous - labelmap = Dict(zip(ticks...)) - labelfunc = val -> labelmap[val] - push!(gplt.scales, gfunc(labels = labelfunc)) - - else - error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks) - end -end - -continuousAndSameAxis(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y) -filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales) - - -function getGadflyScaleFunction(plotattributes::KW, isx::Bool) - scalekey = isx ? :xscale : :yscale - hasScaleKey = haskey(plotattributes, scalekey) - if hasScaleKey - scale = plotattributes[scalekey] - scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey, log - scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey, log2 - scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey, log10 - scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey, asinh - scale == :sqrt && return isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt, hasScaleKey, sqrt - end - isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous, hasScaleKey, identity -end - - -function addGadflyLimitsScale(gplt, plotattributes::KW, isx::Bool) - gfunc, hasScaleKey, func = getGadflyScaleFunction(plotattributes, isx) - - # do we want to add min/max limits for the axis? - limsym = isx ? :xlims : :ylims - limargs = Any[] - - # map :auto to nothing, otherwise add to limargs - lims = get(plotattributes, limsym, :auto) - if lims == :auto - lims = nothing - else - if limsType(lims) == :limits - push!(limargs, (:minvalue, min(lims...))) - push!(limargs, (:maxvalue, max(lims...))) - else - error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims) - end - end - - # replace any current scales with this one - if hasScaleKey || !isempty(limargs) - filterGadflyScale(gplt, isx) - push!(gplt.scales, gfunc(; limargs...)) - end - - lims, func -end - -function updateGadflyAxisFlips(gplt, plotattributes::KW, xlims, ylims, xfunc, yfunc) - if isa(gplt.coord, Gadfly.Coord.Cartesian) - gplt.coord = Gadfly.Coord.cartesian( - gplt.coord.xvars, - gplt.coord.yvars; - xmin = xlims == nothing ? gplt.coord.xmin : xfunc(minimum(xlims)), - xmax = xlims == nothing ? gplt.coord.xmax : xfunc(maximum(xlims)), - ymin = ylims == nothing ? gplt.coord.ymin : yfunc(minimum(ylims)), - ymax = ylims == nothing ? gplt.coord.ymax : yfunc(maximum(ylims)), - xflip = get(plotattributes, :xflip, gplt.coord.xflip), - yflip = get(plotattributes, :yflip, gplt.coord.yflip), - fixed = gplt.coord.fixed, - aspect_ratio = gplt.coord.aspect_ratio, - raster = gplt.coord.raster - ) - else - gplt.coord = Gadfly.Coord.Cartesian( - xflip = get(plotattributes, :xflip, false), - yflip = get(plotattributes, :yflip, false) - ) - end -end - - -function findGuideAndSet(gplt, t::DataType, args...; kw...) - for (i,guide) in enumerate(gplt.guides) - if isa(guide, t) - gplt.guides[i] = t(args...; kw...) - end - end -end - -function updateGadflyGuides(plt::Plot, plotattributes::KW) - gplt = getGadflyContext(plt) - haskey(plotattributes, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(plotattributes[:title])) - haskey(plotattributes, :xguide) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(plotattributes[:xguide])) - haskey(plotattributes, :yguide) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(plotattributes[:yguide])) - - xlims, xfunc = addGadflyLimitsScale(gplt, plotattributes, true) - ylims, yfunc = addGadflyLimitsScale(gplt, plotattributes, false) - - ticks = get(plotattributes, :xticks, :auto) - if ticks == :none - _remove_axis(plt, true) - else - addGadflyTicksGuide(gplt, ticks, true) - end - ticks = get(plotattributes, :yticks, :auto) - if ticks == :none - _remove_axis(plt, false) - else - addGadflyTicksGuide(gplt, ticks, false) - end - - updateGadflyAxisFlips(gplt, plotattributes, xlims, ylims, xfunc, yfunc) -end - -function updateGadflyPlotTheme(plt::Plot, plotattributes::KW) - kwargs = KW() - - # colors - insidecolor, gridcolor, textcolor, guidecolor, legendcolor = - map(s -> getColor(plotattributes[s]), ( - :background_color_inside, - :foreground_color_grid, - :foreground_color_text, - :foreground_color_guide, - :foreground_color_legend - )) - - # # hide the legend? - leg = plotattributes[plotattributes[:legend] == :none ? :colorbar : :legend] - if leg != :best - kwargs[:key_position] = leg == :inside ? :right : leg - end - - if !get(plotattributes, :grid, true) - kwargs[:grid_color] = gridcolor - end - - # fonts - tfont, gfont, lfont = plotattributes[:tickfont], plotattributes[:guidefont], plotattributes[:legendfont] - - getGadflyContext(plt).theme = Gadfly.Theme(; - background_color = insidecolor, - minor_label_color = textcolor, - minor_label_font = tfont.family, - minor_label_font_size = tfont.pointsize * Gadfly.pt, - major_label_color = guidecolor, - major_label_font = gfont.family, - major_label_font_size = gfont.pointsize * Gadfly.pt, - key_title_color = guidecolor, - key_title_font = gfont.family, - key_title_font_size = gfont.pointsize * Gadfly.pt, - key_label_color = legendcolor, - key_label_font = lfont.family, - key_label_font_size = lfont.pointsize * Gadfly.pt, - plot_padding = 1 * Gadfly.mm, - kwargs... - ) -end - -# ---------------------------------------------------------------- - - -function createGadflyAnnotationObject(x, y, val::AbstractString) - Gadfly.Guide.annotation(Compose.compose( - Compose.context(), - Compose.text(x, y, val) - )) -end - -function createGadflyAnnotationObject(x, y, txt::PlotText) - halign = (txt.font.halign == :hcenter ? Compose.hcenter : (txt.font.halign == :left ? Compose.hleft : Compose.hright)) - valign = (txt.font.valign == :vcenter ? Compose.vcenter : (txt.font.valign == :top ? Compose.vtop : Compose.vbottom)) - rotations = (txt.font.rotation == 0.0 ? [] : [Compose.Rotation(txt.font.rotation, Compose.Point(Compose.x_measure(x), Compose.y_measure(y)))]) - Gadfly.Guide.annotation(Compose.compose( - Compose.context(), - Compose.text(x, y, txt.str, halign, valign, rotations...), - Compose.font(string(txt.font.family)), - Compose.fontsize(txt.font.pointsize * Gadfly.pt), - Compose.stroke(txt.font.color), - Compose.fill(txt.font.color) - )) -end - -function _add_annotations(plt::Plot{GadflyBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V} - for ann in anns - push!(plt.o.guides, createGadflyAnnotationObject(ann...)) - end -end - - -# --------------------------------------------------------------------------- - -# create a blank Gadfly.Plot object -# function _create_plot(pkg::GadflyBackend, plotattributes::KW) -# gplt = createGadflyPlotObject(plotattributes) -# Plot(gplt, pkg, 0, plotattributes, KW[]) -# end -function _create_backend_figure(plt::Plot{GadflyBackend}) - createGadflyPlotObject(plt.attr) -end - - -# plot one data series -# function _series_added(::GadflyBackend, plt::Plot, plotattributes::KW) -function _series_added(plt::Plot{GadflyBackend}, series::Series) - # first clear out the temporary layer - gplt = getGadflyContext(plt) - if gplt.layers[1].geom.tag == :remove - gplt.layers = gplt.layers[2:end] - end - - addGadflySeries!(plt, series.plotattributes) - # push!(plt.seriesargs, plotattributes) - # plt -end - - - -function _update_plot_object(plt::Plot{GadflyBackend}, plotattributes::KW) - updateGadflyGuides(plt, plotattributes) - updateGadflyPlotTheme(plt, plotattributes) -end - - -# ---------------------------------------------------------------- - -# accessors for x/y data - -# TODO: need to save all the layer indices which apply to this series -function getGadflyMappings(plt::Plot, i::Integer) - @assert i > 0 && i <= plt.n - mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]] -end - -function getxy(plt::Plot{GadflyBackend}, i::Integer) - mapping = getGadflyMappings(plt, i)[1] - mapping[:x], mapping[:y] -end - -function setxy!(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y} - for mapping in getGadflyMappings(plt, i) - mapping[:x], mapping[:y] = xy - end - plt -end - -# ---------------------------------------------------------------- - - -# # create the underlying object (each backend will do this differently) -# function _create_subplot(subplt::Subplot{GadflyBackend}, isbefore::Bool) -# isbefore && return false # wait until after plotting to create the subplots -# subplt.o = nothing -# true -# end - - -function _remove_axis(plt::Plot{GadflyBackend}, isx::Bool) - gplt = getGadflyContext(plt) - addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false) - addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "") -end - -function _expand_limits(lims, plt::Plot{GadflyBackend}, isx::Bool) - for l in getGadflyContext(plt).layers - _expand_limits(lims, l.mapping[isx ? :x : :y]) - end -end - - -# ---------------------------------------------------------------- - - -getGadflyContext(plt::Plot{GadflyBackend}) = plt.o -# getGadflyContext(subplt::Subplot{GadflyBackend}) = buildGadflySubplotContext(subplt) - -# # create my Compose.Context grid by hstacking and vstacking the Gadfly.Plot objects -# function buildGadflySubplotContext(subplt::Subplot) -# rows = Any[] -# row = Any[] -# for (i,(r,c)) in enumerate(subplt.layout) -# -# # add the Plot object to the row -# push!(row, getGadflyContext(subplt.plts[i])) -# -# # add the row -# if c == ncols(subplt.layout, r) -# push!(rows, Gadfly.hstack(row...)) -# row = Any[] -# end -# end -# -# # stack the rows -# Gadfly.vstack(rows...) -# end - -setGadflyDisplaySize(w,h) = Compose.set_default_graphic_size(w * Compose.px, h * Compose.px) -setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.attr[:size]...) -# setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getattr(subplt, 1)[:size]...) -# ------------------------------------------------------------------------- - - -function doshow(io::IO, func, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend} - gplt = getGadflyContext(plt) - setGadflyDisplaySize(plt) - Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt) -end - -getGadflyWriteFunc(::MIME"image/png") = Gadfly.PNG -getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG -# getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS -getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF -getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS -getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF -getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m) - -for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex") - @eval function Base.show(io::IO, ::$mime, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend} - func = getGadflyWriteFunc($mime()) - doshow(io, func, plt) - end -end - - - -function Base.display(::PlotsDisplay, plt::Plot{GadflyBackend}) - setGadflyDisplaySize(plt.attr[:size]...) - display(plt.o) -end - - -# function Base.display(::PlotsDisplay, subplt::Subplot{GadflyBackend}) -# setGadflyDisplaySize(getattr(subplt,1)[:size]...) -# ctx = buildGadflySubplotContext(subplt) -# -# # taken from Gadfly since I couldn't figure out how to do it directly -# -# filename = string(Gadfly.tempname(), ".html") -# output = open(filename, "w") -# -# plot_output = IOBuffer() -# Gadfly.draw(Gadfly.SVGJS(plot_output, Compose.default_graphic_width, -# Compose.default_graphic_height, false), ctx) -# plotsvg = takebuf_string(plot_output) -# -# write(output, -# """ -# -# -# -# Gadfly Plot -# -# -# -# -# -# $(plotsvg) -# -# -# """) -# close(output) -# Gadfly.open_file(filename) -# end diff --git a/src/deprecated/backends/gadfly_shapes.jl b/src/deprecated/backends/gadfly_shapes.jl deleted file mode 100644 index 1a818993..00000000 --- a/src/deprecated/backends/gadfly_shapes.jl +++ /dev/null @@ -1,93 +0,0 @@ - - -# Geometry which displays arbitrary shapes at given (x, y) positions. -# note: vertices is a list of shapes -struct ShapeGeometry <: Gadfly.GeometryElement - vertices::AbstractVector #{Tuple{Float64,Float64}} - tag::Symbol - - function ShapeGeometry(shape; tag::Symbol=Gadfly.Geom.empty_tag) - new(shape, tag) - end -end - -# TODO: add for PR -# const shape = ShapeGeometry - - -function Gadfly.element_aesthetics(::ShapeGeometry) - [:x, :y, :size, :color] -end - - -# Generate a form for a shape geometry. -# -# Args: -# geom: shape geometry. -# theme: the plot's theme. -# aes: aesthetics. -# -# Returns: -# A compose Form. -# -function Gadfly.render(geom::ShapeGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics) - - # TODO: add for PR - # Gadfly.assert_aesthetics_defined("Geom.shape", aes, :x, :y) - # Gadfly.assert_aesthetics_equal_length("Geom.shape", aes, - # element_aesthetics(geom)...) - - default_aes = Gadfly.Aesthetics() - default_aes.color = Gadfly.DataFrames.PooledDataArray(RGBA{Float32}[theme.default_color]) - default_aes.size = Compose.Measure[theme.default_point_size] - aes = Gadfly.inherit(aes, default_aes) - - lw_hover_scale = 10 - lw_ratio = theme.line_width / aes.size[1] - - aes_x, aes_y = Gadfly.concretize(aes.x, aes.y) - - ctx = Compose.compose!( - Compose.context(), - make_polygon(geom, aes.x, aes.y, aes.size), - Compose.fill(aes.color), - Compose.linewidth(theme.highlight_width)) - - if aes.color_key_continuous != nothing && aes.color_key_continuous - Compose.compose!(ctx, - Compose.stroke(map(theme.continuous_highlight_color, aes.color))) - else - Compose.compose!(ctx, - Compose.stroke(map(theme.discrete_highlight_color, aes.color)), - Compose.svgclass([Gadfly.svg_color_class_from_label(Gadfly.escape_id(aes.color_label([c])[1])) - for c in aes.color])) - end - - return Compose.compose!(Compose.context(order=4), Compose.svgclass("geometry"), ctx) -end - -function gadflyshape(sv::Shape) - ShapeGeometry(Any[vertices(sv)]) -end - -function gadflyshape(sv::AVec{Shape}) - ShapeGeometry(Any[vertices(s) for s in sv]) -end - - -# create a Compose context given a ShapeGeometry and the xs/ys/sizes -function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray, rs::AbstractArray) - n = max(length(xs), length(ys), length(rs)) - T = Tuple{Compose.Measure, Compose.Measure} - polys = Array(Vector{T}, n) - for i in 1:n - x = Compose.x_measure(xs[mod1(i, length(xs))]) - y = Compose.y_measure(ys[mod1(i, length(ys))]) - r = rs[mod1(i, length(rs))] - polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)] - end - Gadfly.polygon(polys, geom.tag) -end - - -# --------------------------------------------------------------------------------------------- diff --git a/src/deprecated/backends/immerse.jl b/src/deprecated/backends/immerse.jl deleted file mode 100644 index 754f55de..00000000 --- a/src/deprecated/backends/immerse.jl +++ /dev/null @@ -1,186 +0,0 @@ - -# https://github.com/JuliaGraphics/Immerse.jl - -supported_attrs(::ImmerseBackend) = supported_attrs(GadflyBackend()) -supported_types(::ImmerseBackend) = supported_types(GadflyBackend()) -supported_styles(::ImmerseBackend) = supported_styles(GadflyBackend()) -supported_markers(::ImmerseBackend) = supported_markers(GadflyBackend()) -supported_scales(::ImmerseBackend) = supported_scales(GadflyBackend()) -is_subplot_supported(::ImmerseBackend) = true - -# -------------------------------------------------------------------------------------- - -function _initialize_backend(::ImmerseBackend; kw...) - @eval begin - import Immerse, Gadfly, Compose, Gtk - export Immerse, Gadfly, Compose, Gtk - include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl")) - end -end - -function createImmerseFigure(plotattributes::KW) - w,h = plotattributes[:size] - figidx = Immerse.figure(; name = plotattributes[:window_title], width = w, height = h) - Immerse.Figure(figidx) -end - -# ---------------------------------------------------------------- - - -# create a blank Gadfly.Plot object -# function _create_plot(pkg::ImmerseBackend, plotattributes::KW) -# # create the underlying Gadfly.Plot object -# gplt = createGadflyPlotObject(plotattributes) -# -# # save both the Immerse.Figure and the Gadfly.Plot -# Plot((nothing,gplt), pkg, 0, plotattributes, KW[]) -# end -function _create_backend_figure(plt::Plot{ImmerseBackend}) - (nothing, createGadflyPlotObject(plt.attr)) -end - - -# # plot one data series -# function _series_added(::ImmerseBackend, plt::Plot, plotattributes::KW) -# addGadflySeries!(plt, plotattributes) -# push!(plt.seriesargs, plotattributes) -# plt -# end - -function _series_added(plt::Plot{ImmerseBackend}, series::Series) - addGadflySeries!(plt, series.plotattributes) -end - - -function _update_plot_object(plt::Plot{ImmerseBackend}, plotattributes::KW) - updateGadflyGuides(plt, plotattributes) - updateGadflyPlotTheme(plt, plotattributes) -end - - - -# ---------------------------------------------------------------- - -function _add_annotations(plt::Plot{ImmerseBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V} - for ann in anns - push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...)) - end -end - -# ---------------------------------------------------------------- - -# accessors for x/y data - -function getxy(plt::Plot{ImmerseBackend}, i::Integer) - mapping = getGadflyMappings(plt, i)[1] - mapping[:x], mapping[:y] -end - -function setxy!(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y} - for mapping in getGadflyMappings(plt, i) - mapping[:x], mapping[:y] = xy - end - plt -end - - -# ---------------------------------------------------------------- - - -# function _create_subplot(subplt::Subplot{ImmerseBackend}, isbefore::Bool) -# return false -# # isbefore && return false -# end -# -# function showSubplotObject(subplt::Subplot{ImmerseBackend}) -# # create the Gtk window with vertical box vsep -# plotattributes = getattr(subplt,1) -# w,h = plotattributes[:size] -# vsep = Gtk.GtkBoxLeaf(:v) -# win = Gtk.GtkWindowLeaf(vsep, plotattributes[:window_title], w, h) -# -# figindices = [] -# row = Gtk.GtkBoxLeaf(:h) -# push!(vsep, row) -# for (i,(r,c)) in enumerate(subplt.layout) -# plt = subplt.plts[i] -# -# # get the components... box is the main plot GtkBox, and canvas is the GtkCanvas where it's plotted -# box, toolbar, canvas = Immerse.createPlotGuiComponents() -# -# # add the plot's box to the row -# push!(row, box) -# -# # create the figure and store the index returned for destruction later -# figidx = Immerse.figure(canvas) -# push!(figindices, figidx) -# -# fig = Immerse.figure(figidx) -# plt.o = (fig, plt.o[2]) -# -# # add the row -# if c == ncols(subplt.layout, r) -# row = Gtk.GtkBoxLeaf(:h) -# push!(vsep, row) -# end -# -# end -# -# # destructor... clean up plots -# Gtk.on_signal_destroy((x...) -> ([Immerse.dropfig(Immerse._display,i) for i in figindices]; subplt.o = nothing), win) -# -# subplt.o = win -# true -# end - - -function _remove_axis(plt::Plot{ImmerseBackend}, isx::Bool) - gplt = getGadflyContext(plt) - addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false) - addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "") -end - -function _expand_limits(lims, plt::Plot{ImmerseBackend}, isx::Bool) - for l in getGadflyContext(plt).layers - _expand_limits(lims, l.mapping[isx ? :x : :y]) - end -end - - -# ---------------------------------------------------------------- - -getGadflyContext(plt::Plot{ImmerseBackend}) = plt.o[2] -# getGadflyContext(subplt::Subplot{ImmerseBackend}) = buildGadflySubplotContext(subplt) - - -function Base.display(::PlotsDisplay, plt::Plot{ImmerseBackend}) - - fig, gplt = plt.o - if fig == nothing - fig = createImmerseFigure(plt.attr) - Gtk.on_signal_destroy((x...) -> (Immerse.dropfig(Immerse._display, fig.figno); plt.o = (nothing,gplt)), fig.canvas) - plt.o = (fig, gplt) - end - - Immerse.figure(fig.figno; displayfig = false) - display(gplt) -end - - -# function Base.display(::PlotsDisplay, subplt::Subplot{ImmerseBackend}) -# -# # if we haven't created the window yet, do it -# if subplt.o == nothing -# showSubplotObject(subplt) -# end -# -# # display the plots by creating a fresh Immerse.Figure object from the GtkCanvas and Gadfly.Plot -# for plt in subplt.plts -# fig, gplt = plt.o -# Immerse.figure(fig.figno; displayfig = false) -# display(gplt) -# end -# -# # o is the window... show it -# showall(subplt.o) -# end diff --git a/src/deprecated/backends/qwt.jl b/src/deprecated/backends/qwt.jl deleted file mode 100644 index 0546b3db..00000000 --- a/src/deprecated/backends/qwt.jl +++ /dev/null @@ -1,308 +0,0 @@ - -# https://github.com/tbreloff/Qwt.jl - - -supported_attrs(::QwtBackend) = merge_with_base_supported([ - :annotations, - :linecolor, - :fillrange, - :fillcolor, - :label, - :legend, - :seriescolor, :seriesalpha, - :linestyle, - :linewidth, - :markershape, - :markercolor, - :markersize, - :bins, - :pos, - :title, - :window_title, - :guide, :lims, :ticks, :scale, - ]) -supported_types(::QwtBackend) = [:path, :scatter, :hexbin, :bar] -supported_markers(::QwtBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :star8, :hexagon] -supported_scales(::QwtBackend) = [:identity, :log10] -is_subplot_supported(::QwtBackend) = true - - -# -------------------------------------------------------------------------------------- - -function _initialize_backend(::QwtBackend; kw...) - @eval begin - @warn("Qwt is no longer supported... many features will likely be broken.") - import Qwt - export Qwt - end -end - -# ------------------------------- - -const _qwtAliases = KW( - :bins => :heatmap_n, - :fillrange => :fillto, - :linewidth => :width, - :markershape => :marker, - :hexbin => :heatmap, - :path => :line, - :steppost => :step, - :steppre => :stepinverted, - :star5 => :star1, - :star8 => :star2, - ) - -function fixcolors(plotattributes::KW) - for (k,v) in plotattributes - if typeof(v) <: ColorScheme - plotattributes[k] = getColor(v) - end - end -end - -function replaceQwtAliases(plotattributes, s) - if haskey(_qwtAliases, plotattributes[s]) - plotattributes[s] = _qwtAliases[plotattributes[s]] - end -end - -function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...) - plotattributes = KW(kw) - st = plotattributes[:seriestype] - if st == :scatter - plotattributes[:seriestype] = :none - if plotattributes[:markershape] == :none - plotattributes[:markershape] = :circle - end - - elseif st in (:hline, :vline) - addLineMarker(plt, plotattributes) - plotattributes[:seriestype] = :none - plotattributes[:markershape] = :circle - plotattributes[:markersize] = 1 - if st == :vline - plotattributes[:x], plotattributes[:y] = plotattributes[:y], plotattributes[:x] - end - - elseif !iscreating && st == :bar - plotattributes = barHack(; kw...) - elseif !iscreating && st == :histogram - plotattributes = barHack(; histogramHack(; kw...)...) - end - - replaceQwtAliases(plotattributes, :seriestype) - replaceQwtAliases(plotattributes, :markershape) - - for k in keys(plotattributes) - if haskey(_qwtAliases, k) - plotattributes[_qwtAliases[k]] = plotattributes[k] - end - end - - plotattributes[:x] = collect(plotattributes[:x]) - plotattributes[:y] = collect(plotattributes[:y]) - - plotattributes -end - -# function _create_plot(pkg::QwtBackend, plotattributes::KW) -function _create_backend_figure(plt::Plot{QwtBackend}) - fixcolors(plt.attr) - dumpdict(plt.attr,"\n\n!!! plot") - o = Qwt.plot(zeros(0,0); plt.attr..., show=false) - # plt = Plot(o, pkg, 0, plotattributes, KW[]) - # plt -end - -# function _series_added(::QwtBackend, plt::Plot, plotattributes::KW) -function _series_added(plt::Plot{QwtBackend}, series::Series) - plotattributes = adjustQwtKeywords(plt, false; series.plotattributes...) - fixcolors(plotattributes) - dumpdict(plotattributes,"\n\n!!! plot!") - Qwt.oplot(plt.o; plotattributes...) - # push!(plt.seriesargs, plotattributes) - # plt -end - - -# ---------------------------------------------------------------- - -function updateLimsAndTicks(plt::Plot{QwtBackend}, plotattributes::KW, isx::Bool) - lims = get(plotattributes, isx ? :xlims : :ylims, nothing) - ticks = get(plotattributes, isx ? :xticks : :yticks, nothing) - w = plt.o.widget - axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft] - - if typeof(lims) <: Union{Tuple,AVec} && length(lims) == 2 - if isx - plt.o.autoscale_x = false - else - plt.o.autoscale_y = false - end - w[:setAxisScale](axisid, lims...) - end - - if typeof(ticks) <: AbstractRange - if isx - plt.o.autoscale_x = false - else - plt.o.autoscale_y = false - end - w[:setAxisScale](axisid, float(minimum(ticks)), float(maximum(ticks)), float(step(ticks))) - elseif !(ticks in (nothing, :none, :auto)) - @warn("Only Range types are supported for Qwt xticks/yticks. typeof(ticks)=$(typeof(ticks))") - end - - # change the scale - scalesym = isx ? :xscale : :yscale - if haskey(plotattributes, scalesym) - scaletype = plotattributes[scalesym] - scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine()) - # scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e)) - # scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2)) - scaletype == :log10 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLog10ScaleEngine()) - scaletype in supported_scales() || @warn("Unsupported scale type: ", scaletype) - end - -end - - -function _update_plot_object(plt::Plot{QwtBackend}, plotattributes::KW) - haskey(plotattributes, :title) && Qwt.title(plt.o, plotattributes[:title]) - haskey(plotattributes, :xguide) && Qwt.xlabel(plt.o, plotattributes[:xguide]) - haskey(plotattributes, :yguide) && Qwt.ylabel(plt.o, plotattributes[:yguide]) - updateLimsAndTicks(plt, plotattributes, true) - updateLimsAndTicks(plt, plotattributes, false) -end - -function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, plotattributes::KW) - haskey(plotattributes, :size) && Qwt.resizewidget(plt.o, plotattributes[:size]...) - haskey(plotattributes, :pos) && Qwt.movewidget(plt.o, plotattributes[:pos]...) -end - - -# ---------------------------------------------------------------- - - # curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle))) -function addLineMarker(plt::Plot{QwtBackend}, plotattributes::KW) - for yi in plotattributes[:y] - marker = Qwt.QWT.QwtPlotMarker() - ishorizontal = (plotattributes[:seriestype] == :hline) - marker[:setLineStyle](ishorizontal ? 1 : 2) - marker[ishorizontal ? :setYValue : :setXValue](yi) - qcolor = Qwt.convertRGBToQColor(getColor(plotattributes[:linecolor])) - linestyle = plt.o.widget[:getLineStyle](string(plotattributes[:linestyle])) - marker[:setLinePen](Qwt.QT.QPen(qcolor, plotattributes[:linewidth], linestyle)) - marker[:attach](plt.o.widget) - end - - # marker[:setValue](x, y) - # marker[:setLabel](Qwt.QWT.QwtText(val)) - # marker[:attach](plt.o.widget) -end - -function createQwtAnnotation(plt::Plot, x, y, val::PlotText) - marker = Qwt.QWT.QwtPlotMarker() - marker[:setValue](x, y) - qwttext = Qwt.QWT.QwtText(val.str) - qwttext[:setFont](Qwt.QT.QFont(val.font.family, val.font.pointsize)) - qwttext[:setColor](Qwt.convertRGBToQColor(getColor(val.font.color))) - marker[:setLabel](qwttext) - marker[:attach](plt.o.widget) -end - -function createQwtAnnotation(plt::Plot, x, y, val::AbstractString) - marker = Qwt.QWT.QwtPlotMarker() - marker[:setValue](x, y) - marker[:setLabel](Qwt.QWT.QwtText(val)) - marker[:attach](plt.o.widget) -end - -function _add_annotations(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V} - for ann in anns - createQwtAnnotation(plt, ann...) - end -end - -# ---------------------------------------------------------------- - -# accessors for x/y data - -function getxy(plt::Plot{QwtBackend}, i::Int) - series = plt.o.lines[i] - series.x, series.y -end - -function setxy!(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y} - series = plt.o.lines[i] - series.x, series.y = xy - plt -end - - -# ------------------------------- - -# ------------------------------- - -# # create the underlying object (each backend will do this differently) -# function _create_subplot(subplt::Subplot{QwtBackend}, isbefore::Bool) -# isbefore && return false -# i = 0 -# rows = Any[] -# row = Any[] -# for (i,(r,c)) in enumerate(subplt.layout) -# push!(row, subplt.plts[i].o) -# if c == ncols(subplt.layout, r) -# push!(rows, Qwt.hsplitter(row...)) -# row = Any[] -# end -# end -# # for rowcnt in subplt.layout.rowcounts -# # push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...)) -# # i += rowcnt -# # end -# subplt.o = Qwt.vsplitter(rows...) -# # Qwt.resizewidget(subplt.o, getattr(subplt,1)[:size]...) -# # Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry -# true -# end - -function _expand_limits(lims, plt::Plot{QwtBackend}, isx::Bool) - for series in plt.o.lines - _expand_limits(lims, isx ? series.x : series.y) - end -end - - -function _remove_axis(plt::Plot{QwtBackend}, isx::Bool) -end - - -# ---------------------------------------------------------------- - -function Base.show(io::IO, ::MIME"image/png", plt::Plot{QwtBackend}) - Qwt.refresh(plt.o) - Qwt.savepng(plt.o, "/tmp/dfskjdhfkh.png") - write(io, readall("/tmp/dfskjdhfkh.png")) -end - -# function Base.show(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend}) -# for plt in subplt.plts -# Qwt.refresh(plt.o) -# end -# Qwt.savepng(subplt.o, "/tmp/dfskjdhfkh.png") -# write(io, readall("/tmp/dfskjdhfkh.png")) -# end - - -function Base.display(::PlotsDisplay, plt::Plot{QwtBackend}) - Qwt.refresh(plt.o) - Qwt.showwidget(plt.o) -end - -# function Base.display(::PlotsDisplay, subplt::Subplot{QwtBackend}) -# for plt in subplt.plts -# Qwt.refresh(plt.o) -# end -# Qwt.showwidget(subplt.o) -# end diff --git a/src/deprecated/backends/winston.jl b/src/deprecated/backends/winston.jl deleted file mode 100644 index 5f292271..00000000 --- a/src/deprecated/backends/winston.jl +++ /dev/null @@ -1,272 +0,0 @@ - -# https://github.com/nolta/Winston.jl - -# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation - -supported_attrs(::WinstonBackend) = merge_with_base_supported([ - :annotations, - :linecolor, - :fillrange, - :fillcolor, - :label, - :legend, - :seriescolor, :seriesalpha, - :linestyle, - :linewidth, - :markershape, - :markercolor, - :markersize, - :bins, - :title, - :window_title, - :guide, :lims, :scale, - ]) -supported_types(::WinstonBackend) = [:path, :scatter, :bar] -supported_styles(::WinstonBackend) = [:auto, :solid, :dash, :dot, :dashdot] -supported_markers(::WinstonBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] -supported_scales(::WinstonBackend) = [:identity, :log10] -is_subplot_supported(::WinstonBackend) = false - - -# -------------------------------------------------------------------------------------- - - -function _initialize_backend(::WinstonBackend; kw...) - @eval begin - # ENV["WINSTON_OUTPUT"] = "gtk" - @warn("Winston is no longer supported... many features will likely be broken.") - import Winston, Gtk - export Winston, Gtk - end -end - -# --------------------------------------------------------------------------- - - -## dictionaries for conversion of Plots.jl names to Winston ones. -const winston_linestyle = KW(:solid=>"solid", - :dash=>"dash", - :dot=>"dotted", - :dashdot=>"dotdashed" - ) - -const winston_marker = KW(:none=>".", - :rect => "square", - :circle=>"circle", - :diamond=>"diamond", - :utriangle=>"triangle", - :dtriangle=>"down-triangle", - :cross => "plus", - :xcross => "cross", - :star5 => "asterisk" - ) - -function _before_update(plt::Plot{WinstonBackend}) - Winston.ghf(plt.o) -end - -# --------------------------------------------------------------------------- - -function _create_backend_figure(plt::Plot{WinstonBackend}) - Winston.FramedPlot( - title = plt.attr[:title], - xlabel = plt.attr[:xguide], - ylabel = plt.attr[:yguide] - ) -end - -copy_remove(plotattributes::KW, s::Symbol) = delete!(copy(plotattributes), s) - -function addRegressionLineWinston(plotattributes::KW, wplt) - xs, ys = regressionXY(plotattributes[:x], plotattributes[:y]) - Winston.add(wplt, Winston.Curve(xs, ys, kind="dotted")) -end - -function getWinstonItems(plt::Plot) - if isa(plt.o, Winston.FramedPlot) - wplt = plt.o - window, canvas = nothing, nothing - else - window, canvas, wplt = plt.o - end - window, canvas, wplt -end - -function _series_added(plt::Plot{WinstonBackend}, series::Series) - plotattributes = series.plotattributes - window, canvas, wplt = getWinstonItems(plt) - - # until we call it normally, do the hack - if plotattributes[:seriestype] == :bar - plotattributes = barHack(;plotattributes...) - end - - - e = KW() - e[:color] = getColor(plotattributes[:linecolor]) - e[:linewidth] = plotattributes[:linewidth] - e[:kind] = winston_linestyle[plotattributes[:linestyle]] - e[:symbolkind] = winston_marker[plotattributes[:markershape]] - # markercolor # same choices as `color`, or :match will set the color to be the same as `color` - e[:symbolsize] = plotattributes[:markersize] / 5 - - # pos # (Int,Int), move the enclosing window to this position - # screen # Integer, move enclosing window to this screen number (for multiscreen desktops) - - - - ## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :histogram2d, :hexbin, :histogram, :bar - if plotattributes[:seriestype] == :none - Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor]))) - - elseif plotattributes[:seriestype] == :path - x, y = plotattributes[:x], plotattributes[:y] - Winston.add(wplt, Winston.Curve(x, y; e...)) - - fillrange = plotattributes[:fillrange] - if fillrange != nothing - if isa(fillrange, AbstractVector) - y2 = fillrange - else - y2 = Float64[fillrange for yi in y] - end - Winston.add(wplt, Winston.FillBetween(x, y, x, y2, fillcolor=getColor(plotattributes[:fillcolor]))) - end - - elseif plotattributes[:seriestype] == :scatter - if plotattributes[:markershape] == :none - plotattributes[:markershape] = :circle - end - - # elseif plotattributes[:seriestype] == :step - # fn = Winston.XXX - - # elseif plotattributes[:seriestype] == :stepinverted - # fn = Winston.XXX - - elseif plotattributes[:seriestype] == :sticks - Winston.add(wplt, Winston.Stems(plotattributes[:x], plotattributes[:y]; e...)) - - # elseif plotattributes[:seriestype] == :dots - # fn = Winston.XXX - - # elseif plotattributes[:seriestype] == :histogram2d - # fn = Winston.XXX - - # elseif plotattributes[:seriestype] == :hexbin - # fn = Winston.XXX - - elseif plotattributes[:seriestype] == :histogram - hst = hist(plotattributes[:y], plotattributes[:bins]) - Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :bins)...)) - - # elseif plotattributes[:seriestype] == :bar - # # fn = Winston.XXX - - else - error("seriestype $(plotattributes[:seriestype]) not supported by Winston.") - - end - - - # markershape - if plotattributes[:markershape] != :none - Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor]))) - end - - - # optionally add a regression line - plotattributes[:smooth] && plotattributes[:seriestype] != :histogram && addRegressionLineWinston(plotattributes, wplt) - - # push!(plt.seriesargs, plotattributes) - # plt -end - - -# ---------------------------------------------------------------- - -const _winstonNames = KW( - :xlims => :xrange, - :ylims => :yrange, - :xscale => :xlog, - :yscale => :ylog, - ) - -function _update_plot_object(plt::Plot{WinstonBackend}, plotattributes::KW) - window, canvas, wplt = getWinstonItems(plt) - for k in (:xguide, :yguide, :title, :xlims, :ylims) - if haskey(plotattributes, k) - Winston.setattr(wplt, string(get(_winstonNames, k, k)), plotattributes[k]) - end - end - - for k in (:xscale, :yscale) - if haskey(plotattributes, k) - islogscale = plotattributes[k] == :log10 - Winston.setattr(wplt, (k == :xscale ? :xlog : :ylog), islogscale) - end - end - -end - - - -# ---------------------------------------------------------------- - -function createWinstonAnnotationObject(plt::Plot{WinstonBackend}, x, y, val::AbstractString) - Winston.text(x, y, val) -end - -function _add_annotations(plt::Plot{WinstonBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V} - for ann in anns - createWinstonAnnotationObject(plt, ann...) - end -end - - -# ---------------------------------------------------------------- - -# function _create_subplot(subplt::Subplot{WinstonBackend}, isbefore::Bool) -# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example -# end - -# ---------------------------------------------------------------- - -function addWinstonLegend(plt::Plot, wplt) - if plt.attr[:legend] != :none - Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs]) - end -end - -function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{WinstonBackend}) - window, canvas, wplt = getWinstonItems(plt) - addWinstonLegend(plt, wplt) - show(io, "image/png", wplt) -end - - -function Base.display(::PlotsDisplay, plt::Plot{WinstonBackend}) - - window, canvas, wplt = getWinstonItems(plt) - - if window == nothing - if Winston.output_surface != :gtk - error("Gtk is the only supported display for Winston in Plots. Set `output_surface = gtk` in src/Winston.ini") - end - # initialize window - w,h = plt.attr[:size] - canvas = Gtk.GtkCanvasLeaf() - window = Gtk.GtkWindowLeaf(canvas, plt.attr[:window_title], w, h) - plt.o = (window, canvas, wplt) - end - - addWinstonLegend(plt, wplt) - - Winston.display(canvas, wplt) - Gtk.showall(window) -end - - -# function Base.display(::PlotsDisplay, subplt::Subplot{WinstonBackend}) -# # TODO: display/show the Subplot object -# end diff --git a/src/deprecated/color_gradients.jl b/src/deprecated/color_gradients.jl deleted file mode 100644 index 5516ac06..00000000 --- a/src/deprecated/color_gradients.jl +++ /dev/null @@ -1,1067 +0,0 @@ - -# -------------------------------------------------------------------------- -# -------------------------------------------------------------------------- -# The following gradients were taken from https://github.com/BIDS/colormap/blob/master/colormaps.py -# Here is the licensing note which accompanied this: - - # New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt, - # and (in the case of viridis) Eric Firing. - # - # This file and the colormaps in it are released under the CC0 license / - # public domain dedication. We would appreciate credit if you use or - # redistribute these colormaps, but do not impose any legal restrictions. - # - # To the extent possible under law, the persons who associated CC0 with - # mpl-colormaps have waived all copyright and related or neighboring rights - # to mpl-colormaps. - # - # You should have received a copy of the CC0 legalcode along with this - # work. If not, see . - -function sample_evenly(v::AVec, n::Integer = length(v)) - idx = Int[round(Int, x) for x in range(1, stop=length(v), length=n)] - v[idx] -end - -# note: to use the full arrays, just take out the second param (n) from the sample_evenly calls - -register_gradient_colors(:magma, sample_evenly([ - RGB(0.001462, 0.000466, 0.013866), - RGB(0.002258, 0.001295, 0.018331), - RGB(0.003279, 0.002305, 0.023708), - RGB(0.004512, 0.003490, 0.029965), - RGB(0.005950, 0.004843, 0.037130), - RGB(0.007588, 0.006356, 0.044973), - RGB(0.009426, 0.008022, 0.052844), - RGB(0.011465, 0.009828, 0.060750), - RGB(0.013708, 0.011771, 0.068667), - RGB(0.016156, 0.013840, 0.076603), - RGB(0.018815, 0.016026, 0.084584), - RGB(0.021692, 0.018320, 0.092610), - RGB(0.024792, 0.020715, 0.100676), - RGB(0.028123, 0.023201, 0.108787), - RGB(0.031696, 0.025765, 0.116965), - RGB(0.035520, 0.028397, 0.125209), - RGB(0.039608, 0.031090, 0.133515), - RGB(0.043830, 0.033830, 0.141886), - RGB(0.048062, 0.036607, 0.150327), - RGB(0.052320, 0.039407, 0.158841), - RGB(0.056615, 0.042160, 0.167446), - RGB(0.060949, 0.044794, 0.176129), - RGB(0.065330, 0.047318, 0.184892), - RGB(0.069764, 0.049726, 0.193735), - RGB(0.074257, 0.052017, 0.202660), - RGB(0.078815, 0.054184, 0.211667), - RGB(0.083446, 0.056225, 0.220755), - RGB(0.088155, 0.058133, 0.229922), - RGB(0.092949, 0.059904, 0.239164), - RGB(0.097833, 0.061531, 0.248477), - RGB(0.102815, 0.063010, 0.257854), - RGB(0.107899, 0.064335, 0.267289), - RGB(0.113094, 0.065492, 0.276784), - RGB(0.118405, 0.066479, 0.286321), - RGB(0.123833, 0.067295, 0.295879), - RGB(0.129380, 0.067935, 0.305443), - RGB(0.135053, 0.068391, 0.315000), - RGB(0.140858, 0.068654, 0.324538), - RGB(0.146785, 0.068738, 0.334011), - RGB(0.152839, 0.068637, 0.343404), - RGB(0.159018, 0.068354, 0.352688), - RGB(0.165308, 0.067911, 0.361816), - RGB(0.171713, 0.067305, 0.370771), - RGB(0.178212, 0.066576, 0.379497), - RGB(0.184801, 0.065732, 0.387973), - RGB(0.191460, 0.064818, 0.396152), - RGB(0.198177, 0.063862, 0.404009), - RGB(0.204935, 0.062907, 0.411514), - RGB(0.211718, 0.061992, 0.418647), - RGB(0.218512, 0.061158, 0.425392), - RGB(0.225302, 0.060445, 0.431742), - RGB(0.232077, 0.059889, 0.437695), - RGB(0.238826, 0.059517, 0.443256), - RGB(0.245543, 0.059352, 0.448436), - RGB(0.252220, 0.059415, 0.453248), - RGB(0.258857, 0.059706, 0.457710), - RGB(0.265447, 0.060237, 0.461840), - RGB(0.271994, 0.060994, 0.465660), - RGB(0.278493, 0.061978, 0.469190), - RGB(0.284951, 0.063168, 0.472451), - RGB(0.291366, 0.064553, 0.475462), - RGB(0.297740, 0.066117, 0.478243), - RGB(0.304081, 0.067835, 0.480812), - RGB(0.310382, 0.069702, 0.483186), - RGB(0.316654, 0.071690, 0.485380), - RGB(0.322899, 0.073782, 0.487408), - RGB(0.329114, 0.075972, 0.489287), - RGB(0.335308, 0.078236, 0.491024), - RGB(0.341482, 0.080564, 0.492631), - RGB(0.347636, 0.082946, 0.494121), - RGB(0.353773, 0.085373, 0.495501), - RGB(0.359898, 0.087831, 0.496778), - RGB(0.366012, 0.090314, 0.497960), - RGB(0.372116, 0.092816, 0.499053), - RGB(0.378211, 0.095332, 0.500067), - RGB(0.384299, 0.097855, 0.501002), - RGB(0.390384, 0.100379, 0.501864), - RGB(0.396467, 0.102902, 0.502658), - RGB(0.402548, 0.105420, 0.503386), - RGB(0.408629, 0.107930, 0.504052), - RGB(0.414709, 0.110431, 0.504662), - RGB(0.420791, 0.112920, 0.505215), - RGB(0.426877, 0.115395, 0.505714), - RGB(0.432967, 0.117855, 0.506160), - RGB(0.439062, 0.120298, 0.506555), - RGB(0.445163, 0.122724, 0.506901), - RGB(0.451271, 0.125132, 0.507198), - RGB(0.457386, 0.127522, 0.507448), - RGB(0.463508, 0.129893, 0.507652), - RGB(0.469640, 0.132245, 0.507809), - RGB(0.475780, 0.134577, 0.507921), - RGB(0.481929, 0.136891, 0.507989), - RGB(0.488088, 0.139186, 0.508011), - RGB(0.494258, 0.141462, 0.507988), - RGB(0.500438, 0.143719, 0.507920), - RGB(0.506629, 0.145958, 0.507806), - RGB(0.512831, 0.148179, 0.507648), - RGB(0.519045, 0.150383, 0.507443), - RGB(0.525270, 0.152569, 0.507192), - RGB(0.531507, 0.154739, 0.506895), - RGB(0.537755, 0.156894, 0.506551), - RGB(0.544015, 0.159033, 0.506159), - RGB(0.550287, 0.161158, 0.505719), - RGB(0.556571, 0.163269, 0.505230), - RGB(0.562866, 0.165368, 0.504692), - RGB(0.569172, 0.167454, 0.504105), - RGB(0.575490, 0.169530, 0.503466), - RGB(0.581819, 0.171596, 0.502777), - RGB(0.588158, 0.173652, 0.502035), - RGB(0.594508, 0.175701, 0.501241), - RGB(0.600868, 0.177743, 0.500394), - RGB(0.607238, 0.179779, 0.499492), - RGB(0.613617, 0.181811, 0.498536), - RGB(0.620005, 0.183840, 0.497524), - RGB(0.626401, 0.185867, 0.496456), - RGB(0.632805, 0.187893, 0.495332), - RGB(0.639216, 0.189921, 0.494150), - RGB(0.645633, 0.191952, 0.492910), - RGB(0.652056, 0.193986, 0.491611), - RGB(0.658483, 0.196027, 0.490253), - RGB(0.664915, 0.198075, 0.488836), - RGB(0.671349, 0.200133, 0.487358), - RGB(0.677786, 0.202203, 0.485819), - RGB(0.684224, 0.204286, 0.484219), - RGB(0.690661, 0.206384, 0.482558), - RGB(0.697098, 0.208501, 0.480835), - RGB(0.703532, 0.210638, 0.479049), - RGB(0.709962, 0.212797, 0.477201), - RGB(0.716387, 0.214982, 0.475290), - RGB(0.722805, 0.217194, 0.473316), - RGB(0.729216, 0.219437, 0.471279), - RGB(0.735616, 0.221713, 0.469180), - RGB(0.742004, 0.224025, 0.467018), - RGB(0.748378, 0.226377, 0.464794), - RGB(0.754737, 0.228772, 0.462509), - RGB(0.761077, 0.231214, 0.460162), - RGB(0.767398, 0.233705, 0.457755), - RGB(0.773695, 0.236249, 0.455289), - RGB(0.779968, 0.238851, 0.452765), - RGB(0.786212, 0.241514, 0.450184), - RGB(0.792427, 0.244242, 0.447543), - RGB(0.798608, 0.247040, 0.444848), - RGB(0.804752, 0.249911, 0.442102), - RGB(0.810855, 0.252861, 0.439305), - RGB(0.816914, 0.255895, 0.436461), - RGB(0.822926, 0.259016, 0.433573), - RGB(0.828886, 0.262229, 0.430644), - RGB(0.834791, 0.265540, 0.427671), - RGB(0.840636, 0.268953, 0.424666), - RGB(0.846416, 0.272473, 0.421631), - RGB(0.852126, 0.276106, 0.418573), - RGB(0.857763, 0.279857, 0.415496), - RGB(0.863320, 0.283729, 0.412403), - RGB(0.868793, 0.287728, 0.409303), - RGB(0.874176, 0.291859, 0.406205), - RGB(0.879464, 0.296125, 0.403118), - RGB(0.884651, 0.300530, 0.400047), - RGB(0.889731, 0.305079, 0.397002), - RGB(0.894700, 0.309773, 0.393995), - RGB(0.899552, 0.314616, 0.391037), - RGB(0.904281, 0.319610, 0.388137), - RGB(0.908884, 0.324755, 0.385308), - RGB(0.913354, 0.330052, 0.382563), - RGB(0.917689, 0.335500, 0.379915), - RGB(0.921884, 0.341098, 0.377376), - RGB(0.925937, 0.346844, 0.374959), - RGB(0.929845, 0.352734, 0.372677), - RGB(0.933606, 0.358764, 0.370541), - RGB(0.937221, 0.364929, 0.368567), - RGB(0.940687, 0.371224, 0.366762), - RGB(0.944006, 0.377643, 0.365136), - RGB(0.947180, 0.384178, 0.363701), - RGB(0.950210, 0.390820, 0.362468), - RGB(0.953099, 0.397563, 0.361438), - RGB(0.955849, 0.404400, 0.360619), - RGB(0.958464, 0.411324, 0.360014), - RGB(0.960949, 0.418323, 0.359630), - RGB(0.963310, 0.425390, 0.359469), - RGB(0.965549, 0.432519, 0.359529), - RGB(0.967671, 0.439703, 0.359810), - RGB(0.969680, 0.446936, 0.360311), - RGB(0.971582, 0.454210, 0.361030), - RGB(0.973381, 0.461520, 0.361965), - RGB(0.975082, 0.468861, 0.363111), - RGB(0.976690, 0.476226, 0.364466), - RGB(0.978210, 0.483612, 0.366025), - RGB(0.979645, 0.491014, 0.367783), - RGB(0.981000, 0.498428, 0.369734), - RGB(0.982279, 0.505851, 0.371874), - RGB(0.983485, 0.513280, 0.374198), - RGB(0.984622, 0.520713, 0.376698), - RGB(0.985693, 0.528148, 0.379371), - RGB(0.986700, 0.535582, 0.382210), - RGB(0.987646, 0.543015, 0.385210), - RGB(0.988533, 0.550446, 0.388365), - RGB(0.989363, 0.557873, 0.391671), - RGB(0.990138, 0.565296, 0.395122), - RGB(0.990871, 0.572706, 0.398714), - RGB(0.991558, 0.580107, 0.402441), - RGB(0.992196, 0.587502, 0.406299), - RGB(0.992785, 0.594891, 0.410283), - RGB(0.993326, 0.602275, 0.414390), - RGB(0.993834, 0.609644, 0.418613), - RGB(0.994309, 0.616999, 0.422950), - RGB(0.994738, 0.624350, 0.427397), - RGB(0.995122, 0.631696, 0.431951), - RGB(0.995480, 0.639027, 0.436607), - RGB(0.995810, 0.646344, 0.441361), - RGB(0.996096, 0.653659, 0.446213), - RGB(0.996341, 0.660969, 0.451160), - RGB(0.996580, 0.668256, 0.456192), - RGB(0.996775, 0.675541, 0.461314), - RGB(0.996925, 0.682828, 0.466526), - RGB(0.997077, 0.690088, 0.471811), - RGB(0.997186, 0.697349, 0.477182), - RGB(0.997254, 0.704611, 0.482635), - RGB(0.997325, 0.711848, 0.488154), - RGB(0.997351, 0.719089, 0.493755), - RGB(0.997351, 0.726324, 0.499428), - RGB(0.997341, 0.733545, 0.505167), - RGB(0.997285, 0.740772, 0.510983), - RGB(0.997228, 0.747981, 0.516859), - RGB(0.997138, 0.755190, 0.522806), - RGB(0.997019, 0.762398, 0.528821), - RGB(0.996898, 0.769591, 0.534892), - RGB(0.996727, 0.776795, 0.541039), - RGB(0.996571, 0.783977, 0.547233), - RGB(0.996369, 0.791167, 0.553499), - RGB(0.996162, 0.798348, 0.559820), - RGB(0.995932, 0.805527, 0.566202), - RGB(0.995680, 0.812706, 0.572645), - RGB(0.995424, 0.819875, 0.579140), - RGB(0.995131, 0.827052, 0.585701), - RGB(0.994851, 0.834213, 0.592307), - RGB(0.994524, 0.841387, 0.598983), - RGB(0.994222, 0.848540, 0.605696), - RGB(0.993866, 0.855711, 0.612482), - RGB(0.993545, 0.862859, 0.619299), - RGB(0.993170, 0.870024, 0.626189), - RGB(0.992831, 0.877168, 0.633109), - RGB(0.992440, 0.884330, 0.640099), - RGB(0.992089, 0.891470, 0.647116), - RGB(0.991688, 0.898627, 0.654202), - RGB(0.991332, 0.905763, 0.661309), - RGB(0.990930, 0.912915, 0.668481), - RGB(0.990570, 0.920049, 0.675675), - RGB(0.990175, 0.927196, 0.682926), - RGB(0.989815, 0.934329, 0.690198), - RGB(0.989434, 0.941470, 0.697519), - RGB(0.989077, 0.948604, 0.704863), - RGB(0.988717, 0.955742, 0.712242), - RGB(0.988367, 0.962878, 0.719649), - RGB(0.988033, 0.970012, 0.727077), - RGB(0.987691, 0.977154, 0.734536), - RGB(0.987387, 0.984288, 0.742002), - RGB(0.987053, 0.991438, 0.749504) -], 30)) - -register_gradient_colors(:inferno, sample_evenly([ - RGB(0.001462, 0.000466, 0.013866), - RGB(0.002267, 0.001270, 0.018570), - RGB(0.003299, 0.002249, 0.024239), - RGB(0.004547, 0.003392, 0.030909), - RGB(0.006006, 0.004692, 0.038558), - RGB(0.007676, 0.006136, 0.046836), - RGB(0.009561, 0.007713, 0.055143), - RGB(0.011663, 0.009417, 0.063460), - RGB(0.013995, 0.011225, 0.071862), - RGB(0.016561, 0.013136, 0.080282), - RGB(0.019373, 0.015133, 0.088767), - RGB(0.022447, 0.017199, 0.097327), - RGB(0.025793, 0.019331, 0.105930), - RGB(0.029432, 0.021503, 0.114621), - RGB(0.033385, 0.023702, 0.123397), - RGB(0.037668, 0.025921, 0.132232), - RGB(0.042253, 0.028139, 0.141141), - RGB(0.046915, 0.030324, 0.150164), - RGB(0.051644, 0.032474, 0.159254), - RGB(0.056449, 0.034569, 0.168414), - RGB(0.061340, 0.036590, 0.177642), - RGB(0.066331, 0.038504, 0.186962), - RGB(0.071429, 0.040294, 0.196354), - RGB(0.076637, 0.041905, 0.205799), - RGB(0.081962, 0.043328, 0.215289), - RGB(0.087411, 0.044556, 0.224813), - RGB(0.092990, 0.045583, 0.234358), - RGB(0.098702, 0.046402, 0.243904), - RGB(0.104551, 0.047008, 0.253430), - RGB(0.110536, 0.047399, 0.262912), - RGB(0.116656, 0.047574, 0.272321), - RGB(0.122908, 0.047536, 0.281624), - RGB(0.129285, 0.047293, 0.290788), - RGB(0.135778, 0.046856, 0.299776), - RGB(0.142378, 0.046242, 0.308553), - RGB(0.149073, 0.045468, 0.317085), - RGB(0.155850, 0.044559, 0.325338), - RGB(0.162689, 0.043554, 0.333277), - RGB(0.169575, 0.042489, 0.340874), - RGB(0.176493, 0.041402, 0.348111), - RGB(0.183429, 0.040329, 0.354971), - RGB(0.190367, 0.039309, 0.361447), - RGB(0.197297, 0.038400, 0.367535), - RGB(0.204209, 0.037632, 0.373238), - RGB(0.211095, 0.037030, 0.378563), - RGB(0.217949, 0.036615, 0.383522), - RGB(0.224763, 0.036405, 0.388129), - RGB(0.231538, 0.036405, 0.392400), - RGB(0.238273, 0.036621, 0.396353), - RGB(0.244967, 0.037055, 0.400007), - RGB(0.251620, 0.037705, 0.403378), - RGB(0.258234, 0.038571, 0.406485), - RGB(0.264810, 0.039647, 0.409345), - RGB(0.271347, 0.040922, 0.411976), - RGB(0.277850, 0.042353, 0.414392), - RGB(0.284321, 0.043933, 0.416608), - RGB(0.290763, 0.045644, 0.418637), - RGB(0.297178, 0.047470, 0.420491), - RGB(0.303568, 0.049396, 0.422182), - RGB(0.309935, 0.051407, 0.423721), - RGB(0.316282, 0.053490, 0.425116), - RGB(0.322610, 0.055634, 0.426377), - RGB(0.328921, 0.057827, 0.427511), - RGB(0.335217, 0.060060, 0.428524), - RGB(0.341500, 0.062325, 0.429425), - RGB(0.347771, 0.064616, 0.430217), - RGB(0.354032, 0.066925, 0.430906), - RGB(0.360284, 0.069247, 0.431497), - RGB(0.366529, 0.071579, 0.431994), - RGB(0.372768, 0.073915, 0.432400), - RGB(0.379001, 0.076253, 0.432719), - RGB(0.385228, 0.078591, 0.432955), - RGB(0.391453, 0.080927, 0.433109), - RGB(0.397674, 0.083257, 0.433183), - RGB(0.403894, 0.085580, 0.433179), - RGB(0.410113, 0.087896, 0.433098), - RGB(0.416331, 0.090203, 0.432943), - RGB(0.422549, 0.092501, 0.432714), - RGB(0.428768, 0.094790, 0.432412), - RGB(0.434987, 0.097069, 0.432039), - RGB(0.441207, 0.099338, 0.431594), - RGB(0.447428, 0.101597, 0.431080), - RGB(0.453651, 0.103848, 0.430498), - RGB(0.459875, 0.106089, 0.429846), - RGB(0.466100, 0.108322, 0.429125), - RGB(0.472328, 0.110547, 0.428334), - RGB(0.478558, 0.112764, 0.427475), - RGB(0.484789, 0.114974, 0.426548), - RGB(0.491022, 0.117179, 0.425552), - RGB(0.497257, 0.119379, 0.424488), - RGB(0.503493, 0.121575, 0.423356), - RGB(0.509730, 0.123769, 0.422156), - RGB(0.515967, 0.125960, 0.420887), - RGB(0.522206, 0.128150, 0.419549), - RGB(0.528444, 0.130341, 0.418142), - RGB(0.534683, 0.132534, 0.416667), - RGB(0.540920, 0.134729, 0.415123), - RGB(0.547157, 0.136929, 0.413511), - RGB(0.553392, 0.139134, 0.411829), - RGB(0.559624, 0.141346, 0.410078), - RGB(0.565854, 0.143567, 0.408258), - RGB(0.572081, 0.145797, 0.406369), - RGB(0.578304, 0.148039, 0.404411), - RGB(0.584521, 0.150294, 0.402385), - RGB(0.590734, 0.152563, 0.400290), - RGB(0.596940, 0.154848, 0.398125), - RGB(0.603139, 0.157151, 0.395891), - RGB(0.609330, 0.159474, 0.393589), - RGB(0.615513, 0.161817, 0.391219), - RGB(0.621685, 0.164184, 0.388781), - RGB(0.627847, 0.166575, 0.386276), - RGB(0.633998, 0.168992, 0.383704), - RGB(0.640135, 0.171438, 0.381065), - RGB(0.646260, 0.173914, 0.378359), - RGB(0.652369, 0.176421, 0.375586), - RGB(0.658463, 0.178962, 0.372748), - RGB(0.664540, 0.181539, 0.369846), - RGB(0.670599, 0.184153, 0.366879), - RGB(0.676638, 0.186807, 0.363849), - RGB(0.682656, 0.189501, 0.360757), - RGB(0.688653, 0.192239, 0.357603), - RGB(0.694627, 0.195021, 0.354388), - RGB(0.700576, 0.197851, 0.351113), - RGB(0.706500, 0.200728, 0.347777), - RGB(0.712396, 0.203656, 0.344383), - RGB(0.718264, 0.206636, 0.340931), - RGB(0.724103, 0.209670, 0.337424), - RGB(0.729909, 0.212759, 0.333861), - RGB(0.735683, 0.215906, 0.330245), - RGB(0.741423, 0.219112, 0.326576), - RGB(0.747127, 0.222378, 0.322856), - RGB(0.752794, 0.225706, 0.319085), - RGB(0.758422, 0.229097, 0.315266), - RGB(0.764010, 0.232554, 0.311399), - RGB(0.769556, 0.236077, 0.307485), - RGB(0.775059, 0.239667, 0.303526), - RGB(0.780517, 0.243327, 0.299523), - RGB(0.785929, 0.247056, 0.295477), - RGB(0.791293, 0.250856, 0.291390), - RGB(0.796607, 0.254728, 0.287264), - RGB(0.801871, 0.258674, 0.283099), - RGB(0.807082, 0.262692, 0.278898), - RGB(0.812239, 0.266786, 0.274661), - RGB(0.817341, 0.270954, 0.270390), - RGB(0.822386, 0.275197, 0.266085), - RGB(0.827372, 0.279517, 0.261750), - RGB(0.832299, 0.283913, 0.257383), - RGB(0.837165, 0.288385, 0.252988), - RGB(0.841969, 0.292933, 0.248564), - RGB(0.846709, 0.297559, 0.244113), - RGB(0.851384, 0.302260, 0.239636), - RGB(0.855992, 0.307038, 0.235133), - RGB(0.860533, 0.311892, 0.230606), - RGB(0.865006, 0.316822, 0.226055), - RGB(0.869409, 0.321827, 0.221482), - RGB(0.873741, 0.326906, 0.216886), - RGB(0.878001, 0.332060, 0.212268), - RGB(0.882188, 0.337287, 0.207628), - RGB(0.886302, 0.342586, 0.202968), - RGB(0.890341, 0.347957, 0.198286), - RGB(0.894305, 0.353399, 0.193584), - RGB(0.898192, 0.358911, 0.188860), - RGB(0.902003, 0.364492, 0.184116), - RGB(0.905735, 0.370140, 0.179350), - RGB(0.909390, 0.375856, 0.174563), - RGB(0.912966, 0.381636, 0.169755), - RGB(0.916462, 0.387481, 0.164924), - RGB(0.919879, 0.393389, 0.160070), - RGB(0.923215, 0.399359, 0.155193), - RGB(0.926470, 0.405389, 0.150292), - RGB(0.929644, 0.411479, 0.145367), - RGB(0.932737, 0.417627, 0.140417), - RGB(0.935747, 0.423831, 0.135440), - RGB(0.938675, 0.430091, 0.130438), - RGB(0.941521, 0.436405, 0.125409), - RGB(0.944285, 0.442772, 0.120354), - RGB(0.946965, 0.449191, 0.115272), - RGB(0.949562, 0.455660, 0.110164), - RGB(0.952075, 0.462178, 0.105031), - RGB(0.954506, 0.468744, 0.099874), - RGB(0.956852, 0.475356, 0.094695), - RGB(0.959114, 0.482014, 0.089499), - RGB(0.961293, 0.488716, 0.084289), - RGB(0.963387, 0.495462, 0.079073), - RGB(0.965397, 0.502249, 0.073859), - RGB(0.967322, 0.509078, 0.068659), - RGB(0.969163, 0.515946, 0.063488), - RGB(0.970919, 0.522853, 0.058367), - RGB(0.972590, 0.529798, 0.053324), - RGB(0.974176, 0.536780, 0.048392), - RGB(0.975677, 0.543798, 0.043618), - RGB(0.977092, 0.550850, 0.039050), - RGB(0.978422, 0.557937, 0.034931), - RGB(0.979666, 0.565057, 0.031409), - RGB(0.980824, 0.572209, 0.028508), - RGB(0.981895, 0.579392, 0.026250), - RGB(0.982881, 0.586606, 0.024661), - RGB(0.983779, 0.593849, 0.023770), - RGB(0.984591, 0.601122, 0.023606), - RGB(0.985315, 0.608422, 0.024202), - RGB(0.985952, 0.615750, 0.025592), - RGB(0.986502, 0.623105, 0.027814), - RGB(0.986964, 0.630485, 0.030908), - RGB(0.987337, 0.637890, 0.034916), - RGB(0.987622, 0.645320, 0.039886), - RGB(0.987819, 0.652773, 0.045581), - RGB(0.987926, 0.660250, 0.051750), - RGB(0.987945, 0.667748, 0.058329), - RGB(0.987874, 0.675267, 0.065257), - RGB(0.987714, 0.682807, 0.072489), - RGB(0.987464, 0.690366, 0.079990), - RGB(0.987124, 0.697944, 0.087731), - RGB(0.986694, 0.705540, 0.095694), - RGB(0.986175, 0.713153, 0.103863), - RGB(0.985566, 0.720782, 0.112229), - RGB(0.984865, 0.728427, 0.120785), - RGB(0.984075, 0.736087, 0.129527), - RGB(0.983196, 0.743758, 0.138453), - RGB(0.982228, 0.751442, 0.147565), - RGB(0.981173, 0.759135, 0.156863), - RGB(0.980032, 0.766837, 0.166353), - RGB(0.978806, 0.774545, 0.176037), - RGB(0.977497, 0.782258, 0.185923), - RGB(0.976108, 0.789974, 0.196018), - RGB(0.974638, 0.797692, 0.206332), - RGB(0.973088, 0.805409, 0.216877), - RGB(0.971468, 0.813122, 0.227658), - RGB(0.969783, 0.820825, 0.238686), - RGB(0.968041, 0.828515, 0.249972), - RGB(0.966243, 0.836191, 0.261534), - RGB(0.964394, 0.843848, 0.273391), - RGB(0.962517, 0.851476, 0.285546), - RGB(0.960626, 0.859069, 0.298010), - RGB(0.958720, 0.866624, 0.310820), - RGB(0.956834, 0.874129, 0.323974), - RGB(0.954997, 0.881569, 0.337475), - RGB(0.953215, 0.888942, 0.351369), - RGB(0.951546, 0.896226, 0.365627), - RGB(0.950018, 0.903409, 0.380271), - RGB(0.948683, 0.910473, 0.395289), - RGB(0.947594, 0.917399, 0.410665), - RGB(0.946809, 0.924168, 0.426373), - RGB(0.946392, 0.930761, 0.442367), - RGB(0.946403, 0.937159, 0.458592), - RGB(0.946903, 0.943348, 0.474970), - RGB(0.947937, 0.949318, 0.491426), - RGB(0.949545, 0.955063, 0.507860), - RGB(0.951740, 0.960587, 0.524203), - RGB(0.954529, 0.965896, 0.540361), - RGB(0.957896, 0.971003, 0.556275), - RGB(0.961812, 0.975924, 0.571925), - RGB(0.966249, 0.980678, 0.587206), - RGB(0.971162, 0.985282, 0.602154), - RGB(0.976511, 0.989753, 0.616760), - RGB(0.982257, 0.994109, 0.631017), - RGB(0.988362, 0.998364, 0.644924) -], 30)) - -register_gradient_colors(:plasma, sample_evenly([ - RGB(0.050383, 0.029803, 0.527975), - RGB(0.063536, 0.028426, 0.533124), - RGB(0.075353, 0.027206, 0.538007), - RGB(0.086222, 0.026125, 0.542658), - RGB(0.096379, 0.025165, 0.547103), - RGB(0.105980, 0.024309, 0.551368), - RGB(0.115124, 0.023556, 0.555468), - RGB(0.123903, 0.022878, 0.559423), - RGB(0.132381, 0.022258, 0.563250), - RGB(0.140603, 0.021687, 0.566959), - RGB(0.148607, 0.021154, 0.570562), - RGB(0.156421, 0.020651, 0.574065), - RGB(0.164070, 0.020171, 0.577478), - RGB(0.171574, 0.019706, 0.580806), - RGB(0.178950, 0.019252, 0.584054), - RGB(0.186213, 0.018803, 0.587228), - RGB(0.193374, 0.018354, 0.590330), - RGB(0.200445, 0.017902, 0.593364), - RGB(0.207435, 0.017442, 0.596333), - RGB(0.214350, 0.016973, 0.599239), - RGB(0.221197, 0.016497, 0.602083), - RGB(0.227983, 0.016007, 0.604867), - RGB(0.234715, 0.015502, 0.607592), - RGB(0.241396, 0.014979, 0.610259), - RGB(0.248032, 0.014439, 0.612868), - RGB(0.254627, 0.013882, 0.615419), - RGB(0.261183, 0.013308, 0.617911), - RGB(0.267703, 0.012716, 0.620346), - RGB(0.274191, 0.012109, 0.622722), - RGB(0.280648, 0.011488, 0.625038), - RGB(0.287076, 0.010855, 0.627295), - RGB(0.293478, 0.010213, 0.629490), - RGB(0.299855, 0.009561, 0.631624), - RGB(0.306210, 0.008902, 0.633694), - RGB(0.312543, 0.008239, 0.635700), - RGB(0.318856, 0.007576, 0.637640), - RGB(0.325150, 0.006915, 0.639512), - RGB(0.331426, 0.006261, 0.641316), - RGB(0.337683, 0.005618, 0.643049), - RGB(0.343925, 0.004991, 0.644710), - RGB(0.350150, 0.004382, 0.646298), - RGB(0.356359, 0.003798, 0.647810), - RGB(0.362553, 0.003243, 0.649245), - RGB(0.368733, 0.002724, 0.650601), - RGB(0.374897, 0.002245, 0.651876), - RGB(0.381047, 0.001814, 0.653068), - RGB(0.387183, 0.001434, 0.654177), - RGB(0.393304, 0.001114, 0.655199), - RGB(0.399411, 0.000859, 0.656133), - RGB(0.405503, 0.000678, 0.656977), - RGB(0.411580, 0.000577, 0.657730), - RGB(0.417642, 0.000564, 0.658390), - RGB(0.423689, 0.000646, 0.658956), - RGB(0.429719, 0.000831, 0.659425), - RGB(0.435734, 0.001127, 0.659797), - RGB(0.441732, 0.001540, 0.660069), - RGB(0.447714, 0.002080, 0.660240), - RGB(0.453677, 0.002755, 0.660310), - RGB(0.459623, 0.003574, 0.660277), - RGB(0.465550, 0.004545, 0.660139), - RGB(0.471457, 0.005678, 0.659897), - RGB(0.477344, 0.006980, 0.659549), - RGB(0.483210, 0.008460, 0.659095), - RGB(0.489055, 0.010127, 0.658534), - RGB(0.494877, 0.011990, 0.657865), - RGB(0.500678, 0.014055, 0.657088), - RGB(0.506454, 0.016333, 0.656202), - RGB(0.512206, 0.018833, 0.655209), - RGB(0.517933, 0.021563, 0.654109), - RGB(0.523633, 0.024532, 0.652901), - RGB(0.529306, 0.027747, 0.651586), - RGB(0.534952, 0.031217, 0.650165), - RGB(0.540570, 0.034950, 0.648640), - RGB(0.546157, 0.038954, 0.647010), - RGB(0.551715, 0.043136, 0.645277), - RGB(0.557243, 0.047331, 0.643443), - RGB(0.562738, 0.051545, 0.641509), - RGB(0.568201, 0.055778, 0.639477), - RGB(0.573632, 0.060028, 0.637349), - RGB(0.579029, 0.064296, 0.635126), - RGB(0.584391, 0.068579, 0.632812), - RGB(0.589719, 0.072878, 0.630408), - RGB(0.595011, 0.077190, 0.627917), - RGB(0.600266, 0.081516, 0.625342), - RGB(0.605485, 0.085854, 0.622686), - RGB(0.610667, 0.090204, 0.619951), - RGB(0.615812, 0.094564, 0.617140), - RGB(0.620919, 0.098934, 0.614257), - RGB(0.625987, 0.103312, 0.611305), - RGB(0.631017, 0.107699, 0.608287), - RGB(0.636008, 0.112092, 0.605205), - RGB(0.640959, 0.116492, 0.602065), - RGB(0.645872, 0.120898, 0.598867), - RGB(0.650746, 0.125309, 0.595617), - RGB(0.655580, 0.129725, 0.592317), - RGB(0.660374, 0.134144, 0.588971), - RGB(0.665129, 0.138566, 0.585582), - RGB(0.669845, 0.142992, 0.582154), - RGB(0.674522, 0.147419, 0.578688), - RGB(0.679160, 0.151848, 0.575189), - RGB(0.683758, 0.156278, 0.571660), - RGB(0.688318, 0.160709, 0.568103), - RGB(0.692840, 0.165141, 0.564522), - RGB(0.697324, 0.169573, 0.560919), - RGB(0.701769, 0.174005, 0.557296), - RGB(0.706178, 0.178437, 0.553657), - RGB(0.710549, 0.182868, 0.550004), - RGB(0.714883, 0.187299, 0.546338), - RGB(0.719181, 0.191729, 0.542663), - RGB(0.723444, 0.196158, 0.538981), - RGB(0.727670, 0.200586, 0.535293), - RGB(0.731862, 0.205013, 0.531601), - RGB(0.736019, 0.209439, 0.527908), - RGB(0.740143, 0.213864, 0.524216), - RGB(0.744232, 0.218288, 0.520524), - RGB(0.748289, 0.222711, 0.516834), - RGB(0.752312, 0.227133, 0.513149), - RGB(0.756304, 0.231555, 0.509468), - RGB(0.760264, 0.235976, 0.505794), - RGB(0.764193, 0.240396, 0.502126), - RGB(0.768090, 0.244817, 0.498465), - RGB(0.771958, 0.249237, 0.494813), - RGB(0.775796, 0.253658, 0.491171), - RGB(0.779604, 0.258078, 0.487539), - RGB(0.783383, 0.262500, 0.483918), - RGB(0.787133, 0.266922, 0.480307), - RGB(0.790855, 0.271345, 0.476706), - RGB(0.794549, 0.275770, 0.473117), - RGB(0.798216, 0.280197, 0.469538), - RGB(0.801855, 0.284626, 0.465971), - RGB(0.805467, 0.289057, 0.462415), - RGB(0.809052, 0.293491, 0.458870), - RGB(0.812612, 0.297928, 0.455338), - RGB(0.816144, 0.302368, 0.451816), - RGB(0.819651, 0.306812, 0.448306), - RGB(0.823132, 0.311261, 0.444806), - RGB(0.826588, 0.315714, 0.441316), - RGB(0.830018, 0.320172, 0.437836), - RGB(0.833422, 0.324635, 0.434366), - RGB(0.836801, 0.329105, 0.430905), - RGB(0.840155, 0.333580, 0.427455), - RGB(0.843484, 0.338062, 0.424013), - RGB(0.846788, 0.342551, 0.420579), - RGB(0.850066, 0.347048, 0.417153), - RGB(0.853319, 0.351553, 0.413734), - RGB(0.856547, 0.356066, 0.410322), - RGB(0.859750, 0.360588, 0.406917), - RGB(0.862927, 0.365119, 0.403519), - RGB(0.866078, 0.369660, 0.400126), - RGB(0.869203, 0.374212, 0.396738), - RGB(0.872303, 0.378774, 0.393355), - RGB(0.875376, 0.383347, 0.389976), - RGB(0.878423, 0.387932, 0.386600), - RGB(0.881443, 0.392529, 0.383229), - RGB(0.884436, 0.397139, 0.379860), - RGB(0.887402, 0.401762, 0.376494), - RGB(0.890340, 0.406398, 0.373130), - RGB(0.893250, 0.411048, 0.369768), - RGB(0.896131, 0.415712, 0.366407), - RGB(0.898984, 0.420392, 0.363047), - RGB(0.901807, 0.425087, 0.359688), - RGB(0.904601, 0.429797, 0.356329), - RGB(0.907365, 0.434524, 0.352970), - RGB(0.910098, 0.439268, 0.349610), - RGB(0.912800, 0.444029, 0.346251), - RGB(0.915471, 0.448807, 0.342890), - RGB(0.918109, 0.453603, 0.339529), - RGB(0.920714, 0.458417, 0.336166), - RGB(0.923287, 0.463251, 0.332801), - RGB(0.925825, 0.468103, 0.329435), - RGB(0.928329, 0.472975, 0.326067), - RGB(0.930798, 0.477867, 0.322697), - RGB(0.933232, 0.482780, 0.319325), - RGB(0.935630, 0.487712, 0.315952), - RGB(0.937990, 0.492667, 0.312575), - RGB(0.940313, 0.497642, 0.309197), - RGB(0.942598, 0.502639, 0.305816), - RGB(0.944844, 0.507658, 0.302433), - RGB(0.947051, 0.512699, 0.299049), - RGB(0.949217, 0.517763, 0.295662), - RGB(0.951344, 0.522850, 0.292275), - RGB(0.953428, 0.527960, 0.288883), - RGB(0.955470, 0.533093, 0.285490), - RGB(0.957469, 0.538250, 0.282096), - RGB(0.959424, 0.543431, 0.278701), - RGB(0.961336, 0.548636, 0.275305), - RGB(0.963203, 0.553865, 0.271909), - RGB(0.965024, 0.559118, 0.268513), - RGB(0.966798, 0.564396, 0.265118), - RGB(0.968526, 0.569700, 0.261721), - RGB(0.970205, 0.575028, 0.258325), - RGB(0.971835, 0.580382, 0.254931), - RGB(0.973416, 0.585761, 0.251540), - RGB(0.974947, 0.591165, 0.248151), - RGB(0.976428, 0.596595, 0.244767), - RGB(0.977856, 0.602051, 0.241387), - RGB(0.979233, 0.607532, 0.238013), - RGB(0.980556, 0.613039, 0.234646), - RGB(0.981826, 0.618572, 0.231287), - RGB(0.983041, 0.624131, 0.227937), - RGB(0.984199, 0.629718, 0.224595), - RGB(0.985301, 0.635330, 0.221265), - RGB(0.986345, 0.640969, 0.217948), - RGB(0.987332, 0.646633, 0.214648), - RGB(0.988260, 0.652325, 0.211364), - RGB(0.989128, 0.658043, 0.208100), - RGB(0.989935, 0.663787, 0.204859), - RGB(0.990681, 0.669558, 0.201642), - RGB(0.991365, 0.675355, 0.198453), - RGB(0.991985, 0.681179, 0.195295), - RGB(0.992541, 0.687030, 0.192170), - RGB(0.993032, 0.692907, 0.189084), - RGB(0.993456, 0.698810, 0.186041), - RGB(0.993814, 0.704741, 0.183043), - RGB(0.994103, 0.710698, 0.180097), - RGB(0.994324, 0.716681, 0.177208), - RGB(0.994474, 0.722691, 0.174381), - RGB(0.994553, 0.728728, 0.171622), - RGB(0.994561, 0.734791, 0.168938), - RGB(0.994495, 0.740880, 0.166335), - RGB(0.994355, 0.746995, 0.163821), - RGB(0.994141, 0.753137, 0.161404), - RGB(0.993851, 0.759304, 0.159092), - RGB(0.993482, 0.765499, 0.156891), - RGB(0.993033, 0.771720, 0.154808), - RGB(0.992505, 0.777967, 0.152855), - RGB(0.991897, 0.784239, 0.151042), - RGB(0.991209, 0.790537, 0.149377), - RGB(0.990439, 0.796859, 0.147870), - RGB(0.989587, 0.803205, 0.146529), - RGB(0.988648, 0.809579, 0.145357), - RGB(0.987621, 0.815978, 0.144363), - RGB(0.986509, 0.822401, 0.143557), - RGB(0.985314, 0.828846, 0.142945), - RGB(0.984031, 0.835315, 0.142528), - RGB(0.982653, 0.841812, 0.142303), - RGB(0.981190, 0.848329, 0.142279), - RGB(0.979644, 0.854866, 0.142453), - RGB(0.977995, 0.861432, 0.142808), - RGB(0.976265, 0.868016, 0.143351), - RGB(0.974443, 0.874622, 0.144061), - RGB(0.972530, 0.881250, 0.144923), - RGB(0.970533, 0.887896, 0.145919), - RGB(0.968443, 0.894564, 0.147014), - RGB(0.966271, 0.901249, 0.148180), - RGB(0.964021, 0.907950, 0.149370), - RGB(0.961681, 0.914672, 0.150520), - RGB(0.959276, 0.921407, 0.151566), - RGB(0.956808, 0.928152, 0.152409), - RGB(0.954287, 0.934908, 0.152921), - RGB(0.951726, 0.941671, 0.152925), - RGB(0.949151, 0.948435, 0.152178), - RGB(0.946602, 0.955190, 0.150328), - RGB(0.944152, 0.961916, 0.146861), - RGB(0.941896, 0.968590, 0.140956), - RGB(0.940015, 0.975158, 0.131326) -], 30)) - -register_gradient_colors(:viridis, sample_evenly([ - RGB(0.267004, 0.004874, 0.329415), - RGB(0.268510, 0.009605, 0.335427), - RGB(0.269944, 0.014625, 0.341379), - RGB(0.271305, 0.019942, 0.347269), - RGB(0.272594, 0.025563, 0.353093), - RGB(0.273809, 0.031497, 0.358853), - RGB(0.274952, 0.037752, 0.364543), - RGB(0.276022, 0.044167, 0.370164), - RGB(0.277018, 0.050344, 0.375715), - RGB(0.277941, 0.056324, 0.381191), - RGB(0.278791, 0.062145, 0.386592), - RGB(0.279566, 0.067836, 0.391917), - RGB(0.280267, 0.073417, 0.397163), - RGB(0.280894, 0.078907, 0.402329), - RGB(0.281446, 0.084320, 0.407414), - RGB(0.281924, 0.089666, 0.412415), - RGB(0.282327, 0.094955, 0.417331), - RGB(0.282656, 0.100196, 0.422160), - RGB(0.282910, 0.105393, 0.426902), - RGB(0.283091, 0.110553, 0.431554), - RGB(0.283197, 0.115680, 0.436115), - RGB(0.283229, 0.120777, 0.440584), - RGB(0.283187, 0.125848, 0.444960), - RGB(0.283072, 0.130895, 0.449241), - RGB(0.282884, 0.135920, 0.453427), - RGB(0.282623, 0.140926, 0.457517), - RGB(0.282290, 0.145912, 0.461510), - RGB(0.281887, 0.150881, 0.465405), - RGB(0.281412, 0.155834, 0.469201), - RGB(0.280868, 0.160771, 0.472899), - RGB(0.280255, 0.165693, 0.476498), - RGB(0.279574, 0.170599, 0.479997), - RGB(0.278826, 0.175490, 0.483397), - RGB(0.278012, 0.180367, 0.486697), - RGB(0.277134, 0.185228, 0.489898), - RGB(0.276194, 0.190074, 0.493001), - RGB(0.275191, 0.194905, 0.496005), - RGB(0.274128, 0.199721, 0.498911), - RGB(0.273006, 0.204520, 0.501721), - RGB(0.271828, 0.209303, 0.504434), - RGB(0.270595, 0.214069, 0.507052), - RGB(0.269308, 0.218818, 0.509577), - RGB(0.267968, 0.223549, 0.512008), - RGB(0.266580, 0.228262, 0.514349), - RGB(0.265145, 0.232956, 0.516599), - RGB(0.263663, 0.237631, 0.518762), - RGB(0.262138, 0.242286, 0.520837), - RGB(0.260571, 0.246922, 0.522828), - RGB(0.258965, 0.251537, 0.524736), - RGB(0.257322, 0.256130, 0.526563), - RGB(0.255645, 0.260703, 0.528312), - RGB(0.253935, 0.265254, 0.529983), - RGB(0.252194, 0.269783, 0.531579), - RGB(0.250425, 0.274290, 0.533103), - RGB(0.248629, 0.278775, 0.534556), - RGB(0.246811, 0.283237, 0.535941), - RGB(0.244972, 0.287675, 0.537260), - RGB(0.243113, 0.292092, 0.538516), - RGB(0.241237, 0.296485, 0.539709), - RGB(0.239346, 0.300855, 0.540844), - RGB(0.237441, 0.305202, 0.541921), - RGB(0.235526, 0.309527, 0.542944), - RGB(0.233603, 0.313828, 0.543914), - RGB(0.231674, 0.318106, 0.544834), - RGB(0.229739, 0.322361, 0.545706), - RGB(0.227802, 0.326594, 0.546532), - RGB(0.225863, 0.330805, 0.547314), - RGB(0.223925, 0.334994, 0.548053), - RGB(0.221989, 0.339161, 0.548752), - RGB(0.220057, 0.343307, 0.549413), - RGB(0.218130, 0.347432, 0.550038), - RGB(0.216210, 0.351535, 0.550627), - RGB(0.214298, 0.355619, 0.551184), - RGB(0.212395, 0.359683, 0.551710), - RGB(0.210503, 0.363727, 0.552206), - RGB(0.208623, 0.367752, 0.552675), - RGB(0.206756, 0.371758, 0.553117), - RGB(0.204903, 0.375746, 0.553533), - RGB(0.203063, 0.379716, 0.553925), - RGB(0.201239, 0.383670, 0.554294), - RGB(0.199430, 0.387607, 0.554642), - RGB(0.197636, 0.391528, 0.554969), - RGB(0.195860, 0.395433, 0.555276), - RGB(0.194100, 0.399323, 0.555565), - RGB(0.192357, 0.403199, 0.555836), - RGB(0.190631, 0.407061, 0.556089), - RGB(0.188923, 0.410910, 0.556326), - RGB(0.187231, 0.414746, 0.556547), - RGB(0.185556, 0.418570, 0.556753), - RGB(0.183898, 0.422383, 0.556944), - RGB(0.182256, 0.426184, 0.557120), - RGB(0.180629, 0.429975, 0.557282), - RGB(0.179019, 0.433756, 0.557430), - RGB(0.177423, 0.437527, 0.557565), - RGB(0.175841, 0.441290, 0.557685), - RGB(0.174274, 0.445044, 0.557792), - RGB(0.172719, 0.448791, 0.557885), - RGB(0.171176, 0.452530, 0.557965), - RGB(0.169646, 0.456262, 0.558030), - RGB(0.168126, 0.459988, 0.558082), - RGB(0.166617, 0.463708, 0.558119), - RGB(0.165117, 0.467423, 0.558141), - RGB(0.163625, 0.471133, 0.558148), - RGB(0.162142, 0.474838, 0.558140), - RGB(0.160665, 0.478540, 0.558115), - RGB(0.159194, 0.482237, 0.558073), - RGB(0.157729, 0.485932, 0.558013), - RGB(0.156270, 0.489624, 0.557936), - RGB(0.154815, 0.493313, 0.557840), - RGB(0.153364, 0.497000, 0.557724), - RGB(0.151918, 0.500685, 0.557587), - RGB(0.150476, 0.504369, 0.557430), - RGB(0.149039, 0.508051, 0.557250), - RGB(0.147607, 0.511733, 0.557049), - RGB(0.146180, 0.515413, 0.556823), - RGB(0.144759, 0.519093, 0.556572), - RGB(0.143343, 0.522773, 0.556295), - RGB(0.141935, 0.526453, 0.555991), - RGB(0.140536, 0.530132, 0.555659), - RGB(0.139147, 0.533812, 0.555298), - RGB(0.137770, 0.537492, 0.554906), - RGB(0.136408, 0.541173, 0.554483), - RGB(0.135066, 0.544853, 0.554029), - RGB(0.133743, 0.548535, 0.553541), - RGB(0.132444, 0.552216, 0.553018), - RGB(0.131172, 0.555899, 0.552459), - RGB(0.129933, 0.559582, 0.551864), - RGB(0.128729, 0.563265, 0.551229), - RGB(0.127568, 0.566949, 0.550556), - RGB(0.126453, 0.570633, 0.549841), - RGB(0.125394, 0.574318, 0.549086), - RGB(0.124395, 0.578002, 0.548287), - RGB(0.123463, 0.581687, 0.547445), - RGB(0.122606, 0.585371, 0.546557), - RGB(0.121831, 0.589055, 0.545623), - RGB(0.121148, 0.592739, 0.544641), - RGB(0.120565, 0.596422, 0.543611), - RGB(0.120092, 0.600104, 0.542530), - RGB(0.119738, 0.603785, 0.541400), - RGB(0.119512, 0.607464, 0.540218), - RGB(0.119423, 0.611141, 0.538982), - RGB(0.119483, 0.614817, 0.537692), - RGB(0.119699, 0.618490, 0.536347), - RGB(0.120081, 0.622161, 0.534946), - RGB(0.120638, 0.625828, 0.533488), - RGB(0.121380, 0.629492, 0.531973), - RGB(0.122312, 0.633153, 0.530398), - RGB(0.123444, 0.636809, 0.528763), - RGB(0.124780, 0.640461, 0.527068), - RGB(0.126326, 0.644107, 0.525311), - RGB(0.128087, 0.647749, 0.523491), - RGB(0.130067, 0.651384, 0.521608), - RGB(0.132268, 0.655014, 0.519661), - RGB(0.134692, 0.658636, 0.517649), - RGB(0.137339, 0.662252, 0.515571), - RGB(0.140210, 0.665859, 0.513427), - RGB(0.143303, 0.669459, 0.511215), - RGB(0.146616, 0.673050, 0.508936), - RGB(0.150148, 0.676631, 0.506589), - RGB(0.153894, 0.680203, 0.504172), - RGB(0.157851, 0.683765, 0.501686), - RGB(0.162016, 0.687316, 0.499129), - RGB(0.166383, 0.690856, 0.496502), - RGB(0.170948, 0.694384, 0.493803), - RGB(0.175707, 0.697900, 0.491033), - RGB(0.180653, 0.701402, 0.488189), - RGB(0.185783, 0.704891, 0.485273), - RGB(0.191090, 0.708366, 0.482284), - RGB(0.196571, 0.711827, 0.479221), - RGB(0.202219, 0.715272, 0.476084), - RGB(0.208030, 0.718701, 0.472873), - RGB(0.214000, 0.722114, 0.469588), - RGB(0.220124, 0.725509, 0.466226), - RGB(0.226397, 0.728888, 0.462789), - RGB(0.232815, 0.732247, 0.459277), - RGB(0.239374, 0.735588, 0.455688), - RGB(0.246070, 0.738910, 0.452024), - RGB(0.252899, 0.742211, 0.448284), - RGB(0.259857, 0.745492, 0.444467), - RGB(0.266941, 0.748751, 0.440573), - RGB(0.274149, 0.751988, 0.436601), - RGB(0.281477, 0.755203, 0.432552), - RGB(0.288921, 0.758394, 0.428426), - RGB(0.296479, 0.761561, 0.424223), - RGB(0.304148, 0.764704, 0.419943), - RGB(0.311925, 0.767822, 0.415586), - RGB(0.319809, 0.770914, 0.411152), - RGB(0.327796, 0.773980, 0.406640), - RGB(0.335885, 0.777018, 0.402049), - RGB(0.344074, 0.780029, 0.397381), - RGB(0.352360, 0.783011, 0.392636), - RGB(0.360741, 0.785964, 0.387814), - RGB(0.369214, 0.788888, 0.382914), - RGB(0.377779, 0.791781, 0.377939), - RGB(0.386433, 0.794644, 0.372886), - RGB(0.395174, 0.797475, 0.367757), - RGB(0.404001, 0.800275, 0.362552), - RGB(0.412913, 0.803041, 0.357269), - RGB(0.421908, 0.805774, 0.351910), - RGB(0.430983, 0.808473, 0.346476), - RGB(0.440137, 0.811138, 0.340967), - RGB(0.449368, 0.813768, 0.335384), - RGB(0.458674, 0.816363, 0.329727), - RGB(0.468053, 0.818921, 0.323998), - RGB(0.477504, 0.821444, 0.318195), - RGB(0.487026, 0.823929, 0.312321), - RGB(0.496615, 0.826376, 0.306377), - RGB(0.506271, 0.828786, 0.300362), - RGB(0.515992, 0.831158, 0.294279), - RGB(0.525776, 0.833491, 0.288127), - RGB(0.535621, 0.835785, 0.281908), - RGB(0.545524, 0.838039, 0.275626), - RGB(0.555484, 0.840254, 0.269281), - RGB(0.565498, 0.842430, 0.262877), - RGB(0.575563, 0.844566, 0.256415), - RGB(0.585678, 0.846661, 0.249897), - RGB(0.595839, 0.848717, 0.243329), - RGB(0.606045, 0.850733, 0.236712), - RGB(0.616293, 0.852709, 0.230052), - RGB(0.626579, 0.854645, 0.223353), - RGB(0.636902, 0.856542, 0.216620), - RGB(0.647257, 0.858400, 0.209861), - RGB(0.657642, 0.860219, 0.203082), - RGB(0.668054, 0.861999, 0.196293), - RGB(0.678489, 0.863742, 0.189503), - RGB(0.688944, 0.865448, 0.182725), - RGB(0.699415, 0.867117, 0.175971), - RGB(0.709898, 0.868751, 0.169257), - RGB(0.720391, 0.870350, 0.162603), - RGB(0.730889, 0.871916, 0.156029), - RGB(0.741388, 0.873449, 0.149561), - RGB(0.751884, 0.874951, 0.143228), - RGB(0.762373, 0.876424, 0.137064), - RGB(0.772852, 0.877868, 0.131109), - RGB(0.783315, 0.879285, 0.125405), - RGB(0.793760, 0.880678, 0.120005), - RGB(0.804182, 0.882046, 0.114965), - RGB(0.814576, 0.883393, 0.110347), - RGB(0.824940, 0.884720, 0.106217), - RGB(0.835270, 0.886029, 0.102646), - RGB(0.845561, 0.887322, 0.099702), - RGB(0.855810, 0.888601, 0.097452), - RGB(0.866013, 0.889868, 0.095953), - RGB(0.876168, 0.891125, 0.095250), - RGB(0.886271, 0.892374, 0.095374), - RGB(0.896320, 0.893616, 0.096335), - RGB(0.906311, 0.894855, 0.098125), - RGB(0.916242, 0.896091, 0.100717), - RGB(0.926106, 0.897330, 0.104071), - RGB(0.935904, 0.898570, 0.108131), - RGB(0.945636, 0.899815, 0.112838), - RGB(0.955300, 0.901065, 0.118128), - RGB(0.964894, 0.902323, 0.123941), - RGB(0.974417, 0.903590, 0.130215), - RGB(0.983868, 0.904867, 0.136897), - RGB(0.993248, 0.906157, 0.143936) -], 30)) - - -# end of matplotlib colormaps -# ---------------------------------------------------------------------- -# ---------------------------------------------------------------------- diff --git a/src/deprecated/colors.jl b/src/deprecated/colors.jl deleted file mode 100644 index 5e01bdc1..00000000 --- a/src/deprecated/colors.jl +++ /dev/null @@ -1,415 +0,0 @@ - -abstract type ColorScheme end - -Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i) - -export - cgrad - -cgrad() = default_gradient() - -function cgrad(arg, values = nothing; alpha = nothing, scale = :identity) - colors = ColorGradient(arg, alpha=alpha).colors - values = if values != nothing - values - elseif scale in (:log, :log10) - log10(range(1, stop=10, length=30)) - elseif scale == :log2 - log2(range(1, stop=2, length=30)) - elseif scale == :ln - log(range(1, stop=pi, length=30)) - elseif scale in (:exp, :exp10) - (exp10(range(0, stop=1, length=30)) - 1) / 9 - else - range(0, stop=1, length=length(colors)) - end - ColorGradient(colors, values) -end - -# -------------------------------------------------------------- - -getColor(scheme::ColorScheme) = getColor(scheme, 1) -getColorVector(scheme::ColorScheme) = [getColor(scheme)] - -colorscheme(scheme::ColorScheme) = scheme -colorscheme(s::AbstractString; kw...) = colorscheme(Symbol(s); kw...) -colorscheme(s::Symbol; kw...) = haskey(_gradients, s) ? ColorGradient(s; kw...) : ColorWrapper(convertColor(s); kw...) -colorscheme(s::Symbol, vals::AVec{T}; kw...) where {T<:Real} = ColorGradient(s, vals; kw...) -colorscheme(cs::AVec, vs::AVec; kw...) = ColorGradient(cs, vs; kw...) -colorscheme(cs::AVec{T}; kw...) where {T<:Colorant} = ColorGradient(cs; kw...) -colorscheme(f::Function; kw...) = ColorFunction(f; kw...) -colorscheme(v::AVec; kw...) = ColorVector(v; kw...) -colorscheme(m::AMat; kw...) = size(m,1) == 1 ? map(c->colorscheme(c; kw...), m) : [colorscheme(m[:,i]; kw...) for i in 1:size(m,2)]' -colorscheme(c::Colorant; kw...) = ColorWrapper(c; kw...) - - -# -------------------------------------------------------------- - - -convertColor(c::AbstractString) = parse(Colorant, c) -convertColor(c::Symbol) = parse(Colorant, string(c)) -convertColor(c::Colorant) = c -convertColor(cvec::AbstractVector) = map(convertColor, cvec) -convertColor(c::ColorScheme) = c -convertColor(v::Nothing) = RGBA(0,0,0,0) -convertColor(b::Bool) = b ? RGBA(0,0,0,1) : RGBA(0,0,0,0) - -function convertColor(c, α::Real) - c = convertColor(c) - RGBA(RGB(getColor(c)), α) -end -convertColor(cs::AVec, α::Real) = map(c -> convertColor(c, α), cs) -convertColor(c, α::Nothing) = convertColor(c) - -# backup... try to convert -getColor(c) = convertColor(c) - -# -------------------------------------------------------------- - -function darken(c, v=0.1) - rgba = convert(RGBA, c) - r = max(0, min(rgba.r - v, 1)) - g = max(0, min(rgba.g - v, 1)) - b = max(0, min(rgba.b - v, 1)) - RGBA(r,g,b,rgba.alpha) -end -function lighten(c, v=0.3) - darken(c, -v) -end - -# -------------------------------------------------------------- - -const _rainbowColors = [colorant"purple", colorant"blue", colorant"green", colorant"orange", colorant"red"] -const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcyan",colorant"green", - darken(colorant"yellow",0.3), colorant"orange", darken(colorant"red",0.2)] - -const _gradients = KW( - :blues => [colorant"lightblue", colorant"darkblue"], - :reds => [colorant"lightpink", colorant"darkred"], - :greens => [colorant"lightgreen", colorant"darkgreen"], - :redsblues => [colorant"darkred", RGB(0.8,0.85,0.8), colorant"darkblue"], - :bluesreds => [colorant"darkblue", RGB(0.8,0.85,0.8), colorant"darkred"], - :heat => [colorant"lightyellow", colorant"orange", colorant"darkred"], - :grays => [RGB(.95,.95,.95),RGB(.05,.05,.05)], - :rainbow => _rainbowColors, - :lightrainbow => map(lighten, _rainbowColors), - :darkrainbow => map(darken, _rainbowColors), - :darktest => _testColors, - :lighttest => map(c -> lighten(c, 0.3), _testColors), - ) - -function register_gradient_colors(name::Symbol, colors::AVec{C}) where C<:Colorant - _gradients[name] = colors -end - -include("color_gradients.jl") - -default_gradient() = ColorGradient(:inferno) - -# -------------------------------------------------------------- - -"Continuous gradient between values. Wraps a list of bounding colors and the values they represent." -struct ColorGradient <: ColorScheme - colors::Vector - values::Vector - - function ColorGradient(cs::AVec, vals::AVec{S} = range(0, stop=1, length=length(cs)); alpha = nothing) where S<:Real - if length(cs) == length(vals) - return new(convertColor(cs,alpha), collect(vals)) - end - - # # otherwise interpolate evenly between the minval and maxval - # minval, maxval = minimum(vals), maximum(vals) - # vs = Float64[interpolate(minval, maxval, w) for w in range(0, stop = 1, length = length(cs))] - # new(convertColor(cs,alpha), vs) - - # interpolate the colors for each value - vals = merge(range(0, stop=1, length=length(cs)), vals) - grad = ColorGradient(cs) - cs = [getColorZ(grad, z) for z in range(0, stop=1, length=length(vals))] - new(convertColor(cs, alpha), vals) - end -end - - - -Base.getindex(cs::ColorGradient, i::Integer) = getColor(cs, i) -Base.getindex(cs::ColorGradient, z::Number) = getColorZ(cs, z) - - -# create a gradient from a symbol (blues, reds, etc) and vector of boundary values -function ColorGradient(s::Symbol, vals::AVec{T} = 0:0; kw...) where T<:Real - haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients)))) - cs = _gradients[s] - if vals == 0:0 - vals = range(0, stop=1, length=length(cs)) - end - ColorGradient(cs, vals; kw...) -end - -# function ColorGradient{T<:Real}(cs::AVec, vals::AVec{T} = range(0, stop = 1, length = length(cs)); kw...) -# ColorGradient(map(convertColor, cs), vals; kw...) -# end - -function ColorGradient(grad::ColorGradient; alpha = nothing) - ColorGradient(convertColor(grad.colors, alpha), grad.values) -end - -# anything else just gets the default gradient -function ColorGradient(cw; alpha=nothing) - ColorGradient(default_gradient(), alpha=alpha) -end - -getColor(gradient::ColorGradient, idx::Int) = gradient.colors[mod1(idx, length(gradient.colors))] - -function getColorZ(gradient::ColorGradient, z::Real) - cs = gradient.colors - vs = gradient.values - n = length(cs) - @assert n > 0 && n == length(vs) - - # can we just return the first color? - if z <= vs[1] || n == 1 - return cs[1] - end - - # find the bounding colors and interpolate - for i in 2:n - if z <= vs[i] - return interpolate_rgb(cs[i-1], cs[i], (z - vs[i-1]) / (vs[i] - vs[i-1])) - end - end - - # if we get here, return the last color - cs[end] -end - -getColorVector(gradient::ColorGradient) = gradient.colors - -# for 0.3 -Colors.RGBA(c::Colorant) = RGBA(red(c), green(c), blue(c), alpha(c)) -Colors.RGB(c::Colorant) = RGB(red(c), green(c), blue(c)) - -function interpolate_rgb(c1::Colorant, c2::Colorant, w::Real) - rgb1 = RGBA(c1) - rgb2 = RGBA(c2) - r = interpolate(rgb1.r, rgb2.r, w) - g = interpolate(rgb1.g, rgb2.g, w) - b = interpolate(rgb1.b, rgb2.b, w) - a = interpolate(rgb1.alpha, rgb2.alpha, w) - RGBA(r, g, b, a) -end - - -function interpolate(v1::Real, v2::Real, w::Real) - (1-w) * v1 + w * v2 -end - -# -------------------------------------------------------------- - -"Wraps a function, taking an index and returning a Colorant" -struct ColorFunction <: ColorScheme - f::Function -end - -getColor(scheme::ColorFunction, idx::Int) = scheme.f(idx) - -# -------------------------------------------------------------- - -"Wraps a function, taking an z-value and returning a Colorant" -struct ColorZFunction <: ColorScheme - f::Function -end - -getColorZ(scheme::ColorZFunction, z::Real) = scheme.f(z) - -# -------------------------------------------------------------- - -"Wraps a vector of colors... may be vector of Symbol/String/Colorant" -struct ColorVector <: ColorScheme - v::Vector{Colorant} - ColorVector(v::AVec; alpha = nothing) = new(convertColor(v,alpha)) -end - -getColor(scheme::ColorVector, idx::Int) = convertColor(scheme.v[mod1(idx, length(scheme.v))]) -getColorVector(scheme::ColorVector) = scheme.v - - -# -------------------------------------------------------------- - -"Wraps a single color" -struct ColorWrapper <: ColorScheme - c::RGBA - ColorWrapper(c::Colorant; alpha = nothing) = new(convertColor(c, alpha)) -end - -ColorWrapper(s::Symbol; alpha = nothing) = ColorWrapper(convertColor(parse(Colorant, s), alpha)) - -getColor(scheme::ColorWrapper, idx::Int) = scheme.c -getColorZ(scheme::ColorWrapper, z::Real) = scheme.c -convertColor(c::ColorWrapper, α::Nothing) = c.c - -# -------------------------------------------------------------- - - -isbackgrounddark(bgcolor::Color) = Lab(bgcolor).l < 0.5 - -# move closer to lighter/darker depending on background value -function adjustAway(val, bgval, vmin=0., vmax=100.) - if bgval < 0.5 * (vmax+vmin) - tmp = max(val, bgval) - return 0.5 * (tmp + max(tmp, vmax)) - else - tmp = min(val, bgval) - return 0.5 * (tmp + min(tmp, vmin)) - end -end - -# borrowed from http://stackoverflow.com/a/1855903: -lightnessLevel(c::Colorant) = 0.299 * red(c) + 0.587 * green(c) + 0.114 * blue(c) - -isdark(c::Colorant) = lightnessLevel(c) < 0.5 -islight(c::Colorant) = !isdark(c) - -function convertHexToRGB(h::Unsigned) - mask = 0x0000FF - RGB([(x & mask) / 0xFF for x in (h >> 16, h >> 8, h)]...) -end - -# note: I found this list of hex values in a comment by Tatarize here: http://stackoverflow.com/a/12224359 -const _masterColorList = [ - 0xFFFFFF, 0x000000, 0x0000FF, 0x00FF00, 0xFF0000, 0x01FFFE, 0xFFA6FE, 0xFFDB66, 0x006401, 0x010067, - 0x95003A, 0x007DB5, 0xFF00F6, 0xFFEEE8, 0x774D00, 0x90FB92, 0x0076FF, 0xD5FF00, 0xFF937E, 0x6A826C, - 0xFF029D, 0xFE8900, 0x7A4782, 0x7E2DD2, 0x85A900, 0xFF0056, 0xA42400, 0x00AE7E, 0x683D3B, 0xBDC6FF, - 0x263400, 0xBDD393, 0x00B917, 0x9E008E, 0x001544, 0xC28C9F, 0xFF74A3, 0x01D0FF, 0x004754, 0xE56FFE, - 0x788231, 0x0E4CA1, 0x91D0CB, 0xBE9970, 0x968AE8, 0xBB8800, 0x43002C, 0xDEFF74, 0x00FFC6, 0xFFE502, - 0x620E00, 0x008F9C, 0x98FF52, 0x7544B1, 0xB500FF, 0x00FF78, 0xFF6E41, 0x005F39, 0x6B6882, 0x5FAD4E, - 0xA75740, 0xA5FFD2, 0xFFB167, 0x009BFF, 0xE85EBE - ] -const _allColors = map(convertHexToRGB, _masterColorList) -const _darkColors = filter(isdark, _allColors) -const _lightColors = filter(islight, _allColors) -const _sortedColorsForDarkBackground = vcat(_lightColors, reverse(_darkColors[2:end])) -const _sortedColorsForLightBackground = vcat(_darkColors, reverse(_lightColors[2:end])) - -const _defaultNumColors = 17 - -# -------------------------------------------------------------- - -# Methods to automatically generate gradients for color selection based on -# background color and a short list of seed colors - -# here are some magic constants that could be changed if you really want -const _lightness_darkbg = [80.0] -const _lightness_lightbg = [60.0] -const _lch_c_const = [60] - -function adjust_lch(color, l, c) - lch = convert(LCHab, color) - convert(RGB, LCHab(l, c, lch.h)) -end - -function lightness_from_background(bgcolor) - bglight = convert(LCHab, bgcolor).l - bglight < 50.0 ? _lightness_darkbg[1] : _lightness_lightbg[1] -end - -function gradient_from_list(cs) - zvalues = Plots.get_zvalues(length(cs)) - indices = sortperm(zvalues) - sorted_colors = map(RGBA, cs[indices]) - sorted_zvalues = zvalues[indices] - ColorGradient(sorted_colors, sorted_zvalues) -end - -function generate_colorgradient(bgcolor = colorant"white"; - color_bases = color_bases=[colorant"steelblue",colorant"orangered"], - lightness = lightness_from_background(bgcolor), - chroma = _lch_c_const[1], - n = _defaultNumColors) - seed_colors = vcat(bgcolor, map(c -> adjust_lch(c, lightness, chroma), color_bases)) - colors = distinguishable_colors(n, - seed_colors, - lchoices=Float64[lightness], - cchoices=Float64[chroma], - hchoices=range(0, stop=340, length=20) - )[2:end] - gradient_from_list(colors) -end - -function get_color_palette(palette, bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) - grad = if palette == :auto - generate_colorgradient(bgcolor) - else - ColorGradient(palette) - end - zrng = get_zvalues(numcolors) - RGBA[getColorZ(grad, z) for z in zrng] -end - -function get_color_palette(palette::Vector{C}, -bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) where C<:Colorant - palette -end - -# ---------------------------------------------------------------------------------- - - -function getpctrange(n::Int) - n > 0 || error() - n == 1 && return zeros(1) - zs = [0.0, 1.0] - for i in 3:n - sorted = sort(zs) - diffs = diff(sorted) - widestj = 0 - widest = 0.0 - for (j,d) in enumerate(diffs) - if d > widest - widest = d - widestj = j - end - end - push!(zs, sorted[widestj] + 0.5 * diffs[widestj]) - end - zs -end - -function get_zvalues(n::Int) - offsets = getpctrange(ceil(Int,n/4)+1)/4 - offsets = vcat(offsets[1], offsets[3:end]) - zvalues = Float64[] - for offset in offsets - append!(zvalues, offset + [0.0, 0.5, 0.25, 0.75]) - end - vcat(zvalues[1], 1.0, zvalues[2:n-1]) -end - -# ---------------------------------------------------------------------------------- - - -make255(x) = round(Int, 255 * x) - -function webcolor(c::Color) - @sprintf("rgb(%d, %d, %d)", [make255(f(c)) for f in [red,green,blue]]...) -end -function webcolor(c::TransparentColor) - @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c)) -end -webcolor(cs::ColorScheme) = webcolor(getColor(cs)) -webcolor(c) = webcolor(convertColor(c)) -webcolor(c, α) = webcolor(convertColor(getColor(c), α)) - -# ---------------------------------------------------------------------------------- - - -# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically -function getSeriesRGBColor(c, sp::Subplot, n::Int) - - if c == :auto - c = autopick(sp[:color_palette], n) - end - - # c should now be a subtype of ColorScheme - colorscheme(c) -end diff --git a/src/deprecated/contours.jl b/src/deprecated/contours.jl deleted file mode 100644 index f9ab0954..00000000 --- a/src/deprecated/contours.jl +++ /dev/null @@ -1,63 +0,0 @@ - - -# TODO: -""" -- load Contours.jl similar to DataFrames -- method to build grid from x/y/z vectors -- method to wrap contours creation -- method to plot contours as custom shapes (TODO: create Stroke and Fill types and add markerstroke/markerfill args) - -""" - - - -# # ---------------------------------------------------------- -# # ---------------------------------------------------------- - - -# immutable Vertex -# x::Float64 -# y::Float64 -# z::Float64 -# end - -# immutable Edge -# v::Vertex -# u::Vertex -# end - -# # ---------------------------------------------------------- - -# # one rectangle's z-values and the center vertex -# # z is ordered: topleft, topright, bottomright, bottomleft -# immutable GridRect -# z::Vector{Float64} -# center::Vertex -# data::Vector{Vertex} -# end - - - -# type Grid -# xs::Vector{Float64} -# ys::Vector{Float64} -# rects::Matrix{GridRect} -# end - -# function splitDataEvenly(v::AbstractVector{Float64}, n::Int) -# vs = sort(v) - -# end - -# # the goal here is to create the vertical and horizontal partitions -# # which define the grid, so that the data is somewhat evenly split -# function bucketData(x, y, z) - -# end - - -# function buildGrid(x, y, z) -# # create -# end - - diff --git a/src/deprecated/series_args.jl b/src/deprecated/series_args.jl deleted file mode 100644 index 4dafda80..00000000 --- a/src/deprecated/series_args.jl +++ /dev/null @@ -1,99 +0,0 @@ - -# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems]. -# Special handling for: no args, xmin/xmax, parametric, dataframes -# Then once inputs have been converted, build the series args, map functions, etc. -# This should cut down on boilerplate code and allow more focused dispatch on type -# note: returns meta information... mainly for use with automatic labeling from DataFrames for now - -const FuncOrFuncs = Union{Function, AVec{Function}} - -all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(plotattributes, :seriestype, :none)) - -# missing -convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing - -# fixed number of blank series -convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing - -# numeric vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing - -# string vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing - -function convertToAnyVector(v::AMat, plotattributes::KW) - if all3D(plotattributes) - Any[Surface(v)] - else - Any[v[:,i] for i in 1:size(v,2)] - end, nothing -end - -# function -convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing - -# surface -convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing - -# # vector of OHLC -# convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing - -# dates -convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing - -# list of things (maybe other vectors, functions, or something else) -function convertToAnyVector(v::AVec, plotattributes::KW) - if all(x -> typeof(x) <: Number, v) - # all real numbers wrap the whole vector as one item - Any[convert(Vector{Float64}, v)], nothing - else - # something else... treat each element as an item - vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing - # Any[vi for vi in v], nothing - end -end - -convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing - - -function convertToAnyVector(args...) - error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))") -end - -# -------------------------------------------------------------------- - -# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array -# result in that array being shared. push!, etc will add too many items to that array - -compute_x(x::Nothing, y::Nothing, z) = 1:size(z,1) -compute_x(x::Nothing, y, z) = 1:size(y,1) -compute_x(x::Function, y, z) = map(x, y) -compute_x(x, y, z) = copy(x) - -# compute_y(x::Void, y::Function, z) = error() -compute_y(x::Nothing, y::Nothing, z) = 1:size(z,2) -compute_y(x, y::Function, z) = map(y, x) -compute_y(x, y, z) = copy(y) - -compute_z(x, y, z::Function) = map(z, x, y) -compute_z(x, y, z::AbstractMatrix) = Surface(z) -compute_z(x, y, z::Nothing) = nothing -compute_z(x, y, z) = copy(z) - -nobigs(v::AVec{BigFloat}) = map(Float64, v) -nobigs(v::AVec{BigInt}) = map(Int64, v) -nobigs(v) = v - -@noinline function compute_xyz(x, y, z) - x = compute_x(x,y,z) - y = compute_y(x,y,z) - z = compute_z(x,y,z) - nobigs(x), nobigs(y), nobigs(z) -end - -# not allowed -compute_xyz(x::Nothing, y::FuncOrFuncs, z) = error("If you want to plot the function `$y`, you need to define the x values!") -compute_xyz(x::Nothing, y::Nothing, z::FuncOrFuncs) = error("If you want to plot the function `$z`, you need to define x and y values!") -compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing!") - -# -------------------------------------------------------------------- diff --git a/src/utils.jl b/src/utils.jl index c52ba186..f80244b1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -737,7 +737,7 @@ function with(f::Function, args...; kw...) end # # TODO: generalize this strategy to allow args as much as possible - # # as in: with(:gadfly, :scatter, :legend, :grid) do; ...; end + # # as in: with(:gr, :scatter, :legend, :grid) do; ...; end # # TODO: can we generalize this enough to also do something similar in the plot commands?? # k = :seriestype diff --git a/test/runtests.jl b/test/runtests.jl index f98f877c..1587d1bb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -87,16 +87,6 @@ end # # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol) # end - -# @testset "Immerse" begin -# @test immerse() == Plots.ImmerseBackend() -# @test backend() == Plots.ImmerseBackend() -# -# # as long as we can plot anything without error, it should be the same as Gadfly -# image_comparison_facts(:immerse, only=[1], tol=img_tol) -# end - - # @testset "PlotlyJS" begin # @test plotlyjs() == Plots.PlotlyJSBackend() # @test backend() == Plots.PlotlyJSBackend() @@ -106,19 +96,6 @@ end # end -# @testset "Gadfly" begin -# @test gadfly() == Plots.GadflyBackend() -# @test backend() == Plots.GadflyBackend() -# -# @test typeof(plot(1:10)) == Plots.Plot{Plots.GadflyBackend} -# @test plot(Int[1,2,3], rand(3)) == not(nothing) -# @test plot(sort(rand(10)), rand(Int, 10, 3)) == not(nothing) -# @test plot!(rand(10,3), rand(10,3)) == not(nothing) -# -# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], tol=img_tol) -# end - - @testset "Axes" begin From 1386435b17f76a9ac4811516ea964881d1fa91b9 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 30 Oct 2018 11:08:08 +0100 Subject: [PATCH 044/230] Completely deprecate glvisualize --- NEWS.md | 2 +- src/backends.jl | 70 +- src/backends/glvisualize.jl | 1472 ----------------------------------- src/init.jl | 1 - src/output.jl | 1 - 5 files changed, 3 insertions(+), 1543 deletions(-) delete mode 100644 src/backends/glvisualize.jl diff --git a/NEWS.md b/NEWS.md index 703c2b2e..3510105e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,7 +10,7 @@ --- ## (current master) -- All new development should target Julia 1.x! +- deprecate GLVisualize ## 0.20.6 - fixes for PlotDocs.jl diff --git a/src/backends.jl b/src/backends.jl index d64db5e4..11cea85e 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -157,7 +157,7 @@ function pickDefaultBackend() # the ordering/inclusion of this package list is my semi-arbitrary guess at # which one someone will want to use if they have the package installed...accounting for # features, speed, and robustness - # for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR", "GLVisualize") + # for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR") # if pkgstr in keys(Pkg.installed()) # return backend(Symbol(lowercase(pkgstr))) # end @@ -213,7 +213,7 @@ function backend(sym::Symbol) backend() end -const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse] +const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize] function warn_on_deprecated_backend(bsym::Symbol) if bsym in _deprecated_backends @@ -273,7 +273,6 @@ end @init_backend Plotly @init_backend PlotlyJS @init_backend GR -@init_backend GLVisualize @init_backend PGFPlots @init_backend InspectDR @init_backend HDF5 @@ -445,71 +444,6 @@ const _plotly_marker = [ ] const _plotly_scale = [:identity, :log10] -# ------------------------------------------------------------------------------ -# glvisualize - -function _initialize_backend(::GLVisualizeBackend; kw...) - @eval Main begin - import GLVisualize, GeometryTypes, Reactive, GLAbstraction, GLWindow, Contour - import GeometryTypes: Point2f0, Point3f0, Vec2f0, Vec3f0, GLNormalMesh, SimpleRectangle, Point, Vec - import FileIO, Images - export GLVisualize - import Reactive: Signal - import GLAbstraction: Style - import GLVisualize: visualize - import Plots.GL - import UnicodeFun - end -end - -const _glvisualize_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :titlefontsize, :titlefontcolor, - :legendfontsize, :legendfontcolor, - :tickfontsize, - :guidefontsize, :guidefontcolor, - :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :colorbar, - :marker_z, - :line_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - #:polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :hover, - :framestyle, - :tick_direction, -]) -const _glvisualize_seriestype = [ - :path, :shape, :straightline, - :scatter, :hexbin, - :bar, :boxplot, - :heatmap, :image, :volume, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe -] -const _glvisualize_style = [:auto, :solid, :dash, :dot, :dashdot] -const _glvisualize_marker = _allMarkers -const _glvisualize_scale = [:identity, :ln, :log2, :log10] - # ------------------------------------------------------------------------------ # pgfplots diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl deleted file mode 100644 index 72f7c74e..00000000 --- a/src/backends/glvisualize.jl +++ /dev/null @@ -1,1472 +0,0 @@ -#= -TODO - * move all gl_ methods to GLPlot - * integrate GLPlot UI - * clean up corner cases - * find a cleaner way for extracting properties - * polar plots - * labes and axis - * fix units in all visuals (e.g dotted lines, marker scale, surfaces) -=# - - - -slice_arg(img::Matrix{C}, idx::Int) where {C<:Colorant} = img -is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true -is_marker_supported(::GLVisualizeBackend, shape::Union{Vector{Matrix{C}}, Matrix{C}}) where {C<:Colorant} = true -is_marker_supported(::GLVisualizeBackend, shape::Shape) = true -GL = Plots - -# --------------------------------------------------------------------------- - -# initialize the figure/window -# function _create_backend_figure(plt::Plot{GLVisualizeBackend}) -# # init a screen -# -# GLPlot.init() -# end -const _glplot_deletes = [] - - -function get_plot_screen(list::Vector, name, result = []) - for elem in list - get_plot_screen(elem, name, result) - end - return result -end -function get_plot_screen(screen, name, result = []) - if screen.name == name - push!(result, screen) - return result - end - get_plot_screen(screen.children, name, result) -end - -function create_window(plt::Plot{GLVisualizeBackend}, visible) - name = Symbol("__Plots.jl") - # make sure we have any screen open - if isempty(GLVisualize.get_screens()) - # create a fresh, new screen - parent_screen = GLVisualize.glscreen( - "Plots", - resolution = plt[:size], - visible = visible - ) - @async GLWindow.renderloop(parent_screen) - GLVisualize.add_screen(parent_screen) - end - # now lets get ourselves a permanent Plotting screen - plot_screens = get_plot_screen(GLVisualize.current_screen(), name) - screen = if isempty(plot_screens) # no screen with `name` - parent = GLVisualize.current_screen() - screen = GLWindow.Screen( - parent, area = map(GLWindow.zeroposition, parent.area), - name = name - ) - screen - elseif length(plot_screens) == 1 - plot_screens[1] - else - # okay this is silly! Lets see if we can. There is an ID we could use - # will not be fine for more than 255 screens though -.-. - error("multiple Plot screens. Please don't use any screen with the name $name") - end - # Since we own this window, we can do deep cleansing - empty!(screen) - plt.o = screen - GLWindow.set_visibility!(screen, visible) - resize!(screen, plt[:size]...) - screen -end -# --------------------------------------------------------------------------- - -const _gl_marker_map = KW( - :rect => '■', - :star5 => '★', - :diamond => '◆', - :hexagon => '⬢', - :cross => '✚', - :xcross => '❌', - :utriangle => '▲', - :dtriangle => '▼', - :ltriangle => '◀', - :rtriangle => '▶', - :pentagon => '⬟', - :octagon => '⯄', - :star4 => '✦', - :star6 => '🟋', - :star8 => '✷', - :vline => '┃', - :hline => '━', - :+ => '+', - :x => 'x', - :circle => '●' -) - -function gl_marker(shape) - shape -end -function gl_marker(shape::Shape) - points = Point2f0[GeometryTypes.Vec{2, Float32}(p) for p in zip(shape.x, shape.y)] - bb = GeometryTypes.AABB(points) - mini, maxi = minimum(bb), maximum(bb) - w3 = maxi-mini - origin, width = Point2f0(mini[1], mini[2]), Point2f0(w3[1], w3[2]) - map!(p -> ((p - origin) ./ width) - 0.5f0, points, points) # normalize and center - GeometryTypes.GLNormalMesh(points) -end -# create a marker/shape type -function gl_marker(shape::Vector{Symbol}) - String(map(shape) do sym - get(_gl_marker_map, sym, '●') - end) -end - -function gl_marker(shape::Symbol) - if shape == :rect - GeometryTypes.HyperRectangle(Vec2f0(0), Vec2f0(1)) - elseif shape == :circle || shape == :none - GeometryTypes.HyperSphere(Point2f0(0), 1f0) - elseif haskey(_gl_marker_map, shape) - _gl_marker_map[shape] - elseif haskey(_shapes, shape) - gl_marker(_shapes[shape]) - else - error("Shape $shape not supported by GLVisualize") - end -end - -function extract_limits(sp, plotattributes, kw_args) - clims = sp[:clims] - if is_2tuple(clims) - if isfinite(clims[1]) && isfinite(clims[2]) - kw_args[:limits] = Vec2f0(clims) - end - end - nothing -end - -to_vec(::Type{T}, vec::T) where {T <: StaticArrays.StaticVector} = vec -to_vec(::Type{T}, s::Number) where {T <: StaticArrays.StaticVector} = T(s) - -to_vec(::Type{T}, vec::StaticArrays.StaticVector{3}) where {T <: StaticArrays.StaticVector{2}} = T(vec[1], vec[2]) -to_vec(::Type{T}, vec::StaticArrays.StaticVector{2}) where {T <: StaticArrays.StaticVector{3}} = T(vec[1], vec[2], 0) - -to_vec(::Type{T}, vecs::AbstractVector) where {T <: StaticArrays.StaticVector} = map(x-> to_vec(T, x), vecs) - -function extract_marker(plotattributes, kw_args) - dim = Plots.is3d(plotattributes) ? 3 : 2 - scaling = dim == 3 ? 0.003 : 2 - if haskey(plotattributes, :markershape) - shape = plotattributes[:markershape] - shape = gl_marker(shape) - if shape != :none - kw_args[:primitive] = shape - end - end - dim = isa(kw_args[:primitive], GLVisualize.Sprites) ? 2 : 3 - if haskey(plotattributes, :markersize) - msize = plotattributes[:markersize] - kw_args[:scale] = to_vec(GeometryTypes.Vec{dim, Float32}, msize .* scaling) - end - if haskey(plotattributes, :offset) - kw_args[:offset] = plotattributes[:offset] - end - # get the color - key = :markercolor - haskey(plotattributes, key) || return - c = gl_color(plotattributes[key]) - if isa(c, AbstractVector) && plotattributes[:marker_z] != nothing - extract_colornorm(plotattributes, kw_args) - kw_args[:color] = nothing - kw_args[:color_map] = c - kw_args[:intensity] = convert(Vector{Float32}, plotattributes[:marker_z]) - else - kw_args[:color] = c - end - key = :markerstrokecolor - haskey(plotattributes, key) || return - c = gl_color(plotattributes[key]) - if c != nothing - if !(isa(c, Colorant) || (isa(c, Vector) && eltype(c) <: Colorant)) - error("Stroke Color not supported: $c") - end - kw_args[:stroke_color] = c - kw_args[:stroke_width] = Float32(plotattributes[:markerstrokewidth]) - end -end - -function _extract_surface(plotattributes::Plots.Surface) - plotattributes.surf -end -function _extract_surface(plotattributes::AbstractArray) - plotattributes -end - -# TODO when to transpose?? -function extract_surface(plotattributes) - map(_extract_surface, (plotattributes[:x], plotattributes[:y], plotattributes[:z])) -end -function topoints(::Type{P}, array) where P - [P(x) for x in zip(array...)] -end -function extract_points(plotattributes) - dim = is3d(plotattributes) ? 3 : 2 - array = if plotattributes[:seriestype] == :straightline - straightline_data(plotattributes) - elseif plotattributes[:seriestype] == :shape - shape_data(plotattributes) - else - (plotattributes[:x], plotattributes[:y], plotattributes[:z])[1:dim] - end - topoints(Point{dim, Float32}, array) -end -function make_gradient(grad::Vector{C}) where C <: Colorant - grad -end -function make_gradient(grad::ColorGradient) - RGBA{Float32}[c for c in grad.colors] -end -make_gradient(c) = make_gradient(cgrad()) - -function extract_any_color(plotattributes, kw_args) - if plotattributes[:marker_z] == nothing - c = scalar_color(plotattributes, :fill) - extract_c(plotattributes, kw_args, :fill) - if isa(c, Colorant) - kw_args[:color] = c - else - kw_args[:color] = nothing - kw_args[:color_map] = make_gradient(c) - clims = plotattributes[:subplot][:clims] - if Plots.is_2tuple(clims) - if isfinite(clims[1]) && isfinite(clims[2]) - kw_args[:color_norm] = Vec2f0(clims) - end - elseif clims == :auto - kw_args[:color_norm] = Vec2f0(ignorenan_extrema(plotattributes[:y])) - end - end - else - kw_args[:color] = nothing - clims = plotattributes[:subplot][:clims] - if Plots.is_2tuple(clims) - if isfinite(clims[1]) && isfinite(clims[2]) - kw_args[:color_norm] = Vec2f0(clims) - end - elseif clims == :auto - kw_args[:color_norm] = Vec2f0(ignorenan_extrema(plotattributes[:y])) - else - error("Unsupported limits: $clims") - end - kw_args[:intensity] = convert(Vector{Float32}, plotattributes[:marker_z]) - kw_args[:color_map] = gl_color_map(plotattributes, :marker) - end -end - -function extract_stroke(plotattributes, kw_args) - extract_c(plotattributes, kw_args, :line) - if haskey(plotattributes, :linewidth) - kw_args[:thickness] = Float32(plotattributes[:linewidth] * 3) - end -end - -function extract_color(plotattributes, sym) - plotattributes[Symbol("$(sym)color")] -end - -gl_color(c::PlotUtils.ColorGradient) = c.colors -gl_color(c::Vector{T}) where {T<:Colorant} = c -gl_color(c::RGBA{Float32}) = c -gl_color(c::Colorant) = RGBA{Float32}(c) - -function gl_color(tuple::Tuple) - gl_color(tuple...) -end - -# convert to RGBA -function gl_color(c, a) - c = convertColor(c, a) - RGBA{Float32}(c) -end -function scalar_color(plotattributes, sym) - gl_color(extract_color(plotattributes, sym)) -end - -function gl_color_map(plotattributes, sym) - colors = extract_color(plotattributes, sym) - _gl_color_map(colors) -end -function _gl_color_map(colors::PlotUtils.ColorGradient) - colors.colors -end -function _gl_color_map(c) - Plots.default_gradient() -end - - - -dist(a, b) = abs(a-b) -mindist(x, a, b) = NaNMath.min(dist(a, x), dist(b, x)) - -function gappy(x, ps) - n = length(ps) - x <= first(ps) && return first(ps) - x - for j=1:(n-1) - p0 = ps[j] - p1 = ps[NaNMath.min(j+1, n)] - if p0 <= x && p1 >= x - return mindist(x, p0, p1) * (isodd(j) ? 1 : -1) - end - end - return last(ps) - x -end -function ticks(points, resolution) - Float16[gappy(x, points) for x = range(first(points), stop=last(points), length=resolution)] -end - - -function insert_pattern!(points, kw_args) - tex = GLAbstraction.Texture(ticks(points, 100), x_repeat=:repeat) - kw_args[:pattern] = tex - kw_args[:pattern_length] = Float32(last(points)) -end -function extract_linestyle(plotattributes, kw_args) - haskey(plotattributes, :linestyle) || return - ls = plotattributes[:linestyle] - lw = plotattributes[:linewidth] - kw_args[:thickness] = Float32(lw) - if ls == :dash - points = [0.0, lw, 2lw, 3lw, 4lw] - insert_pattern!(points, kw_args) - elseif ls == :dot - tick, gap = lw/2, lw/4 - points = [0.0, tick, tick+gap, 2tick+gap, 2tick+2gap] - insert_pattern!(points, kw_args) - elseif ls == :dashdot - dtick, dgap = lw, lw - ptick, pgap = lw/2, lw/4 - points = [0.0, dtick, dtick+dgap, dtick+dgap+ptick, dtick+dgap+ptick+pgap] - insert_pattern!(points, kw_args) - elseif ls == :dashdotdot - dtick, dgap = lw, lw - ptick, pgap = lw/2, lw/4 - points = [0.0, dtick, dtick+dgap, dtick+dgap+ptick, dtick+dgap+ptick+pgap, dtick+dgap+ptick+pgap+ptick, dtick+dgap+ptick+pgap+ptick+pgap] - insert_pattern!(points, kw_args) - end - extract_c(plotattributes, kw_args, :line) - nothing -end - -function hover(to_hover::Vector, to_display, window) - hover(to_hover[], to_display, window) -end - -function get_cam(x) - if isa(x, GLAbstraction.Context) - return get_cam(x.children) - elseif isa(x, Vector) - return get_cam(first(x)) - elseif isa(x, GLAbstraction.RenderObject) - return x[:preferred_camera] - end -end - - -function hover(to_hover, to_display, window) - if isa(to_hover, GLAbstraction.Context) - return hover(to_hover.children, to_display, window) - end - area = map(window.inputs[:mouseposition]) do mp - SimpleRectangle{Int}(round(Int, mp+10)..., 100, 70) - end - mh = GLWindow.mouse2id(window) - popup = GLWindow.Screen( - window, - hidden = map(mh-> !(mh.id == to_hover.id), mh), - area = area, - stroke = (2f0, RGBA(0f0, 0f0, 0f0, 0.8f0)) - ) - cam = get!(popup.cameras, :perspective) do - GLAbstraction.PerspectiveCamera( - popup.inputs, Vec3f0(3), Vec3f0(0), - keep = Signal(false), - theta = Signal(Vec3f0(0)), trans = Signal(Vec3f0(0)) - ) - end - - map(enumerate(to_display)) do id - i,d = id - robj = visualize(d) - viewit = Reactive.droprepeats(map(mh->mh.id == to_hover.id && mh.index == i, mh)) - camtype = get_cam(robj) - Reactive.preserve(map(viewit) do vi - if vi - empty!(popup) - if camtype == :perspective - cam.projectiontype.value = GLVisualize.PERSPECTIVE - else - cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC - end - GLVisualize._view(robj, popup, camera = cam) - bb = GLAbstraction.boundingbox(robj).value - mini = minimum(bb) - w = GeometryTypes.widths(bb) - wborder = w * 0.08f0 #8 percent border - bb = GeometryTypes.AABB{Float32}(mini - wborder, w + 2 * wborder) - GLAbstraction.center!(cam, bb) - end - end) - end - nothing -end - -function extract_extrema(plotattributes, kw_args) - xmin, xmax = ignorenan_extrema(plotattributes[:x]); ymin, ymax = ignorenan_extrema(plotattributes[:y]) - kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(xmin, ymin, xmax-xmin, ymax-ymin) - nothing -end - -function extract_font(font, kw_args) - kw_args[:family] = font.family - kw_args[:relative_scale] = pointsize(font) - kw_args[:color] = gl_color(font.color) -end - -function extract_colornorm(plotattributes, kw_args) - clims = plotattributes[:subplot][:clims] - if Plots.is_2tuple(clims) - if isfinite(clims[1]) && isfinite(clims[2]) - kw_args[:color_norm] = Vec2f0(clims) - end - elseif clims == :auto - z = if haskey(plotattributes, :marker_z) && plotattributes[:marker_z] != nothing - plotattributes[:marker_z] - elseif haskey(plotattributes, :line_z) && plotattributes[:line_z] != nothing - plotattributes[:line_z] - elseif isa(plotattributes[:z], Plots.Surface) - plotattributes[:z].surf - else - plotattributes[:y] - end - kw_args[:color_norm] = Vec2f0(ignorenan_extrema(z)) - kw_args[:intensity] = map(Float32, collect(z)) - end -end - -function extract_gradient(plotattributes, kw_args, sym) - key = Symbol("$(sym)color") - haskey(plotattributes, key) || return - c = make_gradient(plotattributes[key]) - kw_args[:color] = nothing - extract_colornorm(plotattributes, kw_args) - kw_args[:color_map] = c - return -end - -function extract_c(plotattributes, kw_args, sym) - key = Symbol("$(sym)color") - haskey(plotattributes, key) || return - c = gl_color(plotattributes[key]) - kw_args[:color] = nothing - kw_args[:color_map] = nothing - kw_args[:color_norm] = nothing - if ( - isa(c, AbstractVector) && - ((haskey(plotattributes, :marker_z) && plotattributes[:marker_z] != nothing) || - (haskey(plotattributes, :line_z) && plotattributes[:line_z] != nothing)) - ) - extract_colornorm(plotattributes, kw_args) - kw_args[:color_map] = c - else - kw_args[:color] = c - end - return -end - -function extract_stroke(plotattributes, kw_args, sym) - key = Symbol("$(sym)strokecolor") - haskey(plotattributes, key) || return - c = gl_color(plotattributes[key]) - if c != nothing - if !isa(c, Colorant) - error("Stroke Color not supported: $c") - end - kw_args[:stroke_color] = c - kw_args[:stroke_width] = Float32(plotattributes[Symbol("$(sym)strokewidth")]) * 2 - end - return -end - - - -function draw_grid_lines(sp, grid_segs, thickness, style, model, color) - - kw_args = Dict{Symbol, Any}( - :model => model - ) - plotattributes = Dict( - :linestyle => style, - :linewidth => Float32(thickness), - :linecolor => color - ) - Plots.extract_linestyle(plotattributes, kw_args) - GL.gl_lines(map(Point2f0, grid_segs.pts), kw_args) -end - -function align_offset(startpos, lastpos, atlas, rscale, font, align) - xscale, yscale = GLVisualize.glyph_scale!('X', rscale) - xmove = (lastpos-startpos)[1] + xscale - if isa(align, GeometryTypes.Vec) - return -Vec2f0(xmove, yscale) .* align - elseif align == :top - return -Vec2f0(xmove/2f0, yscale) - elseif align == :right - return -Vec2f0(xmove, yscale/2f0) - else - error("Align $align not known") - end -end - - -function alignment2num(x::Symbol) - (x in (:hcenter, :vcenter)) && return 0.5 - (x in (:left, :bottom)) && return 0.0 - (x in (:right, :top)) && return 1.0 - 0.0 # 0 default, or better to error? -end - -function alignment2num(font::Plots.Font) - Vec2f0(map(alignment2num, (font.halign, font.valign))) -end - -pointsize(font) = font.pointsize * 2 - -function draw_ticks( - axis, ticks, isx, isorigin, lims, m, text = "", - positions = Point2f0[], offsets=Vec2f0[] - ) - sz = pointsize(tickfont(axis)) - atlas = GLVisualize.get_texture_atlas() - font = GLVisualize.defaultfont() - - flip = axis[:flip]; mirror = axis[:mirror] - - align = if isx - mirror ? :bottom : :top - else - mirror ? :left : :right - end - axis_gap = Point2f0(isx ? 0 : sz / 2, isx ? sz / 2 : 0) - for (cv, dv) in zip(ticks...) - - x, y = cv, lims[1] - xy = if isorigin - isx ? (x, 0) : (0, x) - else - isx ? (x, y) : (y, x) - end - _pos = m * GeometryTypes.Vec4f0(xy[1], xy[2], 0, 1) - startpos = Point2f0(_pos[1], _pos[2]) - axis_gap - str = string(dv) - # need to tag a new UnicodeFun version for this... also the numbers become - # so small that it looks terrible -.- - # _str = split(string(dv), "^") - # if length(_str) == 2 - # _str[2] = UnicodeFun.to_superscript(_str[2]) - # end - # str = join(_str, "") - position = GLVisualize.calc_position(str, startpos, sz, font, atlas) - offset = GLVisualize.calc_offset(str, sz, font, atlas) - alignoff = align_offset(startpos, last(position), atlas, sz, font, align) - map!(position, position) do pos - pos .+ alignoff - end - append!(positions, position) - append!(offsets, offset) - text *= str - - end - text, positions, offsets -end - -function glvisualize_text(position, text, kw_args) - text_align = alignment2num(text.font) - startpos = Vec2f0(position) - atlas = GLVisualize.get_texture_atlas() - font = GLVisualize.defaultfont() - rscale = kw_args[:relative_scale] - - position = GLVisualize.calc_position(text.str, startpos, rscale, font, atlas) - offset = GLVisualize.calc_offset(text.str, rscale, font, atlas) - alignoff = align_offset(startpos, last(position), atlas, rscale, font, text_align) - - map!(position, position) do pos - pos .+ alignoff - end - kw_args[:position] = position - kw_args[:offset] = offset - kw_args[:scale_primitive] = true - visualize(text.str, Style(:default), kw_args) -end - -function text_model(font, pivot) - pv = GeometryTypes.Vec3f0(pivot[1], pivot[2], 0) - if font.rotation != 0.0 - rot = Float32(deg2rad(font.rotation)) - rotm = GLAbstraction.rotationmatrix_z(rot) - return GLAbstraction.translationmatrix(pv)*rotm*GLAbstraction.translationmatrix(-pv) - else - eye(GeometryTypes.Mat4f0) - end -end -function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, area) - xticks, yticks, xspine_segs, yspine_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xminorgrid_segs, yminorgrid_segs, xborder_segs, yborder_segs = Plots.axis_drawing_info(sp) - xaxis = sp[:xaxis]; yaxis = sp[:yaxis] - - xgc = Colors.color(Plots.gl_color(xaxis[:foreground_color_grid])) - ygc = Colors.color(Plots.gl_color(yaxis[:foreground_color_grid])) - axis_vis = [] - if xaxis[:grid] - grid = draw_grid_lines(sp, xgrid_segs, xaxis[:gridlinewidth], xaxis[:gridstyle], model, RGBA(xgc, xaxis[:gridalpha])) - push!(axis_vis, grid) - end - if yaxis[:grid] - grid = draw_grid_lines(sp, ygrid_segs, yaxis[:gridlinewidth], yaxis[:gridstyle], model, RGBA(ygc, yaxis[:gridalpha])) - push!(axis_vis, grid) - end - if xaxis[:minorgrid] - minorgrid = draw_minorgrid_lines(sp, xminorgrid_segs, xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], model, RGBA(xgc, xaxis[:minorgridalpha])) - push!(axis_vis, minorgrid) - end - if yaxis[:minorgrid] - minorgrid = draw_minorgrid_lines(sp, yminorgrid_segs, yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], model, RGBA(ygc, yaxis[:minorgridalpha])) - push!(axis_vis, minorgrid) - end - - xac = Colors.color(Plots.gl_color(xaxis[:foreground_color_axis])) - yac = Colors.color(Plots.gl_color(yaxis[:foreground_color_axis])) - if alpha(xaxis[:foreground_color_axis]) > 0 - spine = draw_grid_lines(sp, xspine_segs, 1f0, :solid, model, RGBA(xac, 1.0f0)) - push!(axis_vis, spine) - end - if alpha(yaxis[:foreground_color_axis]) > 0 - spine = draw_grid_lines(sp, yspine_segs, 1f0, :solid, model, RGBA(yac, 1.0f0)) - push!(axis_vis, spine) - end - if sp[:framestyle] in (:zerolines, :grid) - if alpha(xaxis[:foreground_color_grid]) > 0 - spine = draw_grid_lines(sp, xtick_segs, 1f0, :solid, model, RGBA(xgc, xaxis[:gridalpha])) - push!(axis_vis, spine) - end - if alpha(yaxis[:foreground_color_grid]) > 0 - spine = draw_grid_lines(sp, ytick_segs, 1f0, :solid, model, RGBA(ygc, yaxis[:gridalpha])) - push!(axis_vis, spine) - end - else - if alpha(xaxis[:foreground_color_axis]) > 0 - spine = draw_grid_lines(sp, xtick_segs, 1f0, :solid, model, RGBA(xac, 1.0f0)) - push!(axis_vis, spine) - end - if alpha(yaxis[:foreground_color_axis]) > 0 - spine = draw_grid_lines(sp, ytick_segs, 1f0, :solid, model, RGBA(yac, 1.0f0)) - push!(axis_vis, spine) - end - end - fcolor = Plots.gl_color(xaxis[:foreground_color_axis]) - - xlim = Plots.axis_limits(xaxis) - ylim = Plots.axis_limits(yaxis) - - if !(xaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none) && xaxis[:showaxis] - ticklabels = map(model) do m - mirror = xaxis[:mirror] - t, positions, offsets = draw_ticks(xaxis, xticks, true, sp[:framestyle] == :origin, ylim, m) - end - kw_args = Dict{Symbol, Any}( - :position => map(x-> x[2], ticklabels), - :offset => map(last, ticklabels), - :color => fcolor, - :relative_scale => pointsize(tickfont(xaxis)), - :scale_primitive => false - ) - push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args)) - end - - if !(yaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none) && yaxis[:showaxis] - ticklabels = map(model) do m - mirror = yaxis[:mirror] - t, positions, offsets = draw_ticks(yaxis, yticks, false, sp[:framestyle] == :origin, xlim, m) - end - kw_args = Dict{Symbol, Any}( - :position => map(x-> x[2], ticklabels), - :offset => map(last, ticklabels), - :color => fcolor, - :relative_scale => pointsize(tickfont(xaxis)), - :scale_primitive => false - ) - push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args)) - end - - xbc = Colors.color(Plots.gl_color(xaxis[:foreground_color_border])) - ybc = Colors.color(Plots.gl_color(yaxis[:foreground_color_border])) - intensity = sp[:framestyle] == :semi ? 0.5f0 : 1.0f0 - if sp[:framestyle] in (:box, :semi) - xborder = draw_grid_lines(sp, xborder_segs, intensity, :solid, model, RGBA(xbc, intensity)) - yborder = draw_grid_lines(sp, yborder_segs, intensity, :solid, model, RGBA(ybc, intensity)) - push!(axis_vis, xborder, yborder) - end - - area_w = GeometryTypes.widths(area) - if sp[:title] != "" - tf = titlefont(sp) - font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, tf.rotation, tf.color) - xy = Point2f0(area.w/2, area_w[2] + pointsize(tf)/2) - kw = Dict(:model => text_model(font, xy), :scale_primitive => true) - extract_font(font, kw) - t = PlotText(sp[:title], font) - push!(axis_vis, glvisualize_text(xy, t, kw)) - end - if xaxis[:guide] != "" - tf = guidefont(xaxis) - xy = Point2f0(area.w/2, - pointsize(tf)/2) - font = Plots.Font(tf.family, tf.pointsize, :hcenter, :bottom, tf.rotation, tf.color) - kw = Dict(:model => text_model(font, xy), :scale_primitive => true) - t = PlotText(xaxis[:guide], font) - extract_font(font, kw) - push!(axis_vis, glvisualize_text(xy, t, kw)) - end - - if yaxis[:guide] != "" - tf = guidefont(yaxis) - font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, 90f0, tf.color) - xy = Point2f0(-pointsize(tf)/2, area.h/2) - kw = Dict(:model => text_model(font, xy), :scale_primitive=>true) - t = PlotText(yaxis[:guide], font) - extract_font(font, kw) - push!(axis_vis, glvisualize_text(xy, t, kw)) - end - - axis_vis -end - -function gl_draw_axes_3d(sp, model) - x = Plots.axis_limits(sp[:xaxis]) - y = Plots.axis_limits(sp[:yaxis]) - z = Plots.axis_limits(sp[:zaxis]) - - min = Vec3f0(x[1], y[1], z[1]) - visualize( - GeometryTypes.AABB{Float32}(min, Vec3f0(x[2], y[2], z[2])-min), - :grid, model=model - ) -end - -function gl_bar(plotattributes, kw_args) - x, y = plotattributes[:x], plotattributes[:y] - nx, ny = length(x), length(y) - axis = plotattributes[:subplot][isvertical(plotattributes) ? :xaxis : :yaxis] - cv = [discrete_value!(axis, xi)[1] for xi=x] - x = if nx == ny - cv - elseif nx == ny + 1 - 0.5diff(cv) + cv[1:end-1] - else - error("bar recipe: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))") - end - if haskey(kw_args, :stroke_width) # stroke is inside for bars - #kw_args[:stroke_width] = -kw_args[:stroke_width] - end - # compute half-width of bars - bw = nothing - hw = if bw == nothing - ignorenan_mean(diff(x)) - else - Float64[_cycle(bw,i)*0.5 for i=1:length(x)] - end - - # make fillto a vector... default fills to 0 - fillto = plotattributes[:fillrange] - if fillto == nothing - fillto = 0 - end - # create the bar shapes by adding x/y segments - positions, scales = Array{Point2f0}(undef, ny), Array{Vec2f0}(undef, ny) - m = Reactive.value(kw_args[:model]) - sx, sy = m[1,1], m[2,2] - for i=1:ny - center = x[i] - hwi = abs(_cycle(hw,i)); yi = y[i]; fi = _cycle(fillto,i) - if Plots.isvertical(plotattributes) - sz = (hwi*sx, yi*sy) - else - sz = (yi*sx, hwi*2*sy) - end - positions[i] = (center-hwi*0.5, fi) - scales[i] = sz - end - - kw_args[:scale] = scales - kw_args[:offset] = Vec2f0(0) - visualize((GLVisualize.RECTANGLE, positions), Style(:default), kw_args) - #[] -end - -const _box_halfwidth = 0.4 - -notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N) - -function gl_boxplot(plotattributes, kw_args) - kwbox = copy(kw_args) - range = 1.5; notch = false - x, y = plotattributes[:x], plotattributes[:y] - glabels = sort(collect(unique(x))) - warning = false - outliers_x, outliers_y = zeros(0), zeros(0) - - box_pos = Point2f0[] - box_scale = Vec2f0[] - outliers = Point2f0[] - t_segments = Point2f0[] - m = Reactive.value(kw_args[:model]) - sx, sy = m[1,1], m[2,2] - for (i,glabel) in enumerate(glabels) - # filter y - values = y[filter(i -> _cycle(x,i) == glabel, 1:length(y))] - # compute quantiles - q1,q2,q3,q4,q5 = quantile(values, range(0, stop=1, length=5)) - # notch - n = Plots.notch_width(q2, q4, length(values)) - # warn on inverted notches? - if notch && !warning && ( (q2>(q3-n)) || (q4<(q3+n)) ) - @warn("Boxplot's notch went outside hinges. Set notch to false.") - warning = true # Show the warning only one time - end - - # make the shape - center = Plots.discrete_value!(plotattributes[:subplot][:xaxis], glabel)[1] - hw = plotattributes[:bar_width] == nothing ? Plots._box_halfwidth*2 : _cycle(plotattributes[:bar_width], i) - l, m, r = center - hw/2, center, center + hw/2 - - # internal nodes for notches - L, R = center - 0.5 * hw, center + 0.5 * hw - # outliers - if Float64(range) != 0.0 # if the range is 0.0, the whiskers will extend to the data - limit = range*(q4-q2) - inside = Float64[] - for value in values - if (value < (q2 - limit)) || (value > (q4 + limit)) - push!(outliers, (center, value)) - else - push!(inside, value) - end - end - # change q1 and q5 to show outliers - # using maximum and minimum values inside the limits - q1, q5 = ignorenan_extrema(inside) - end - # Box - if notch - push!(t_segments, (m, q1), (l, q1), (r, q1), (m, q1), (m, q2))# lower T - push!(box_pos, (l, q2));push!(box_scale, (hw*sx, n*sy)) # lower box - push!(box_pos, (l, q4));push!(box_scale, (hw*sx, n*sy)) # upper box - push!(t_segments, (m, q5), (l, q5), (r, q5), (m, q5), (m, q4))# upper T - - else - push!(t_segments, (m, q2), (m, q1), (l, q1), (r, q1))# lower T - push!(box_pos, (l, q2)); push!(box_scale, (hw*sx, (q3-q2)*sy)) # lower box - push!(box_pos, (l, q4)); push!(box_scale, (hw*sx, (q3-q4)*sy)) # upper box - push!(t_segments, (m, q4), (m, q5), (r, q5), (l, q5))# upper T - end - end - kwbox = Dict{Symbol, Any}( - :scale => box_scale, - :model => kw_args[:model], - :offset => Vec2f0(0), - ) - extract_marker(plotattributes, kw_args) - outlier_kw = Dict( - :model => kw_args[:model], - :color => scalar_color(plotattributes, :fill), - :stroke_width => Float32(plotattributes[:markerstrokewidth]), - :stroke_color => scalar_color(plotattributes, :markerstroke), - ) - lines_kw = Dict( - :model => kw_args[:model], - :stroke_width => plotattributes[:linewidth], - :stroke_color => scalar_color(plotattributes, :fill), - ) - vis1 = GLVisualize.visualize((GLVisualize.RECTANGLE, box_pos), Style(:default), kwbox) - vis2 = GLVisualize.visualize((GLVisualize.CIRCLE, outliers), Style(:default), outlier_kw) - vis3 = GLVisualize.visualize(t_segments, Style(:linesegment), lines_kw) - [vis1, vis2, vis3] -end - - -# --------------------------------------------------------------------------- -function gl_viewport(bb, rect) - l, b, bw, bh = bb - rw, rh = rect.w, rect.h - GLVisualize.SimpleRectangle( - round(Int, rw * l), - round(Int, rh * b), - round(Int, rw * bw), - round(Int, rh * bh) - ) -end - -function to_modelmatrix(rect, subrect, rel_plotarea, sp) - xmin, xmax = Plots.axis_limits(sp[:xaxis]) - ymin, ymax = Plots.axis_limits(sp[:yaxis]) - mini, maxi = Vec3f0(xmin, ymin, 0), Vec3f0(xmax, ymax, 1) - if Plots.is3d(sp) - zmin, zmax = Plots.axis_limits(sp[:zaxis]) - mini, maxi = Vec3f0(xmin, ymin, zmin), Vec3f0(xmax, ymax, zmax) - s = Vec3f0(1) ./ (maxi-mini) - return GLAbstraction.scalematrix(s)*GLAbstraction.translationmatrix(-mini) - end - l, b, bw, bh = rel_plotarea - w, h = rect.w*bw, rect.h*bh - x, y = rect.w*l - subrect.x, rect.h*b - subrect.y - t = -mini - s = Vec3f0(w, h, 1) ./ (maxi-mini) - GLAbstraction.translationmatrix(Vec3f0(x,y,0))*GLAbstraction.scalematrix(s)*GLAbstraction.translationmatrix(t) -end - -# ---------------------------------------------------------------- - - -function scale_for_annotations!(series::Series, scaletype::Symbol = :pixels) - anns = series[:series_annotations] - if anns != nothing && anns.baseshape != nothing - # we use baseshape to overwrite the markershape attribute - # with a list of custom shapes for each - msw, msh = anns.scalefactor - offsets = Array{Vec2f0}(undef, length(anns.strs)) - series[:markersize] = map(1:length(anns.strs)) do i - str = _cycle(anns.strs, i) - # get the width and height of the string (in mm) - sw, sh = text_size(str, anns.font.pointsize) - - # how much to scale the base shape? - # note: it's a rough assumption that the shape fills the unit box [-1,-1,1,1], - # so we scale the length-2 shape by 1/2 the total length - xscale = 0.5to_pixels(sw) * 1.8 - yscale = 0.5to_pixels(sh) * 1.8 - - # we save the size of the larger direction to the markersize list, - # and then re-scale a copy of baseshape to match the w/h ratio - s = Vec2f0(xscale, yscale) - offsets[i] = -s - s - end - series[:offset] = offsets - end - return -end - - - - -function _display(plt::Plot{GLVisualizeBackend}, visible = true) - screen = create_window(plt, visible) - sw, sh = plt[:size] - sw, sh = sw*px, sh*px - - for sp in plt.subplots - _3d = Plots.is3d(sp) - # camera = :perspective - # initialize the sub-screen for this subplot - rel_bbox = Plots.bbox_to_pcts(bbox(sp), sw, sh) - sub_area = map(screen.area) do rect - Plots.gl_viewport(rel_bbox, rect) - end - c = plt[:background_color_outside] - sp_screen = GLVisualize.Screen( - screen, color = c, - area = sub_area - ) - sp.o = sp_screen - cam = get!(sp_screen.cameras, :perspective) do - inside = sp_screen.inputs[:mouseinside] - theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle) - GLAbstraction.PerspectiveCamera( - sp_screen.inputs, Vec3f0(3), Vec3f0(0), - keep = inside, theta = theta - ) - end - - rel_plotarea = Plots.bbox_to_pcts(plotarea(sp), sw, sh) - model_m = map(Plots.to_modelmatrix, - screen.area, sub_area, - Signal(rel_plotarea), Signal(sp) - ) - - # loop over the series and add them to the subplot - if !_3d - axis = gl_draw_axes_2d(sp, model_m, Reactive.value(sub_area)) - GLVisualize._view(axis, sp_screen, camera=:perspective) - cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC - Reactive.run_till_now() # make sure Reactive.push! arrives - GLAbstraction.center!(cam, - GeometryTypes.AABB( - Vec3f0(-20), Vec3f0((GeometryTypes.widths(sp_screen)+40f0)..., 1) - ) - ) - else - axis = gl_draw_axes_3d(sp, model_m) - GLVisualize._view(axis, sp_screen, camera=:perspective) - push!(cam.projectiontype, GLVisualize.PERSPECTIVE) - end - for series in Plots.series_list(sp) - - plotattributes = series.plotattributes - st = plotattributes[:seriestype]; kw_args = KW() # exctract kw - - kw_args[:model] = model_m # add transformation - if !_3d # 3D is treated differently, since we need boundingboxes for camera - kw_args[:boundingbox] = nothing # don't calculate bb, we dont need it - end - scale_for_annotations!(series) - if st in (:surface, :wireframe) - x, y, z = extract_surface(plotattributes) - extract_gradient(plotattributes, kw_args, :fill) - z = Plots.transpose_z(plotattributes, z, false) - if isa(x, AbstractMatrix) && isa(y, AbstractMatrix) - x, y = Plots.transpose_z(plotattributes, x, false), Plots.transpose_z(plotattributes, y, false) - end - if st == :wireframe - kw_args[:wireframe] = true - kw_args[:stroke_color] = plotattributes[:linecolor] - kw_args[:stroke_width] = Float32(plotattributes[:linewidth]/100f0) - end - vis = GL.gl_surface(x, y, z, kw_args) - elseif (st in (:path, :path3d, :straightline)) && plotattributes[:linewidth] > 0 - kw = copy(kw_args) - points = Plots.extract_points(plotattributes) - extract_linestyle(plotattributes, kw) - vis = GL.gl_lines(points, kw) - if plotattributes[:markershape] != :none - kw = copy(kw_args) - extract_stroke(plotattributes, kw) - extract_marker(plotattributes, kw) - vis2 = GL.gl_scatter(copy(points), kw) - vis = [vis; vis2] - end - if plotattributes[:fillrange] != nothing - kw = copy(kw_args) - fr = plotattributes[:fillrange] - ps = if all(x-> x >= 0, diff(plotattributes[:x])) # if is monotonic - vcat(points, Point2f0[(points[i][1], _cycle(fr, i)) for i=length(points):-1:1]) - else - points - end - extract_c(plotattributes, kw, :fill) - vis = [GL.gl_poly(ps, kw), vis] - end - elseif st in (:scatter, :scatter3d) #|| plotattributes[:markershape] != :none - extract_marker(plotattributes, kw_args) - points = extract_points(plotattributes) - vis = GL.gl_scatter(points, kw_args) - elseif st == :shape - extract_c(plotattributes, kw_args, :fill) - vis = GL.gl_shape(plotattributes, kw_args) - elseif st == :contour - x,y,z = extract_surface(plotattributes) - z = transpose_z(plotattributes, z, false) - extract_extrema(plotattributes, kw_args) - extract_gradient(plotattributes, kw_args, :fill) - kw_args[:fillrange] = plotattributes[:fillrange] - kw_args[:levels] = plotattributes[:levels] - - vis = GL.gl_contour(x,y,z, kw_args) - elseif st == :heatmap - x,y,z = extract_surface(plotattributes) - extract_gradient(plotattributes, kw_args, :fill) - extract_extrema(plotattributes, kw_args) - extract_limits(sp, plotattributes, kw_args) - vis = GL.gl_heatmap(x,y,z, kw_args) - elseif st == :bar - extract_c(plotattributes, kw_args, :fill) - extract_stroke(plotattributes, kw_args, :marker) - vis = gl_bar(plotattributes, kw_args) - elseif st == :image - extract_extrema(plotattributes, kw_args) - vis = GL.gl_image(plotattributes[:z].surf, kw_args) - elseif st == :boxplot - extract_c(plotattributes, kw_args, :fill) - vis = gl_boxplot(plotattributes, kw_args) - elseif st == :volume - volume = plotattributes[:y] - _plotattributes = copy(plotattributes) - _plotattributes[:y] = 0:1 - _plotattributes[:x] = 0:1 - kw_args = KW() - extract_gradient(_plotattributes, kw_args, :fill) - vis = visualize(volume.v, Style(:default), kw_args) - else - error("failed to display plot type $st") - end - - isa(vis, Array) && isempty(vis) && continue # nothing to see here - - GLVisualize._view(vis, sp_screen, camera=:perspective) - if haskey(plotattributes, :hover) && !(plotattributes[:hover] in (false, :none, nothing)) - hover(vis, plotattributes[:hover], sp_screen) - end - if isdefined(:GLPlot) && isdefined(Main.GLPlot, :(register_plot!)) - del_signal = Main.GLPlot.register_plot!(vis, sp_screen, create_gizmo=false) - append!(_glplot_deletes, del_signal) - end - anns = series[:series_annotations] - for (x, y, str, font) in EachAnn(anns, plotattributes[:x], plotattributes[:y]) - txt_args = Dict{Symbol, Any}(:model => eye(GLAbstraction.Mat4f0)) - x, y = Reactive.value(model_m) * GeometryTypes.Vec{4, Float32}(x, y, 0, 1) - extract_font(font, txt_args) - t = glvisualize_text(Point2f0(x, y), PlotText(str, font), txt_args) - GLVisualize._view(t, sp_screen, camera = :perspective) - end - - end - generate_legend(sp, sp_screen, model_m) - if _3d - GLAbstraction.center!(sp_screen) - end - GLAbstraction.post_empty() - yield() - end -end - -function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend}) - _display(plt, false) - GLWindow.poll_glfw() - if Base.n_avail(Reactive._messages) > 0 - Reactive.run_till_now() - end - yield() - GLWindow.render_frame(GLWindow.rootscreen(plt.o)) - GLWindow.swapbuffers(plt.o) - buff = GLWindow.screenbuffer(plt.o) - png = map(RGB{U8}, buff) - FileIO.save(FileIO.Stream(FileIO.DataFormat{:PNG}, io), png) -end - - -function gl_image(img, kw_args) - rect = kw_args[:primitive] - kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(rect.x, rect.y, rect.w, rect.h) - visualize(img, Style(:default), kw_args) -end - -function handle_segment(lines, line_segments, points::Vector{P}, segment) where P - (isempty(segment) || length(segment) < 2) && return - if length(segment) == 2 - append!(line_segments, view(points, segment)) - elseif length(segment) == 3 - p = view(points, segment) - push!(line_segments, p[1], p[2], p[2], p[3]) - else - append!(lines, view(points, segment)) - push!(lines, P(NaN)) - end -end - -function gl_lines(points, kw_args) - result = [] - isempty(points) && return result - P = eltype(points) - lines = P[] - line_segments = P[] - last = 1 - for (i,p) in enumerate(points) - if isnan(p) || i==length(points) - _i = isnan(p) ? i-1 : i - handle_segment(lines, line_segments, points, last:_i) - last = i+1 - end - end - if !isempty(lines) - pop!(lines) # remove last NaN - push!(result, visualize(lines, Style(:lines), kw_args)) - end - if !isempty(line_segments) - push!(result, visualize(line_segments, Style(:linesegment), kw_args)) - end - return result -end - -function gl_shape(plotattributes, kw_args) - points = Plots.extract_points(plotattributes) - result = [] - for rng in iter_segments(plotattributes[:x], plotattributes[:y]) - ps = points[rng] - meshes = gl_poly(ps, kw_args) - append!(result, meshes) - end - result -end - - - -function gl_scatter(points, kw_args) - prim = get(kw_args, :primitive, GeometryTypes.Circle) - if isa(prim, GLNormalMesh) - if haskey(kw_args, :model) - p = get(kw_args, :perspective, eye(GeometryTypes.Mat4f0)) - kw_args[:scale] = GLAbstraction.const_lift(kw_args[:model], kw_args[:scale], p) do m, sc, p - s = Vec3f0(m[1,1], m[2,2], m[3,3]) - ps = Vec3f0(p[1,1], p[2,2], p[3,3]) - r = sc ./ (s .* ps) - r - end - end - else # 2D prim - kw_args[:scale] = to_vec(Vec2f0, kw_args[:scale]) - end - - if haskey(kw_args, :stroke_width) - s = Reactive.value(kw_args[:scale]) - sw = kw_args[:stroke_width] - if sw*5 > _cycle(Reactive.value(s), 1)[1] # restrict marker stroke to 1/10th of scale (and handle arrays of scales) - kw_args[:stroke_width] = s[1] / 5f0 - end - end - kw_args[:scale_primitive] = false - if isa(prim, String) - kw_args[:position] = points - if !isa(kw_args[:scale], Vector) # if not vector, we can assume it's relative scale - kw_args[:relative_scale] = kw_args[:scale] - delete!(kw_args, :scale) - end - return visualize(prim, Style(:default), kw_args) - end - - visualize((prim, points), Style(:default), kw_args) -end - - -function gl_poly(points, kw_args) - last(points) == first(points) && pop!(points) - polys = GeometryTypes.split_intersections(points) - result = [] - for poly in polys - mesh = GLNormalMesh(poly) # make polygon - if !isempty(GeometryTypes.faces(mesh)) # check if polygonation has any faces - push!(result, GLVisualize.visualize(mesh, Style(:default), kw_args)) - else - @warn("Couldn't draw the polygon: $points") - end - end - result -end - - - - -function gl_surface(x,y,z, kw_args) - if isa(x, AbstractRange) && isa(y, AbstractRange) - main = z - kw_args[:ranges] = (x, y) - else - if isa(x, AbstractMatrix) && isa(y, AbstractMatrix) - main = map(s->map(Float32, s), (x, y, z)) - elseif isa(x, AbstractVector) || isa(y, AbstractVector) - x = Float32[x[i] for i = 1:size(z,1), j = 1:size(z,2)] - y = Float32[y[j] for i = 1:size(z,1), j = 1:size(z,2)] - main = (x, y, map(Float32, z)) - else - error("surface: combination of types not supported: $(typeof(x)) $(typeof(y)) $(typeof(z))") - end - if get(kw_args, :wireframe, false) - points = map(Point3f0, zip(vec(x), vec(y), vec(z))) - faces = Cuint[] - idx = (i,j) -> CartesianIndices(size(z), i, j) - 1 - for i=1:size(z,1), j=1:size(z,2) - - i < size(z,1) && push!(faces, idx(i, j), idx(i+1, j)) - j < size(z,2) && push!(faces, idx(i, j), idx(i, j+1)) - - end - color = get(kw_args, :stroke_color, RGBA{Float32}(0,0,0,1)) - kw_args[:color] = color - kw_args[:thickness] = Float32(get(kw_args, :stroke_width, 1f0)) - kw_args[:indices] = faces - delete!(kw_args, :stroke_color) - delete!(kw_args, :stroke_width) - - return visualize(points, Style(:linesegment), kw_args) - end - end - return visualize(main, Style(:surface), kw_args) -end - - -function gl_contour(x, y, z, kw_args) - if kw_args[:fillrange] != nothing - - delete!(kw_args, :intensity) - I = GLVisualize.Intensity{Float32} - main = [I(z[j,i]) for i=1:size(z, 2), j=1:size(z, 1)] - return visualize(main, Style(:default), kw_args) - - else - h = kw_args[:levels] - T = eltype(z) - levels = Contour.contours(map(T, x), map(T, y), z, h) - result = Point2f0[] - zmin, zmax = get(kw_args, :limits, Vec2f0(ignorenan_extrema(z))) - cmap = get(kw_args, :color_map, get(kw_args, :color, RGBA{Float32}(0,0,0,1))) - colors = RGBA{Float32}[] - for c in levels.contours - for elem in c.lines - append!(result, elem.vertices) - push!(result, Point2f0(NaN32)) - col = GLVisualize.color_lookup(cmap, c.level, zmin, zmax) - append!(colors, fill(col, length(elem.vertices) + 1)) - end - end - kw_args[:color] = colors - kw_args[:color_map] = nothing - kw_args[:color_norm] = nothing - kw_args[:intensity] = nothing - return visualize(result, Style(:lines),kw_args) - end -end - - -function gl_heatmap(x,y,z, kw_args) - get!(kw_args, :color_norm, Vec2f0(ignorenan_extrema(z))) - get!(kw_args, :color_map, Plots.make_gradient(cgrad())) - delete!(kw_args, :intensity) - I = GLVisualize.Intensity{Float32} - heatmap = I[z[j,i] for i=1:size(z, 2), j=1:size(z, 1)] - tex = GLAbstraction.Texture(heatmap, minfilter=:nearest) - kw_args[:stroke_width] = 0f0 - kw_args[:levels] = 1f0 - visualize(tex, Style(:default), kw_args) -end - - - - -""" -Ugh, so much special casing (╯°□°)╯︵ ┻━┻ -""" -function label_scatter(plotattributes, w, ho) - kw = KW() - extract_stroke(plotattributes, kw) - extract_marker(plotattributes, kw) - kw[:scale] = Vec2f0(w/2) - kw[:offset] = Vec2f0(-w/4) - if haskey(kw, :intensity) - cmap = kw[:color_map] - norm = kw[:color_norm] - kw[:color] = GLVisualize.color_lookup(cmap, kw[:intensity][1], norm) - delete!(kw, :intensity) - delete!(kw, :color_map) - delete!(kw, :color_norm) - else - color = get(kw, :color, nothing) - kw[:color] = isa(color, Array) ? first(color) : color - end - strcolor = get(kw, :stroke_color, RGBA{Float32}(0,0,0,0)) - kw[:stroke_color] = isa(strcolor, Array) ? first(strcolor) : strcolor - p = get(kw, :primitive, GeometryTypes.Circle) - if isa(p, GLNormalMesh) - bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p)) - bbw = GeometryTypes.widths(bb) - if isapprox(bbw[3], 0) - bbw = Vec3f0(bbw[1], bbw[2], 1) - end - mini = minimum(bb) - m = GLAbstraction.translationmatrix(-mini) - m *= GLAbstraction.scalematrix(1 ./ bbw) - kw[:primitive] = m * p - kw[:scale] = Vec3f0(w/2) - delete!(kw, :offset) - end - if isa(p, Array) - kw[:primitive] = GeometryTypes.Circle - end - GL.gl_scatter(Point2f0[(w/2, ho)], kw) -end - - -function make_label(sp, series, i) - GL = Plots - w, gap, ho = 20f0, 5f0, 5 - result = [] - plotattributes = series.plotattributes - st = plotattributes[:seriestype] - kw_args = KW() - if (st in (:path, :path3d, :straightline)) && plotattributes[:linewidth] > 0 - points = Point2f0[(0, ho), (w, ho)] - kw = KW() - extract_linestyle(plotattributes, kw) - append!(result, GL.gl_lines(points, kw)) - if plotattributes[:markershape] != :none - push!(result, label_scatter(plotattributes, w, ho)) - end - elseif st in (:scatter, :scatter3d) #|| plotattributes[:markershape] != :none - push!(result, label_scatter(plotattributes, w, ho)) - else - extract_c(plotattributes, kw_args, :fill) - if isa(kw_args[:color], AbstractVector) - kw_args[:color] = first(kw_args[:color]) - end - push!(result, visualize( - GeometryTypes.SimpleRectangle(-w/2, ho-w/4, w/2, w/2), - Style(:default), kw_args - )) - end - labeltext = if isa(series[:label], Array) - i += 1 - series[:label][i] - else - series[:label] - end - ft = legendfont(sp) - font = Plots.Font(ft.family, ft.pointsize, :left, :bottom, 0.0, ft.color) - xy = Point2f0(w+gap, 0.0) - kw = Dict(:model => text_model(font, xy), :scale_primitive=>false) - extract_font(font, kw) - t = PlotText(labeltext, font) - push!(result, glvisualize_text(xy, t, kw)) - GLAbstraction.Context(result...), i -end - - -function generate_legend(sp, screen, model_m) - legend = GLAbstraction.Context[] - if sp[:legend] != :none - i = 0 - for series in series_list(sp) - should_add_to_legend(series) || continue - result, i = make_label(sp, series, i) - push!(legend, result) - end - if isempty(legend) - return - end - list = visualize(legend, gap=Vec3f0(0,5,0)) - bb = GLAbstraction._boundingbox(list) - wx,wy,_ = GeometryTypes.widths(bb) - xmin, _ = Plots.axis_limits(sp[:xaxis]) - _, ymax = Plots.axis_limits(sp[:yaxis]) - area = map(model_m) do m - p = m * GeometryTypes.Vec4f0(xmin, ymax, 0, 1) - h = round(Int, wy)+20 - w = round(Int, wx)+20 - x,y = round(Int, p[1])+30, round(Int, p[2]-h)-30 - GeometryTypes.SimpleRectangle(x, y, w, h) - end - sscren = GLWindow.Screen( - screen, area = area, - color = sp[:background_color_legend], - stroke = (2f0, RGBA(0.3, 0.3, 0.3, 0.9)) - ) - GLAbstraction.translate!(list, Vec3f0(10,10,0)) - GLVisualize._view(list, sscren, camera=:fixed_pixel) - end - return -end diff --git a/src/init.jl b/src/init.jl index c15975a4..95aa38d0 100644 --- a/src/init.jl +++ b/src/init.jl @@ -19,7 +19,6 @@ function __init__() pushdisplay(PlotsDisplay()) end) - @require GLVisualize = "4086de5b-f4b6-55f3-abb0-b8c73827585f" include(joinpath(@__DIR__, "backends", "glvisualize.jl")) @require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl")) @require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" include(joinpath(@__DIR__, "backends", "inspectdr.jl")) @require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" include(joinpath(@__DIR__, "backends", "pgfplots.jl")) diff --git a/src/output.jl b/src/output.jl index df6e3b84..b3392cc5 100644 --- a/src/output.jl +++ b/src/output.jl @@ -156,7 +156,6 @@ end const _best_html_output_type = KW( :pyplot => :png, :unicodeplots => :txt, - :glvisualize => :png, :plotlyjs => :html, :plotly => :html ) From 85b83e174583101506713ee5045ee8df632fd407 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 30 Oct 2018 11:40:25 +0100 Subject: [PATCH 045/230] add portfoliocomposition --- src/examples.jl | 18 ++++++++++++++++++ src/recipes.jl | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/examples.jl b/src/examples.jl index 7050b1e3..acb6688e 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -435,6 +435,22 @@ each line segment or marker in the plot. end)] ), +PlotExample("Portfolio Composition maps", +""" +see: http://stackoverflow.com/a/37732384/5075246 +""", + [:(begin + tickers = ["IBM", "Google", "Apple", "Intel"] + N = 10 + D = length(tickers) + weights = rand(N,D) + weights ./= sum(weights, 2) + returns = sort!((1:N) + D*randn(N)) + + portfoliocomposition(weights, returns, labels = permutedims(tickers)) + end)] +), + ] # Some constants for PlotDocs and PlotReferenceImages @@ -446,6 +462,8 @@ _backend_skips = Dict( :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30], ) + + # --------------------------------------------------------------------------------- # make and display one plot diff --git a/src/recipes.jl b/src/recipes.jl index 6ac0d11d..4b513a4b 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1131,3 +1131,25 @@ end title := string(grad.args[1]) z end + + +# Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246 +@userplot PortfolioComposition + +# this shows the shifting composition of a basket of something over a variable +# - "returns" are the dependent variable +# - "weights" are a matrix where the ith column is the composition for returns[i] +# - since each polygon is its own series, you can assign labels easily +@recipe function f(pc::PortfolioComposition) + weights, returns = pc.args + n = length(returns) + weights = cumsum(weights,2) + seriestype := :shape + + # create a filled polygon for each item + for c=1:size(weights,2) + sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1])) + sy = vcat(returns, reverse(returns)) + @series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) + end +end From 5e06e0d2d2f8ce70c3ae69e0c135ddedf4ac89c2 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 30 Oct 2018 12:15:07 +0100 Subject: [PATCH 046/230] fix example --- src/examples.jl | 2 +- src/recipes.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples.jl b/src/examples.jl index acb6688e..8e05dec6 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -444,7 +444,7 @@ see: http://stackoverflow.com/a/37732384/5075246 N = 10 D = length(tickers) weights = rand(N,D) - weights ./= sum(weights, 2) + weights ./= sum(weights, dims = 2) returns = sort!((1:N) + D*randn(N)) portfoliocomposition(weights, returns, labels = permutedims(tickers)) diff --git a/src/recipes.jl b/src/recipes.jl index 4b513a4b..5ae3cebf 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1143,7 +1143,7 @@ end @recipe function f(pc::PortfolioComposition) weights, returns = pc.args n = length(returns) - weights = cumsum(weights,2) + weights = cumsum(weights, dims = 2) seriestype := :shape # create a filled polygon for each item From 759cd7b3f2369c8d39bdb61f2cfe2240d5bca02d Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 30 Oct 2018 14:05:18 +0100 Subject: [PATCH 047/230] add seed! --- src/examples.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/examples.jl b/src/examples.jl index 8e05dec6..65737326 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -440,6 +440,8 @@ PlotExample("Portfolio Composition maps", see: http://stackoverflow.com/a/37732384/5075246 """, [:(begin + using Random + Random.seed!(111) tickers = ["IBM", "Google", "Apple", "Intel"] N = 10 D = length(tickers) From af119a024896adc1101b46ffa1e7f0aa224f66c7 Mon Sep 17 00:00:00 2001 From: Diego Javier Zea Date: Tue, 30 Oct 2018 15:15:03 +0100 Subject: [PATCH 048/230] It solves Shape bugs unneeded get and missing undef --- src/components.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components.jl b/src/components.jl index ddd78383..46fc0f7d 100644 --- a/src/components.jl +++ b/src/components.jl @@ -491,7 +491,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels) # with a list of custom shapes for each msw,msh = anns.scalefactor msize = Float64[] - shapes = Vector{Shape}(length(anns.strs)) + shapes = Vector{Shape}(undef, length(anns.strs)) for i in eachindex(anns.strs) str = _cycle(anns.strs,i) @@ -509,7 +509,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels) # and then re-scale a copy of baseshape to match the w/h ratio maxscale = max(xscale, yscale) push!(msize, maxscale) - baseshape = _cycle(get(anns.baseshape),i) + baseshape = _cycle(anns.baseshape, i) shapes[i] = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0)) end series[:markershape] = shapes From 6741287ef15af9ed259d780d042d160432314e77 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 30 Oct 2018 16:06:51 +0100 Subject: [PATCH 049/230] Revert "Transfer portfoliocomposition recipe from PlotRecipes" --- src/examples.jl | 20 -------------------- src/recipes.jl | 22 ---------------------- 2 files changed, 42 deletions(-) diff --git a/src/examples.jl b/src/examples.jl index 65737326..7050b1e3 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -435,24 +435,6 @@ each line segment or marker in the plot. end)] ), -PlotExample("Portfolio Composition maps", -""" -see: http://stackoverflow.com/a/37732384/5075246 -""", - [:(begin - using Random - Random.seed!(111) - tickers = ["IBM", "Google", "Apple", "Intel"] - N = 10 - D = length(tickers) - weights = rand(N,D) - weights ./= sum(weights, dims = 2) - returns = sort!((1:N) + D*randn(N)) - - portfoliocomposition(weights, returns, labels = permutedims(tickers)) - end)] -), - ] # Some constants for PlotDocs and PlotReferenceImages @@ -464,8 +446,6 @@ _backend_skips = Dict( :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30], ) - - # --------------------------------------------------------------------------------- # make and display one plot diff --git a/src/recipes.jl b/src/recipes.jl index 5ae3cebf..6ac0d11d 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1131,25 +1131,3 @@ end title := string(grad.args[1]) z end - - -# Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246 -@userplot PortfolioComposition - -# this shows the shifting composition of a basket of something over a variable -# - "returns" are the dependent variable -# - "weights" are a matrix where the ith column is the composition for returns[i] -# - since each polygon is its own series, you can assign labels easily -@recipe function f(pc::PortfolioComposition) - weights, returns = pc.args - n = length(returns) - weights = cumsum(weights, dims = 2) - seriestype := :shape - - # create a filled polygon for each item - for c=1:size(weights,2) - sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1])) - sy = vcat(returns, reverse(returns)) - @series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) - end -end From 12309c281bdd6bd4e36dcbe9353be7359730ea1d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 30 Oct 2018 16:26:19 +0100 Subject: [PATCH 050/230] Revert "Revert "Transfer portfoliocomposition recipe from PlotRecipes"" --- src/examples.jl | 20 ++++++++++++++++++++ src/recipes.jl | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/examples.jl b/src/examples.jl index 7050b1e3..65737326 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -435,6 +435,24 @@ each line segment or marker in the plot. end)] ), +PlotExample("Portfolio Composition maps", +""" +see: http://stackoverflow.com/a/37732384/5075246 +""", + [:(begin + using Random + Random.seed!(111) + tickers = ["IBM", "Google", "Apple", "Intel"] + N = 10 + D = length(tickers) + weights = rand(N,D) + weights ./= sum(weights, dims = 2) + returns = sort!((1:N) + D*randn(N)) + + portfoliocomposition(weights, returns, labels = permutedims(tickers)) + end)] +), + ] # Some constants for PlotDocs and PlotReferenceImages @@ -446,6 +464,8 @@ _backend_skips = Dict( :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30], ) + + # --------------------------------------------------------------------------------- # make and display one plot diff --git a/src/recipes.jl b/src/recipes.jl index 6ac0d11d..5ae3cebf 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1131,3 +1131,25 @@ end title := string(grad.args[1]) z end + + +# Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246 +@userplot PortfolioComposition + +# this shows the shifting composition of a basket of something over a variable +# - "returns" are the dependent variable +# - "weights" are a matrix where the ith column is the composition for returns[i] +# - since each polygon is its own series, you can assign labels easily +@recipe function f(pc::PortfolioComposition) + weights, returns = pc.args + n = length(returns) + weights = cumsum(weights, dims = 2) + seriestype := :shape + + # create a filled polygon for each item + for c=1:size(weights,2) + sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1])) + sy = vcat(returns, reverse(returns)) + @series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) + end +end From a717bf4f344e861b453e5f48dd26dab5acce4b29 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 31 Oct 2018 12:24:04 +0000 Subject: [PATCH 051/230] Fixes #1827 --- src/plotattr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plotattr.jl b/src/plotattr.jl index e1733984..fb7170e4 100644 --- a/src/plotattr.jl +++ b/src/plotattr.jl @@ -18,7 +18,7 @@ end plotattr([attr]) Look up the properties of a Plots attribute, or specify an attribute type. Call `plotattr()` for options. -The information is the same as that given on https://juliaplots.github.io/attributes/. +The information is the same as that given on https://docs.juliaplots.org/latest/attributes/. """ function plotattr() println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())") From f726151e6ef09d535488dabbf420044fb699323e Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Thu, 8 Nov 2018 19:17:58 -0800 Subject: [PATCH 052/230] Smuggle PyCall and LaTeXStrings through PyPlot fix #1672 fix https://github.com/JuliaPy/PyPlot.jl/issues/389 fix https://github.com/JuliaPy/PyPlot.jl/issues/408 --- src/backends.jl | 8 ++------ src/backends/pyplot.jl | 33 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 11cea85e..eae321f8 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -526,8 +526,7 @@ const _plotlyjs_scale = _plotly_scale function _initialize_backend(::PyPlotBackend) @eval Main begin - import PyPlot, PyCall - import LaTeXStrings + import PyPlot export PyPlot @@ -539,11 +538,8 @@ end function add_backend_string(::PyPlotBackend) """ using Pkg - Pkg.add("PyPlot") - Pkg.add("PyCall") - Pkg.add("LaTeXStrings") withenv("PYTHON" => "") do - Pkg.build("PyCall") + Pkg.add("PyPlot") Pkg.build("PyPlot") end """ diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 0a581a3f..99cf277a 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1,3 +1,6 @@ +# Do "using PyPlot: PyCall, LaTeXStrings" without dependency warning: +const PyCall = PyPlot.PyCall +const LaTeXStrings = PyPlot.LaTeXStrings # https://github.com/stevengj/PyPlot.jl @@ -187,26 +190,22 @@ function add_pyfixedformatter(cbar, vals::AVec) cbar[:update_ticks]() end -@require LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" begin - function labelfunc(scale::Symbol, backend::PyPlotBackend) - if scale == :log10 - x -> LaTeXStrings.latexstring("10^{$x}") - elseif scale == :log2 - x -> LaTeXStrings.latexstring("2^{$x}") - elseif scale == :ln - x -> LaTeXStrings.latexstring("e^{$x}") - else - string - end +function labelfunc(scale::Symbol, backend::PyPlotBackend) + if scale == :log10 + x -> LaTeXStrings.latexstring("10^{$x}") + elseif scale == :log2 + x -> LaTeXStrings.latexstring("2^{$x}") + elseif scale == :ln + x -> LaTeXStrings.latexstring("e^{$x}") + else + string end end -@require PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" begin - function py_mask_nans(z) - # pynp["ma"][:masked_invalid](z))) - PyCall.pycall(pynp["ma"][:masked_invalid], Any, z) - # pynp["ma"][:masked_where](pynp["isnan"](z),z) - end +function py_mask_nans(z) + # pynp["ma"][:masked_invalid](z))) + PyCall.pycall(pynp["ma"][:masked_invalid], Any, z) + # pynp["ma"][:masked_where](pynp["isnan"](z),z) end # --------------------------------------------------------------------------- From af34fdc45abc7a62d861265f20e3b5de3aed92e9 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 11 Nov 2018 21:25:41 +0100 Subject: [PATCH 053/230] add :plain formatter option in arg_desc --- src/arg_desc.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 45dcaaa5..64ce5b93 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -117,7 +117,7 @@ const _arg_desc = KW( :scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", :rotation => "Number. Degrees rotation of tick labels.", :flip => "Bool. Should we flip (reverse) the axis?", -:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.", +:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", :tickfontfamily => "String or Symbol. Font family of tick labels.", :tickfontsize => "Integer. Font pointsize of tick labels.", :tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center", From a2365f2c14fda56fa9864fba00ad395890026610 Mon Sep 17 00:00:00 2001 From: Fabian Greimel Date: Mon, 19 Nov 2018 22:21:21 +0100 Subject: [PATCH 054/230] Use :foreground_color_border for axis color in pgfplot --- src/backends/pgfplots.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 9b351175..e060a2f1 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -405,7 +405,7 @@ function pgf_axis(sp::Subplot, letter) if framestyle == :zerolines push!(style, string("extra ", letter, " ticks = 0")) push!(style, string("extra ", letter, " tick labels = ")) - push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}}")) + push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}}")) end if !axis[:showaxis] @@ -414,7 +414,7 @@ function pgf_axis(sp::Subplot, letter) if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none) push!(style, string(letter, " axis line style = {draw opacity = 0}")) else - push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}")) + push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}")) end # return the style list and KW args From 2643d493a3d11162aea67f16efdef81be24503c2 Mon Sep 17 00:00:00 2001 From: Mauro Date: Wed, 28 Nov 2018 15:27:10 +0000 Subject: [PATCH 055/230] Fix #1799 This may fix #1799. Although, note, I have no deeper understanding of this code... --- src/backends/pyplot.jl | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 99cf277a..ac6b1fed 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -222,17 +222,6 @@ function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series) end end -# total hack due to PyPlot bug (see issue #145). -# hack: duplicate the color vector when the total rgba fields is the same as the series length -function py_color_fix(c, x) - if (typeof(c) <: AbstractArray && length(c)*4 == length(x)) || - (typeof(c) <: Tuple && length(x) == 4) - vcat(c, c) - else - c - end -end - py_linecolor(series::Series) = py_color(series[:linecolor]) py_markercolor(series::Series) = py_color(series[:markercolor]) py_markerstrokecolor(series::Series) = py_color(series[:markerstrokecolor]) @@ -497,7 +486,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) else py_color(plot_color(series[:markercolor], series[:markeralpha])) end - extrakw[:c] = py_color_fix(markercolor, x) + extrakw[:c] = if markercolor isa Array + permutedims(hcat([[m...] for m in markercolor]...),[2,1]) + elseif markercolor isa Tuple + reshape([markercolor...], 1, length(markercolor)) + else + error("This case is not handled. Please file an issue.") + end xyargs = if st == :bar && !isvertical(series) (y, x) else @@ -505,7 +500,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end if isa(series[:markershape], AbstractVector{Shape}) - # this section will create one scatter per data point to accomodate the + # this section will create one scatter per data point to accommodate the # vector of shapes handle = [] x,y = xyargs @@ -789,7 +784,7 @@ function py_set_ticks(ax, ticks, letter) if ticks == :none || ticks == nothing || ticks == false kw = KW() for dir in (:top,:bottom,:left,:right) - kw[dir] = kw[Symbol(:label,dir)] = "off" + kw[dir] = kw[Symbol(:label,dir)] = false end axis[:set_tick_params](;which="both", kw...) return @@ -1052,7 +1047,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) else ax[:spines][string(dir)][:set_visible](false) end - kw[dir] = kw[Symbol(:label,dir)] = "off" + kw[dir] = kw[Symbol(:label,dir)] = false end ax[:xaxis][:set_tick_params](; which="both", kw...) end @@ -1062,7 +1057,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) if !ispolar(sp) ax[:spines][string(dir)][:set_visible](false) end - kw[dir] = kw[Symbol(:label,dir)] = "off" + kw[dir] = kw[Symbol(:label,dir)] = false end ax[:yaxis][:set_tick_params](; which="both", kw...) end From b9b7edc72d53d4858572caf2881fd2f1b82fac6a Mon Sep 17 00:00:00 2001 From: Naoki Saito Date: Sun, 2 Dec 2018 15:37:25 -0800 Subject: [PATCH 056/230] vmin, vmax in KW were suppressed for :wireframe --- src/backends/pyplot.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 0a581a3f..3683a074 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -390,7 +390,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) vmin, vmax = clims = get_clims(sp) # Dict to store extra kwargs - extrakw = KW(:vmin => vmin, :vmax => vmax) + if st == :wireframe + extrakw = KW() # vmin, vmax cause an error for wireframe plot + else + extrakw = KW(:vmin => vmin, :vmax => vmax) + end # holds references to any python object representing the matplotlib series handles = [] From 14cbfb570627a771d72572e0f979cbf93f544daf Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Fri, 7 Dec 2018 08:11:30 +0100 Subject: [PATCH 057/230] fix warn -> @warn --- src/examples.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples.jl b/src/examples.jl index 65737326..9e382eef 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -502,7 +502,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth plts[i] = plt catch ex # TODO: put error info into markdown? - warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex") + @warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex") end if sleep != nothing Base.sleep(sleep) From 6f821e534430dd0876c1c874bc32cb702b2b37d7 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Fri, 7 Dec 2018 08:12:41 +0100 Subject: [PATCH 058/230] MethodError -> ArgumentError --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 5ae3cebf..399b4851 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -47,7 +47,7 @@ end num_series(x::AMat) = size(x,2) num_series(x) = 1 -RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T")) +RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(ArgumentError("Unmatched plot recipe: $T")) # --------------------------------------------------------------------------- From 75be945359e1e953a4778c4a8bf310a2fa6aae3f Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Fri, 7 Dec 2018 08:12:41 +0100 Subject: [PATCH 059/230] Revert "MethodError -> ArgumentError" This reverts commit 6f821e534430dd0876c1c874bc32cb702b2b37d7. --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 399b4851..5ae3cebf 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -47,7 +47,7 @@ end num_series(x::AMat) = size(x,2) num_series(x) = 1 -RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(ArgumentError("Unmatched plot recipe: $T")) +RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T")) # --------------------------------------------------------------------------- From 712b567752989ad3ba9319620a93923577a4259b Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 10 Dec 2018 11:00:30 +0100 Subject: [PATCH 060/230] update news for release --- NEWS.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/NEWS.md b/NEWS.md index 3510105e..79eb968d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,7 +10,21 @@ --- ## (current master) + +## 0.22.0 - deprecate GLVisualize +- allow 1-row and 1-column heatmaps +- add portfoliodecomposition recipe from PlotRecipes +- solve Shape bug +- simplify PyPlot backend installation +- fix wireframe bug in PyPlot +- fix color bug in PyPlot +- minor bug fixes in gr and pyplot + +## 0.21.0 +- Compatibility with StaticArrays 0.9.0 +- Up GR min version to 0.35 +- fix :mirror ## 0.20.6 - fixes for PlotDocs.jl From 4403ed3860714a15ab89a9b6c5f19bc55f412251 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Thu, 27 Dec 2018 10:57:10 +0100 Subject: [PATCH 061/230] insert PlotDisplay directly after REPLDisplay --- src/init.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/init.jl b/src/init.jl index 95aa38d0..e90124a0 100644 --- a/src/init.jl +++ b/src/init.jl @@ -1,3 +1,5 @@ +using REPL + const use_local_dependencies = Ref(false) function __init__() @@ -10,13 +12,14 @@ function __init__() k == :theme || default(k, v) end end - pushdisplay(PlotsDisplay()) + + insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) atreplinit(i -> begin - if PlotDisplay() in Base.Multimedia.displays + while PlotDisplay() in Base.Multimedia.displays popdisplay(PlotsDisplay()) end - pushdisplay(PlotsDisplay()) + insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) end) @require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl")) From 8935728daad6214b1c39386906d3a61f3c469904 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Sat, 29 Dec 2018 09:34:53 +0100 Subject: [PATCH 062/230] PlotDisplay -> PlotsDisplay --- src/init.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.jl b/src/init.jl index e90124a0..257ba4b8 100644 --- a/src/init.jl +++ b/src/init.jl @@ -16,7 +16,7 @@ function __init__() insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) atreplinit(i -> begin - while PlotDisplay() in Base.Multimedia.displays + while PlotsDisplay() in Base.Multimedia.displays popdisplay(PlotsDisplay()) end insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) From d1428b82214c71e729ee1a56d8324f86d5b557be Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 29 Dec 2018 10:05:02 +0100 Subject: [PATCH 063/230] update news.md --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 79eb968d..15d2aaa2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,9 @@ --- ## (current master) +## 0.22.1 +- push PlotsDisplay just after REPLDisplay + ## 0.22.0 - deprecate GLVisualize - allow 1-row and 1-column heatmaps From 7acb5a4bdb0497877b4d214c0cc1a05a8d9bfcf7 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Wed, 2 Jan 2019 17:39:28 +0100 Subject: [PATCH 064/230] allow annotations to take a tuple and pass it to text --- src/components.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components.jl b/src/components.jl index 46fc0f7d..f1f27dc4 100644 --- a/src/components.jl +++ b/src/components.jl @@ -554,7 +554,7 @@ function process_annotation(sp::Subplot, xs, ys, labs, font = font()) alphabet = "abcdefghijklmnopqrstuvwxyz" push!(anns, (x, y, text(string("(", alphabet[sp[:subplot_index]], ")"), font))) else - push!(anns, (x, y, isa(lab, PlotText) ? lab : text(lab, font))) + push!(anns, (x, y, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab...) : text(lab, font))) end end anns @@ -569,7 +569,7 @@ function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol}, alphabet = "abcdefghijklmnopqrstuvwxyz" push!(anns, (pos, text(string("(", alphabet[sp[:subplot_index]], ")"), font))) else - push!(anns, (pos, isa(lab, PlotText) ? lab : text(lab, font))) + push!(anns, (pos, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab...) : text(lab, font))) end end anns From 9679eae662d86b37aca91e7fee7eda2c83968829 Mon Sep 17 00:00:00 2001 From: wfrgra Date: Sat, 5 Jan 2019 13:46:53 +1100 Subject: [PATCH 065/230] stop default widen behaviour overriding axis limit rounding --- src/axes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index 6f00a27a..1b2f693b 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -459,7 +459,7 @@ const _widen_seriestypes = (:line, :path, :steppre, :steppost, :sticks, :scatter function default_should_widen(axis::Axis) should_widen = false - if !is_2tuple(axis[:lims]) + if !(is_2tuple(axis[:lims]) || axis[:lims] == :round) for sp in axis.sps for series in series_list(sp) if series.plotattributes[:seriestype] in _widen_seriestypes From ba46299088ec4cff1d3df686804e89a9ed02500c Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 5 Jan 2019 17:57:21 +0100 Subject: [PATCH 066/230] Fix stray srand in showtheme --- src/Plots.jl | 2 +- src/themes.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 0a6522d6..48669c7d 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -5,7 +5,7 @@ _current_plots_version = v"0.20.6" using Reexport import StaticArrays -using Dates, Printf, Statistics, Base64, LinearAlgebra +using Dates, Printf, Statistics, Base64, LinearAlgebra, Random import SparseArrays: findnz @reexport using RecipesBase diff --git a/src/themes.jl b/src/themes.jl index da313498..592d0a78 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -100,7 +100,7 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func end end - srand(1) + Random.seed!(1) label := "" colorbar := false From 53e27dbc38a99fffa1dfa4d28ce478cbb2cc22dc Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Sun, 6 Jan 2019 11:24:45 +0100 Subject: [PATCH 067/230] Added support for discrete contour plots --- REQUIRE | 2 +- src/backends/gr.jl | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/REQUIRE b/REQUIRE index aae86c2c..6fad4eba 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.35.0 +GR 0.36.0 diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 505ad39f..1d4fbca6 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1029,16 +1029,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) else h = series[:levels] > 1 ? range(zmin, stop=zmax, length=series[:levels]) : [(zmin + zmax) / 2] end + GR.setlinetype(gr_linetype[get_linestyle(series)]) + GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) if series[:fillrange] != nothing - GR.surface(x, y, z, GR.OPTION_CELL_ARRAY) + GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0) else - GR.setlinetype(gr_linetype[get_linestyle(series)]) - GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) - if plot_color(series[:linecolor]) == [plot_color(:black)] - GR.contour(x, y, h, z, 0 + (series[:contour_labels] == true ? 1 : 0)) - else - GR.contour(x, y, h, z, 1000 + (series[:contour_labels] == true ? 1 : 0)) - end + coff = plot_color(series[:linecolor]) == [plot_color(:black)] ? 0 : 1000 + GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0)) end # create the colorbar of contour levels From 8951526d0d395f7bece2217d1d021b5fa9cdac57 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 7 Jan 2019 13:26:08 +0100 Subject: [PATCH 068/230] Set minimum GR version --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index 6fad4eba..a6b2ed11 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.36.0 +GR 0.37.0 From ffea050bc20573596a4bbeded52060db6478cb26 Mon Sep 17 00:00:00 2001 From: Spencer Lyon Date: Tue, 8 Jan 2019 14:04:03 -0500 Subject: [PATCH 069/230] ENH: don't special case html display for jupyter --- src/backends/plotlyjs.jl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 791016d7..575d076b 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -50,13 +50,6 @@ end # ---------------------------------------------------------------- -function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) - if isijulia() && !_use_remote[] - write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o))) - else - show(io, MIME("text/html"), plt.o) - end -end function plotlyjs_save_hack(io::IO, plt::Plot{PlotlyJSBackend}, ext::String) tmpfn = tempname() * "." * ext @@ -67,6 +60,7 @@ _show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = plotlyjs_save _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png") _show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf") _show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps") +_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o) function write_temp_html(plt::Plot{PlotlyJSBackend}) filename = string(tempname(), ".html") From 80a97b0f2693e0b7e9959859144e4121f364f4b7 Mon Sep 17 00:00:00 2001 From: Spencer Lyon Date: Tue, 8 Jan 2019 14:04:33 -0500 Subject: [PATCH 070/230] ENH: use PlotlyJS.savefig(::IO, ...) methods instead of former `plotlyjs_save_hack` hack --- src/backends/plotlyjs.jl | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 575d076b..08e40762 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -1,5 +1,4 @@ - -# https://github.com/spencerlyon2/PlotlyJS.jl +# https://github.com/sglyon/PlotlyJS.jl # -------------------------------------------------------------------------------------- @@ -50,17 +49,11 @@ end # ---------------------------------------------------------------- - -function plotlyjs_save_hack(io::IO, plt::Plot{PlotlyJSBackend}, ext::String) - tmpfn = tempname() * "." * ext - PlotlyJS.savefig(plt.o, tmpfn) - write(io, read(open(tmpfn))) -end -_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "svg") -_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png") -_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf") -_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps") _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o) +_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="svg") +_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="png") +_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf") +_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps") function write_temp_html(plt::Plot{PlotlyJSBackend}) filename = string(tempname(), ".html") From e6bb17dc865781c304392582862fdc475d9b276c Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Tue, 8 Jan 2019 17:55:52 -0500 Subject: [PATCH 071/230] document @shorthands functions --- src/Plots.jl | 92 +---------------------------------------------- src/arg_desc.jl | 48 ++++++++++++------------- src/components.jl | 20 ++++++++++- src/utils.jl | 37 +++++++++++++++++++ 4 files changed, 81 insertions(+), 116 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 48669c7d..fb93c45f 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -186,97 +186,7 @@ include("backends/plotly.jl") include("backends/gr.jl") include("backends/web.jl") -# --------------------------------------------------------- - -@shorthands scatter -@shorthands bar -@shorthands barh -@shorthands histogram -@shorthands barhist -@shorthands stephist -@shorthands scatterhist -@shorthands histogram2d -@shorthands density -@shorthands heatmap -@shorthands plots_heatmap -@shorthands hexbin -@shorthands sticks -@shorthands hline -@shorthands vline -@shorthands hspan -@shorthands vspan -@shorthands ohlc -@shorthands contour -@shorthands contourf -@shorthands contour3d -@shorthands surface -@shorthands wireframe -@shorthands path3d -@shorthands scatter3d -@shorthands boxplot -@shorthands violin -@shorthands quiver -@shorthands curves - -"Plot a pie diagram" -pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) -pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) - -"Plot with seriestype :path3d" -plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) -plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) - -"Add title to an existing plot" -title!(s::AbstractString; kw...) = plot!(; title = s, kw...) - -"Add xlabel to an existing plot" -xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...) - -"Add ylabel to an existing plot" -ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...) - -"Set xlims for an existing plot" -xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...) - -"Set ylims for an existing plot" -ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...) - -"Set zlims for an existing plot" -zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...) - -xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...) -ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...) -zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...) - - -"Set xticks for an existing plot" -xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...) - -"Set yticks for an existing plot" -yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...) - -xticks!( -ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...) -yticks!( -ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...) - -"Add annotations to an existing plot" -annotate!(anns...; kw...) = plot!(; annotation = anns, kw...) -annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...) - -"Flip the current plots' x axis" -xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...) - -"Flip the current plots' y axis" -yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...) - -"Specify x axis attributes for an existing plot" -xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) - -"Specify x axis attributes for an existing plot" -yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) -xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) -ygrid!(args...; kw...) = plot!(; ygrid = args, kw...) +include("shorthands.jl") let PlotOrSubplot = Union{Plot, Subplot} global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 64ce5b93..6fe8f068 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -2,7 +2,7 @@ const _arg_desc = KW( # series args -:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.", +:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.", :seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot", :seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.", :seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.", @@ -10,7 +10,7 @@ const _arg_desc = KW( :linewidth => "Number. Width of the line (in pixels)", :linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).", :linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.", -:fillrange => "Number or AbstractVector. Fills area from this to y for line-types, sets the base for bar/stick types, and similar for other types.", +:fillrange => "Number or AbstractVector. Fills area between fillrange and y for line-types, sets the base for bar/stick types, and similar for other types.", :fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.", :fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.", :markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).", @@ -21,7 +21,7 @@ const _arg_desc = KW( :markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.", -:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(min(x), stop = extrema(x), length = 25)`", +:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(minimum(x), stop = maximum(x), length = 25)`", :smooth => "Bool. Add a regression line?", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.", :x => "Various. Input data. First Dimension", @@ -29,13 +29,13 @@ const _arg_desc = KW( :z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.", :marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.", :line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).", -:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", -:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.", +:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", +:levels => "Integer, NTuple{2,Integer}, or AbstractVector. Levels or number of levels (or x-levels/y-levels) for a contour type.", :orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).", :bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)", -:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", -:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", -:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)", +:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", +:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", +:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)", :yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)", :ribbon => "Number or AbstractVector. Creates a fillrange around the data points.", :quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.", @@ -43,12 +43,12 @@ const _arg_desc = KW( :normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).", :weights => "AbstractVector. Used in histogram types for weighted counts.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.", -:contour_labels => "Bool. Show labels at the contour lines?", +:contour_labels => "Bool. Show labels at the contour lines?", :match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.", :subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.", -:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", -:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", -:hover => "nothing or vector of strings. Text to display when hovering over each data point.", +:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", +:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", +:hover => "nothing or vector of strings. Text to display when hovering over each data point.", # plot args :plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)", @@ -63,11 +63,11 @@ const _arg_desc = KW( :link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).", :overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).", :html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.", -:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", -:dpi => "Number. Dots Per Inch of output figures", +:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", +: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.", +: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.", :fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides", # subplot args @@ -98,7 +98,7 @@ const _arg_desc = KW( :legendfont => "Font. Font of legend items.", :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.", :projection => "Symbol or String. '3d' or 'polar'", -:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `apect_ratio` x-units.", +:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.", :margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.", :left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.", :top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.", @@ -110,14 +110,14 @@ const _arg_desc = KW( :camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots", # axis args -:guide => "String. Axis guide (label).", +:guide => "String. Axis guide (label).", :guide_position => "Symbol. Position of axis guides: :top, :bottom, :left or :right", -:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]", -:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", -:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", -:rotation => "Number. Degrees rotation of tick labels.", -:flip => "Bool. Should we flip (reverse) the axis?", -:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", +:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]", +:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", +:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", +:rotation => "Number. Degrees rotation of tick labels.", +:flip => "Bool. Should we flip (reverse) the axis?", +:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", :tickfontfamily => "String or Symbol. Font family of tick labels.", :tickfontsize => "Integer. Font pointsize of tick labels.", :tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center", diff --git a/src/components.jl b/src/components.jl index f1f27dc4..f338432c 100644 --- a/src/components.jl +++ b/src/components.jl @@ -256,7 +256,25 @@ mutable struct Font color::Colorant end -"Create a Font from a list of unordered features" +""" + font(args...) + +Create a Font from an unordered list of features. + +# Arguments + +- `family`: AbstractString. "serif" or "sans-serif" or "monospace" +- `pointsize`: Integer. Size of font in points +- `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right) +- `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom) +- `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type) +- `color`: Colorant or Symbol + +# Examples +```julia-repl +julia> text("sans-serif",8,:hcenter,45.0,:blue) +``` +""" function font(args...) # defaults diff --git a/src/utils.jl b/src/utils.jl index e0d26c81..a0bad5a8 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1199,3 +1199,40 @@ end function construct_categorical_data(x::AbstractArray, axis::Axis) map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x) end + +_fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(IOBuffer(),paragraph,0;kwargs...) + +function _fmt_paragraph(io::IOBuffer, + remaining_text::AbstractString, + column_count::Integer; + fillwidth=60, + leadingspaces=0) + + kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces) + + m = match(r"(.*?) (.*)",remaining_text) + if isa(m,Nothing) + if column_count + length(remaining_text) ≤ fillwidth + print(io,remaining_text) + String(take!(io)) + else + print(io,"\n"*" "^leadingspaces*remaining_text) + String(take!(io)) + end + else + if column_count + length(m[1]) ≤ fillwidth + print(io,"$(m[1]) ") + _fmt_paragraph(io,m[2],column_count + length(m[1]) + 1;kwargs...) + else + print(io,"\n"*" "^leadingspaces*"$(m[1]) ") + _fmt_paragraph(io,m[2],leadingspaces;kwargs...) + end + end +end + +function _document_argument(S::AbstractString) + _fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S)) +end + + + From 689e437baccdcfb40c4b91997be85eef74799d10 Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Tue, 8 Jan 2019 18:10:48 -0500 Subject: [PATCH 072/230] Add shorthands.jl --- src/shorthands.jl | 489 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 src/shorthands.jl diff --git a/src/shorthands.jl b/src/shorthands.jl new file mode 100644 index 00000000..dc4af52d --- /dev/null +++ b/src/shorthands.jl @@ -0,0 +1,489 @@ +xydoc = """ +- `x`: AbstractVector of x values. +- `y`: AbstractVector of y values. +""" + +xyzdoc = """ +- `x`: x-coordinates. Either a vector of length `size(z,1)` or a rectangular + array with the same dimensions as `z`. `1:size(z,1)` by default. +- `y`: y-coordinates. Either a vector of length `size(z,2)` or a rectangular + array with the same dimensions as `z`. `1:size(z,2)` by default. +- `z`: Rectangular array of height values for the contour lines, or a function to + apply to `x` and `y` to obtain such an array. +""" + +""" + scatter(x,y) + scatter!(x,y) + +Make a scatter plot of y vs x. + +# Arguments +$xydoc + +# Examples +```julia-repl +julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue]) +julia> scatter([(1,4),(2,5),(3,6)]) +``` +""" +@shorthands scatter + +""" + bar(x,y) + bar!(x,y) + +Make a bar plot of y vs x. + +# Arguments + +$xydoc +- $(_document_argument("bar_position")) +- $(_document_argument("bar_width")) +- $(_document_argument("bar_edges")) +- $(_document_argument("orientation")) + +# Examples +```julia-repl +julia> bar([1,2,3],[4,5,6],fillcolor=[:red,:green,:blue],fillalpha=[0.2,0.4,0.6]) +julia> bar([(1,4),(2,5),(3,6)]) +``` +""" +@shorthands bar + +@shorthands barh + +""" + histogram(x) + histogram!(x) + +Plot a histogram. + +# Arguments + +- `x`: AbstractVector of values to be binned +- $(_document_argument("bins")) +- `weights`: Vector of weights for the values in `x`, for weighted bin counts +- $(_document_argument("normalize")) +- $(_document_argument("bar_position")) +- $(_document_argument("bar_width")) +- $(_document_argument("bar_edges")) +- $(_document_argument("orientation")) + +# Example +```julia-repl +julia> histogram([1,2,1,1,4,3,8],bins=0:8) +``` +""" +@shorthands histogram + +""" + barhist(x) + barhist!(x) + +Make a histogram bar plot. See `histogram`. +""" +@shorthands barhist + +""" + stephist(x) + stephist(x) + +Make a histogram step plot (bin counts are represented using horizontal lines +instead of bars). See `histogram`. +""" +@shorthands stephist + +""" + scatterhist(x) + scatterhist!(x) + +Make a histogram scatter plot (bin counts are represented using points +instead of bars). See `histogram`. +""" +@shorthands scatterhist + +""" + histogram2d(x,y) + histogram2d!(x,y) + +Plot a two-dimensional histogram. + +# Arguments + +$xydoc +- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) +- `weights`: Vector of weights for the values in `x`. Each entry of x contributes + its weight to the height of its bin. + +# Example +```julia-repl +julia> histogram2d(randn(10_000),randn(10_000)) +``` +""" +@shorthands histogram2d + +""" + density(x) + density!(x) + +Make a line plot of a kernel density estimate of x + +# Arguments + +- `x`: AbstractVector of samples for probability density estimation + +# Example +```julia-repl +julia> using StatPlots +julia> density(randn(100_000)) +``` +""" +@shorthands density + +""" + heatmap(x,y,z) + heatmap!(x,y,z) + +Plot a heatmap of the rectangular array `z` + +# Arguments +$xyzdoc + + +# Example +```julia-repl +julia> heatmap(randn(10,10)) +``` +""" +@shorthands heatmap +@shorthands plots_heatmap + +""" + hexbin(x,y) + hexbin!(x,y) + +Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])` +with hexagonal bins) + +# Example +```julia-repl +julia> hexbin(randn(10_000), randn(10_000)) +``` +""" +@shorthands hexbin + +""" + sticks(x,y) + sticks!(x,y) + +Draw a stick plot of y vs x. + +# Arguments +$xydoc + +# Example +```julia-repl +julia> sticks(1:10) +``` +""" +@shorthands sticks + +""" + hline(y) + hline!(y) + +Draw horizontal lines at positions specified by the values in +the AbstractVector `y` + +# Example +```julia-repl +julia> hline([-1,0,2]) +``` +""" +@shorthands hline + +""" + vline(x) + vline!(x) + +Draw vertical lines at positions specified by the values in +the AbstractVector `x` + +# Example +```julia-repl +julia> vline([-1,0,2]) +``` +""" +@shorthands vline + +""" + hspan(y) + +Draw a rectangle between the horizontal line at position `y[1]` +and the horizontal line at position `y[2]`. If `length(y) ≥ 4`, +then further rectangles are drawn between `y[3]` and `y[4]`, +`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the +last entry of `y` is ignored. +# Example +```julia-repl +julia> hspan(1:6) +``` +""" +@shorthands hspan + +""" + vspan(x) + +Draw a rectangle between the vertical line at position `x[1]` +and the vertical line at position `x[2]`. If `length(x) ≥ 4`, +then further rectangles are drawn between `x[3]` and `x[4]`, +`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the +last entry of `x` is ignored. +# Example +```julia-repl +julia> vspan(1:6) +``` +""" +@shorthands vspan + +""" + ohlc(x,y::Vector{OHLC}) + ohlc!(x,y::Vector{OHLC}) + +Make open-high-low-close plot. Each entry of y is represented by a vertical +segment extending from the low value to the high value, with short horizontal +segments on the left and right indicating the open and close values, respectively. + +# Example +```julia-repl +julia> meanprices = cumsum(randn(100)) +julia> y = OHLC[(p+rand(),p+1,p-1,p+rand()) for p in meanprices] +julia> ohlc(y) +``` +""" +@shorthands ohlc + + +""" + contour(x,y,z) + contour!(x,y,z) + +Draw contour lines of the `Surface` z. + +# Arguments +$xyzdoc +- `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`) +- `fill`: Bool. Fill area between contours or draw contours only (false by default) + +# Example +```julia-repl +julia> contour(-20:20,-20:20,(x,y)->x^2+y^2) +``` +""" +@shorthands contour + +"An alias for `contour` with fill = true." +@shorthands contourf + + +@shorthands contour3d + +""" + surface(x,y,z) + surface!(x,y,z) + +Draw a 3D surface plot. + +# Arguments +$xyzdoc + +# Example +```julia-repl +julia> surface(1:10,1:10,randn(10,10)) +``` +""" +@shorthands surface + +""" + wireframe(x,y,z) + wireframe!(x,y,z) + +Draw a 3D wireframe plot. + +# Arguments +$xyzdoc + +# Example +```julia-repl +julia> wireframe(1:10,1:10,randn(10,10)) +``` +""" +@shorthands wireframe + +""" + path3d(x,y,z) + path3d!(x,y,z) + +Plot a 3D path from `(x[1],y[1],z[1])` to `(x[2],y[2],z[2])`, +..., to `(x[end],y[end],z[end])`. + +# Example +```julia-repl +julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) +``` +""" +@shorthands path3d + +""" + scatter3d(x,y,z) + scatter3d!(x,y,z) + +Make a 3D scatter plot. + +# Example +```julia-repl +julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) +``` +""" +@shorthands scatter3d + +""" + boxplot(x, y) + boxplot!(x, y) + +Make a box and whisker plot. + +# Arguments +$xydoc + +# Keyword arguments +- `notch`: Bool. Notch the box plot? (false) +- `range`: Real. Values more than range*IQR below the first quartile + or above the third quartile are shown as outliers (1.5) +- `outliers`: Bool. Show outliers? (true) +- `whisker_width`: Real or Symbol. Length of whiskers (:match) + +# Example +```julia-repl +julia> using StatPlots +julia> boxplot(repeat([1,2,3],outer=100),randn(300)) +``` +""" +@shorthands boxplot + +""" + violin(x,y,z) + violin!(x,y,z) + +Make a violin plot. + +# Example +```julia-repl +julia> violin(repeat([1,2,3],outer=100),randn(300)) +``` +""" +@shorthands violin + +""" + quiver(x,y,quiver=(u,v)) + quiver!(x,y,quiver=(u,v)) + +Make a quiver (vector field) plot. The `i`th vector extends +from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`. + +# Example +```julia-repl +julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3])) +``` +""" +@shorthands quiver + +""" + curves(x,y) + curves!(x,y) + +Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])` +with control points `(x[2],y[2]), ..., (x[end-1],y[end]-1)` + +# Example +```julia-repl +julia> curves([1,2,3,4],[1,1,2,4]) +``` +""" +@shorthands curves + +"Plot a pie diagram" +pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) +pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) + +"Plot with seriestype :path3d" +plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) +plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) + +"Add title to an existing plot" +title!(s::AbstractString; kw...) = plot!(; title = s, kw...) + +"Add xlabel to an existing plot" +xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...) + +"Add ylabel to an existing plot" +ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...) + +"Set xlims for an existing plot" +xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...) + +"Set ylims for an existing plot" +ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...) + +"Set zlims for an existing plot" +zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...) + +xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...) +ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...) +zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...) + + +"Set xticks for an existing plot" +xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...) + +"Set yticks for an existing plot" +yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...) + +xticks!( +ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...) +yticks!( +ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...) + +""" + annotate!(anns...) + +Add annotations to an existing plot. + +# Arguments + +- `anns`: An `AbstractVector` of tuples of the form (x,y,text). The text object + can be an String or PlotText + +# Example +```julia-repl +julia> plot(1:10) +julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))]) +``` +""" +annotate!(anns...; kw...) = plot!(; annotation = anns, kw...) +annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...) + +"Flip the current plots' x axis" +xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...) + +"Flip the current plots' y axis" +yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...) + +"Specify x axis attributes for an existing plot" +xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) + +"Specify x axis attributes for an existing plot" +yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) +xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) +ygrid!(args...; kw...) = plot!(; ygrid = args, kw...) From b20b47f8eb2ccf8d861adbea69cafaa94cd6d49d Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 10 Jan 2019 08:44:41 -0500 Subject: [PATCH 073/230] remove rand from example Co-Authored-By: sswatson --- src/shorthands.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index dc4af52d..7b216696 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -300,7 +300,8 @@ $xyzdoc # Example ```julia-repl -julia> surface(1:10,1:10,randn(10,10)) +julia> x = y = range(-3, 3, length = 100) +julia> surface(x, y, (x, y) -> sinc(norm([x, y]))) ``` """ @shorthands surface From e673339dc4aab78bf67cb22dfe408237d1b60a23 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 10 Jan 2019 08:46:38 -0500 Subject: [PATCH 074/230] change contour example Co-Authored-By: sswatson --- src/shorthands.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index 7b216696..cb244bcd 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -278,7 +278,8 @@ $xyzdoc # Example ```julia-repl -julia> contour(-20:20,-20:20,(x,y)->x^2+y^2) +julia> x = y = range(-20, 20, length = 100) +julia> contour(x, y, (x, y) -> x^2 + y^2) ``` """ @shorthands contour From d29a44efa734b3a54e6b4c2c444598d53bd222de Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 13 Jan 2019 12:44:59 +0100 Subject: [PATCH 075/230] fix histograms with NaN --- src/recipes.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 5ae3cebf..f86bad70 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -590,7 +590,7 @@ wand_edges(x...) = (@warn("Load the StatPlots package in order to use :wand bins function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N _cl(x) = ceil(Int, NaNMath.max(x, one(x))) - _iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1)) + _iqr(v) = (q = quantile(filter(!isnan,v), 0.75) - quantile(filter(!isnan,v), 0.25); q > 0 ? q : oftype(q, 1)) _span(v) = ignorenan_maximum(v) - ignorenan_minimum(v) n_samples = length(LinearIndices(first(vs))) @@ -622,7 +622,7 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S end end -_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(vs[dim], binning, :left) +_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(filter(!isnan,vs[dim]), binning, :left) _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} = binning @@ -635,11 +635,17 @@ _hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abstra _hist_norm_mode(mode::Symbol) = mode _hist_norm_mode(mode::Bool) = mode ? :pdf : :none +function _filternans(vs::NTuple{N,AbstractVector}) where N + _invertedindex(v, not) = [j for (i,j) in enumerate(v) if !(i ∈ not)] + nots = union(Set.(findall.(isnan, vs))...) + _invertedindex.(vs, Ref(nots)) +end + function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N edges = _hist_edges(vs, binning) h = float( weights == nothing ? - StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) : - StatsBase.fit(StatsBase.Histogram, vs, StatsBase.Weights(weights), edges, closed = :left) + StatsBase.fit(StatsBase.Histogram, _filternans(vs), edges, closed = :left) : + StatsBase.fit(StatsBase.Histogram, _filternans(vs), StatsBase.Weights(weights), edges, closed = :left) ) normalize!(h, mode = _hist_norm_mode(normed)) end From 979f9495f104c524b79f6cee1efeead165c8d704 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 13 Jan 2019 14:17:54 +0100 Subject: [PATCH 076/230] add faster method for 1-d histogram --- src/recipes.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/recipes.jl b/src/recipes.jl index f86bad70..0b729b3d 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -635,6 +635,7 @@ _hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abstra _hist_norm_mode(mode::Symbol) = mode _hist_norm_mode(mode::Bool) = mode ? :pdf : :none +_filternans(vs::NTuple{1,AbstractVector}) = filter!.(!isnan, vs) function _filternans(vs::NTuple{N,AbstractVector}) where N _invertedindex(v, not) = [j for (i,j) in enumerate(v) if !(i ∈ not)] nots = union(Set.(findall.(isnan, vs))...) From 667ed161c0d1710fdc1c287254f17590ab0e106e Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 14 Jan 2019 10:21:35 +0100 Subject: [PATCH 077/230] move filtering to makebins --- src/recipes.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 0b729b3d..0bef95c7 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -589,9 +589,9 @@ Plots.@deps stepbins path wand_edges(x...) = (@warn("Load the StatPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto) function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N - _cl(x) = ceil(Int, NaNMath.max(x, one(x))) - _iqr(v) = (q = quantile(filter(!isnan,v), 0.75) - quantile(filter(!isnan,v), 0.25); q > 0 ? q : oftype(q, 1)) - _span(v) = ignorenan_maximum(v) - ignorenan_minimum(v) + _cl(x) = ceil(Int, max(x, one(x))) + _iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1)) + _span(v) = maximum(v) - minimum(v) n_samples = length(LinearIndices(first(vs))) @@ -622,7 +622,7 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S end end -_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(filter(!isnan,vs[dim]), binning, :left) +_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(vs[dim], binning, :left) _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} = binning @@ -643,10 +643,11 @@ function _filternans(vs::NTuple{N,AbstractVector}) where N end function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N + vs = _filternans(vs) edges = _hist_edges(vs, binning) h = float( weights == nothing ? - StatsBase.fit(StatsBase.Histogram, _filternans(vs), edges, closed = :left) : - StatsBase.fit(StatsBase.Histogram, _filternans(vs), StatsBase.Weights(weights), edges, closed = :left) + StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) : + StatsBase.fit(StatsBase.Histogram, vs, StatsBase.Weights(weights), edges, closed = :left) ) normalize!(h, mode = _hist_norm_mode(normed)) end From 3d77c59c92209902e30e81538c34cbc1df6d8cbf Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 14 Jan 2019 11:44:42 +0100 Subject: [PATCH 078/230] don't rebind vs --- src/recipes.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 0bef95c7..d0e9e7e6 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -643,11 +643,11 @@ function _filternans(vs::NTuple{N,AbstractVector}) where N end function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N - vs = _filternans(vs) - edges = _hist_edges(vs, binning) + localvs = _filternans(vs) + edges = _hist_edges(localvs, binning) h = float( weights == nothing ? - StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) : - StatsBase.fit(StatsBase.Histogram, vs, StatsBase.Weights(weights), edges, closed = :left) + StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) : + StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left) ) normalize!(h, mode = _hist_norm_mode(normed)) end From cfe6103f481f830a66550aa95bab267131748934 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 14 Jan 2019 23:08:50 +0100 Subject: [PATCH 079/230] filter infinite values in histograms too --- src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index d0e9e7e6..63a069c9 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -635,10 +635,10 @@ _hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abstra _hist_norm_mode(mode::Symbol) = mode _hist_norm_mode(mode::Bool) = mode ? :pdf : :none -_filternans(vs::NTuple{1,AbstractVector}) = filter!.(!isnan, vs) +_filternans(vs::NTuple{1,AbstractVector}) = filter!.(isfinite, vs) function _filternans(vs::NTuple{N,AbstractVector}) where N _invertedindex(v, not) = [j for (i,j) in enumerate(v) if !(i ∈ not)] - nots = union(Set.(findall.(isnan, vs))...) + nots = union(Set.(findall.(!isfinite, vs))...) _invertedindex.(vs, Ref(nots)) end From b060576209e5cbc8c3d8eff5a2efb3e8dafc85d5 Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 08:40:25 -0500 Subject: [PATCH 080/230] Remove xydoc and xyzdoc --- src/shorthands.jl | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index dc4af52d..86e913eb 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -1,26 +1,9 @@ -xydoc = """ -- `x`: AbstractVector of x values. -- `y`: AbstractVector of y values. -""" - -xyzdoc = """ -- `x`: x-coordinates. Either a vector of length `size(z,1)` or a rectangular - array with the same dimensions as `z`. `1:size(z,1)` by default. -- `y`: y-coordinates. Either a vector of length `size(z,2)` or a rectangular - array with the same dimensions as `z`. `1:size(z,2)` by default. -- `z`: Rectangular array of height values for the contour lines, or a function to - apply to `x` and `y` to obtain such an array. -""" - """ scatter(x,y) scatter!(x,y) Make a scatter plot of y vs x. -# Arguments -$xydoc - # Examples ```julia-repl julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue]) @@ -37,7 +20,6 @@ Make a bar plot of y vs x. # Arguments -$xydoc - $(_document_argument("bar_position")) - $(_document_argument("bar_width")) - $(_document_argument("bar_edges")) @@ -111,7 +93,6 @@ Plot a two-dimensional histogram. # Arguments -$xydoc - `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) - `weights`: Vector of weights for the values in `x`. Each entry of x contributes its weight to the height of its bin. @@ -127,7 +108,7 @@ julia> histogram2d(randn(10_000),randn(10_000)) density(x) density!(x) -Make a line plot of a kernel density estimate of x +Make a line plot of a kernel density estimate of x. # Arguments @@ -145,11 +126,7 @@ julia> density(randn(100_000)) heatmap(x,y,z) heatmap!(x,y,z) -Plot a heatmap of the rectangular array `z` - -# Arguments -$xyzdoc - +Plot a heatmap of the rectangular array `z`. # Example ```julia-repl @@ -179,9 +156,6 @@ julia> hexbin(randn(10_000), randn(10_000)) Draw a stick plot of y vs x. -# Arguments -$xydoc - # Example ```julia-repl julia> sticks(1:10) @@ -272,7 +246,6 @@ julia> ohlc(y) Draw contour lines of the `Surface` z. # Arguments -$xyzdoc - `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`) - `fill`: Bool. Fill area between contours or draw contours only (false by default) @@ -295,9 +268,6 @@ julia> contour(-20:20,-20:20,(x,y)->x^2+y^2) Draw a 3D surface plot. -# Arguments -$xyzdoc - # Example ```julia-repl julia> surface(1:10,1:10,randn(10,10)) @@ -311,9 +281,6 @@ julia> surface(1:10,1:10,randn(10,10)) Draw a 3D wireframe plot. -# Arguments -$xyzdoc - # Example ```julia-repl julia> wireframe(1:10,1:10,randn(10,10)) @@ -354,9 +321,6 @@ julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) Make a box and whisker plot. -# Arguments -$xydoc - # Keyword arguments - `notch`: Bool. Notch the box plot? (false) - `range`: Real. Values more than range*IQR below the first quartile From b7caec1bfe9a4b929719e8c3ecae3441791963f7 Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 08:43:43 -0500 Subject: [PATCH 081/230] Remove blank lines --- src/utils.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index a0bad5a8..7f582e81 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1233,6 +1233,3 @@ end function _document_argument(S::AbstractString) _fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S)) end - - - From e30889aa122b28610b26df2a483ffe69589ef5fe Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Tue, 8 Jan 2019 17:55:52 -0500 Subject: [PATCH 082/230] document @shorthands functions --- src/Plots.jl | 92 +---------------------------------------------- src/arg_desc.jl | 48 ++++++++++++------------- src/components.jl | 20 ++++++++++- src/utils.jl | 37 +++++++++++++++++++ 4 files changed, 81 insertions(+), 116 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 48669c7d..fb93c45f 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -186,97 +186,7 @@ include("backends/plotly.jl") include("backends/gr.jl") include("backends/web.jl") -# --------------------------------------------------------- - -@shorthands scatter -@shorthands bar -@shorthands barh -@shorthands histogram -@shorthands barhist -@shorthands stephist -@shorthands scatterhist -@shorthands histogram2d -@shorthands density -@shorthands heatmap -@shorthands plots_heatmap -@shorthands hexbin -@shorthands sticks -@shorthands hline -@shorthands vline -@shorthands hspan -@shorthands vspan -@shorthands ohlc -@shorthands contour -@shorthands contourf -@shorthands contour3d -@shorthands surface -@shorthands wireframe -@shorthands path3d -@shorthands scatter3d -@shorthands boxplot -@shorthands violin -@shorthands quiver -@shorthands curves - -"Plot a pie diagram" -pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) -pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) - -"Plot with seriestype :path3d" -plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) -plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) - -"Add title to an existing plot" -title!(s::AbstractString; kw...) = plot!(; title = s, kw...) - -"Add xlabel to an existing plot" -xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...) - -"Add ylabel to an existing plot" -ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...) - -"Set xlims for an existing plot" -xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...) - -"Set ylims for an existing plot" -ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...) - -"Set zlims for an existing plot" -zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...) - -xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...) -ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...) -zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...) - - -"Set xticks for an existing plot" -xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...) - -"Set yticks for an existing plot" -yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...) - -xticks!( -ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...) -yticks!( -ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...) - -"Add annotations to an existing plot" -annotate!(anns...; kw...) = plot!(; annotation = anns, kw...) -annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...) - -"Flip the current plots' x axis" -xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...) - -"Flip the current plots' y axis" -yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...) - -"Specify x axis attributes for an existing plot" -xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) - -"Specify x axis attributes for an existing plot" -yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) -xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) -ygrid!(args...; kw...) = plot!(; ygrid = args, kw...) +include("shorthands.jl") let PlotOrSubplot = Union{Plot, Subplot} global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 64ce5b93..6fe8f068 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -2,7 +2,7 @@ const _arg_desc = KW( # series args -:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.", +:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.", :seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot", :seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.", :seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.", @@ -10,7 +10,7 @@ const _arg_desc = KW( :linewidth => "Number. Width of the line (in pixels)", :linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).", :linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.", -:fillrange => "Number or AbstractVector. Fills area from this to y for line-types, sets the base for bar/stick types, and similar for other types.", +:fillrange => "Number or AbstractVector. Fills area between fillrange and y for line-types, sets the base for bar/stick types, and similar for other types.", :fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.", :fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.", :markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).", @@ -21,7 +21,7 @@ const _arg_desc = KW( :markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.", -:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(min(x), stop = extrema(x), length = 25)`", +:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(minimum(x), stop = maximum(x), length = 25)`", :smooth => "Bool. Add a regression line?", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.", :x => "Various. Input data. First Dimension", @@ -29,13 +29,13 @@ const _arg_desc = KW( :z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.", :marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.", :line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).", -:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", -:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.", +:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", +:levels => "Integer, NTuple{2,Integer}, or AbstractVector. Levels or number of levels (or x-levels/y-levels) for a contour type.", :orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).", :bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)", -:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", -:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", -:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)", +:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", +:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", +:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)", :yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)", :ribbon => "Number or AbstractVector. Creates a fillrange around the data points.", :quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.", @@ -43,12 +43,12 @@ const _arg_desc = KW( :normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).", :weights => "AbstractVector. Used in histogram types for weighted counts.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.", -:contour_labels => "Bool. Show labels at the contour lines?", +:contour_labels => "Bool. Show labels at the contour lines?", :match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.", :subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.", -:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", -:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", -:hover => "nothing or vector of strings. Text to display when hovering over each data point.", +:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", +:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", +:hover => "nothing or vector of strings. Text to display when hovering over each data point.", # plot args :plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)", @@ -63,11 +63,11 @@ const _arg_desc = KW( :link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).", :overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).", :html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.", -:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", -:dpi => "Number. Dots Per Inch of output figures", +:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", +: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.", +: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.", :fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides", # subplot args @@ -98,7 +98,7 @@ const _arg_desc = KW( :legendfont => "Font. Font of legend items.", :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.", :projection => "Symbol or String. '3d' or 'polar'", -:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `apect_ratio` x-units.", +:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.", :margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.", :left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.", :top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.", @@ -110,14 +110,14 @@ const _arg_desc = KW( :camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots", # axis args -:guide => "String. Axis guide (label).", +:guide => "String. Axis guide (label).", :guide_position => "Symbol. Position of axis guides: :top, :bottom, :left or :right", -:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]", -:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", -:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", -:rotation => "Number. Degrees rotation of tick labels.", -:flip => "Bool. Should we flip (reverse) the axis?", -:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", +:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]", +:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", +:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", +:rotation => "Number. Degrees rotation of tick labels.", +:flip => "Bool. Should we flip (reverse) the axis?", +:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", :tickfontfamily => "String or Symbol. Font family of tick labels.", :tickfontsize => "Integer. Font pointsize of tick labels.", :tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center", diff --git a/src/components.jl b/src/components.jl index f1f27dc4..f338432c 100644 --- a/src/components.jl +++ b/src/components.jl @@ -256,7 +256,25 @@ mutable struct Font color::Colorant end -"Create a Font from a list of unordered features" +""" + font(args...) + +Create a Font from an unordered list of features. + +# Arguments + +- `family`: AbstractString. "serif" or "sans-serif" or "monospace" +- `pointsize`: Integer. Size of font in points +- `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right) +- `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom) +- `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type) +- `color`: Colorant or Symbol + +# Examples +```julia-repl +julia> text("sans-serif",8,:hcenter,45.0,:blue) +``` +""" function font(args...) # defaults diff --git a/src/utils.jl b/src/utils.jl index e0d26c81..a0bad5a8 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1199,3 +1199,40 @@ end function construct_categorical_data(x::AbstractArray, axis::Axis) map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x) end + +_fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(IOBuffer(),paragraph,0;kwargs...) + +function _fmt_paragraph(io::IOBuffer, + remaining_text::AbstractString, + column_count::Integer; + fillwidth=60, + leadingspaces=0) + + kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces) + + m = match(r"(.*?) (.*)",remaining_text) + if isa(m,Nothing) + if column_count + length(remaining_text) ≤ fillwidth + print(io,remaining_text) + String(take!(io)) + else + print(io,"\n"*" "^leadingspaces*remaining_text) + String(take!(io)) + end + else + if column_count + length(m[1]) ≤ fillwidth + print(io,"$(m[1]) ") + _fmt_paragraph(io,m[2],column_count + length(m[1]) + 1;kwargs...) + else + print(io,"\n"*" "^leadingspaces*"$(m[1]) ") + _fmt_paragraph(io,m[2],leadingspaces;kwargs...) + end + end +end + +function _document_argument(S::AbstractString) + _fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S)) +end + + + From 63cdf9f8e71fb831d953232990e7d96e9fb94d1d Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Tue, 8 Jan 2019 18:10:48 -0500 Subject: [PATCH 083/230] Add shorthands.jl --- src/shorthands.jl | 489 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 src/shorthands.jl diff --git a/src/shorthands.jl b/src/shorthands.jl new file mode 100644 index 00000000..dc4af52d --- /dev/null +++ b/src/shorthands.jl @@ -0,0 +1,489 @@ +xydoc = """ +- `x`: AbstractVector of x values. +- `y`: AbstractVector of y values. +""" + +xyzdoc = """ +- `x`: x-coordinates. Either a vector of length `size(z,1)` or a rectangular + array with the same dimensions as `z`. `1:size(z,1)` by default. +- `y`: y-coordinates. Either a vector of length `size(z,2)` or a rectangular + array with the same dimensions as `z`. `1:size(z,2)` by default. +- `z`: Rectangular array of height values for the contour lines, or a function to + apply to `x` and `y` to obtain such an array. +""" + +""" + scatter(x,y) + scatter!(x,y) + +Make a scatter plot of y vs x. + +# Arguments +$xydoc + +# Examples +```julia-repl +julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue]) +julia> scatter([(1,4),(2,5),(3,6)]) +``` +""" +@shorthands scatter + +""" + bar(x,y) + bar!(x,y) + +Make a bar plot of y vs x. + +# Arguments + +$xydoc +- $(_document_argument("bar_position")) +- $(_document_argument("bar_width")) +- $(_document_argument("bar_edges")) +- $(_document_argument("orientation")) + +# Examples +```julia-repl +julia> bar([1,2,3],[4,5,6],fillcolor=[:red,:green,:blue],fillalpha=[0.2,0.4,0.6]) +julia> bar([(1,4),(2,5),(3,6)]) +``` +""" +@shorthands bar + +@shorthands barh + +""" + histogram(x) + histogram!(x) + +Plot a histogram. + +# Arguments + +- `x`: AbstractVector of values to be binned +- $(_document_argument("bins")) +- `weights`: Vector of weights for the values in `x`, for weighted bin counts +- $(_document_argument("normalize")) +- $(_document_argument("bar_position")) +- $(_document_argument("bar_width")) +- $(_document_argument("bar_edges")) +- $(_document_argument("orientation")) + +# Example +```julia-repl +julia> histogram([1,2,1,1,4,3,8],bins=0:8) +``` +""" +@shorthands histogram + +""" + barhist(x) + barhist!(x) + +Make a histogram bar plot. See `histogram`. +""" +@shorthands barhist + +""" + stephist(x) + stephist(x) + +Make a histogram step plot (bin counts are represented using horizontal lines +instead of bars). See `histogram`. +""" +@shorthands stephist + +""" + scatterhist(x) + scatterhist!(x) + +Make a histogram scatter plot (bin counts are represented using points +instead of bars). See `histogram`. +""" +@shorthands scatterhist + +""" + histogram2d(x,y) + histogram2d!(x,y) + +Plot a two-dimensional histogram. + +# Arguments + +$xydoc +- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) +- `weights`: Vector of weights for the values in `x`. Each entry of x contributes + its weight to the height of its bin. + +# Example +```julia-repl +julia> histogram2d(randn(10_000),randn(10_000)) +``` +""" +@shorthands histogram2d + +""" + density(x) + density!(x) + +Make a line plot of a kernel density estimate of x + +# Arguments + +- `x`: AbstractVector of samples for probability density estimation + +# Example +```julia-repl +julia> using StatPlots +julia> density(randn(100_000)) +``` +""" +@shorthands density + +""" + heatmap(x,y,z) + heatmap!(x,y,z) + +Plot a heatmap of the rectangular array `z` + +# Arguments +$xyzdoc + + +# Example +```julia-repl +julia> heatmap(randn(10,10)) +``` +""" +@shorthands heatmap +@shorthands plots_heatmap + +""" + hexbin(x,y) + hexbin!(x,y) + +Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])` +with hexagonal bins) + +# Example +```julia-repl +julia> hexbin(randn(10_000), randn(10_000)) +``` +""" +@shorthands hexbin + +""" + sticks(x,y) + sticks!(x,y) + +Draw a stick plot of y vs x. + +# Arguments +$xydoc + +# Example +```julia-repl +julia> sticks(1:10) +``` +""" +@shorthands sticks + +""" + hline(y) + hline!(y) + +Draw horizontal lines at positions specified by the values in +the AbstractVector `y` + +# Example +```julia-repl +julia> hline([-1,0,2]) +``` +""" +@shorthands hline + +""" + vline(x) + vline!(x) + +Draw vertical lines at positions specified by the values in +the AbstractVector `x` + +# Example +```julia-repl +julia> vline([-1,0,2]) +``` +""" +@shorthands vline + +""" + hspan(y) + +Draw a rectangle between the horizontal line at position `y[1]` +and the horizontal line at position `y[2]`. If `length(y) ≥ 4`, +then further rectangles are drawn between `y[3]` and `y[4]`, +`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the +last entry of `y` is ignored. +# Example +```julia-repl +julia> hspan(1:6) +``` +""" +@shorthands hspan + +""" + vspan(x) + +Draw a rectangle between the vertical line at position `x[1]` +and the vertical line at position `x[2]`. If `length(x) ≥ 4`, +then further rectangles are drawn between `x[3]` and `x[4]`, +`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the +last entry of `x` is ignored. +# Example +```julia-repl +julia> vspan(1:6) +``` +""" +@shorthands vspan + +""" + ohlc(x,y::Vector{OHLC}) + ohlc!(x,y::Vector{OHLC}) + +Make open-high-low-close plot. Each entry of y is represented by a vertical +segment extending from the low value to the high value, with short horizontal +segments on the left and right indicating the open and close values, respectively. + +# Example +```julia-repl +julia> meanprices = cumsum(randn(100)) +julia> y = OHLC[(p+rand(),p+1,p-1,p+rand()) for p in meanprices] +julia> ohlc(y) +``` +""" +@shorthands ohlc + + +""" + contour(x,y,z) + contour!(x,y,z) + +Draw contour lines of the `Surface` z. + +# Arguments +$xyzdoc +- `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`) +- `fill`: Bool. Fill area between contours or draw contours only (false by default) + +# Example +```julia-repl +julia> contour(-20:20,-20:20,(x,y)->x^2+y^2) +``` +""" +@shorthands contour + +"An alias for `contour` with fill = true." +@shorthands contourf + + +@shorthands contour3d + +""" + surface(x,y,z) + surface!(x,y,z) + +Draw a 3D surface plot. + +# Arguments +$xyzdoc + +# Example +```julia-repl +julia> surface(1:10,1:10,randn(10,10)) +``` +""" +@shorthands surface + +""" + wireframe(x,y,z) + wireframe!(x,y,z) + +Draw a 3D wireframe plot. + +# Arguments +$xyzdoc + +# Example +```julia-repl +julia> wireframe(1:10,1:10,randn(10,10)) +``` +""" +@shorthands wireframe + +""" + path3d(x,y,z) + path3d!(x,y,z) + +Plot a 3D path from `(x[1],y[1],z[1])` to `(x[2],y[2],z[2])`, +..., to `(x[end],y[end],z[end])`. + +# Example +```julia-repl +julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) +``` +""" +@shorthands path3d + +""" + scatter3d(x,y,z) + scatter3d!(x,y,z) + +Make a 3D scatter plot. + +# Example +```julia-repl +julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) +``` +""" +@shorthands scatter3d + +""" + boxplot(x, y) + boxplot!(x, y) + +Make a box and whisker plot. + +# Arguments +$xydoc + +# Keyword arguments +- `notch`: Bool. Notch the box plot? (false) +- `range`: Real. Values more than range*IQR below the first quartile + or above the third quartile are shown as outliers (1.5) +- `outliers`: Bool. Show outliers? (true) +- `whisker_width`: Real or Symbol. Length of whiskers (:match) + +# Example +```julia-repl +julia> using StatPlots +julia> boxplot(repeat([1,2,3],outer=100),randn(300)) +``` +""" +@shorthands boxplot + +""" + violin(x,y,z) + violin!(x,y,z) + +Make a violin plot. + +# Example +```julia-repl +julia> violin(repeat([1,2,3],outer=100),randn(300)) +``` +""" +@shorthands violin + +""" + quiver(x,y,quiver=(u,v)) + quiver!(x,y,quiver=(u,v)) + +Make a quiver (vector field) plot. The `i`th vector extends +from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`. + +# Example +```julia-repl +julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3])) +``` +""" +@shorthands quiver + +""" + curves(x,y) + curves!(x,y) + +Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])` +with control points `(x[2],y[2]), ..., (x[end-1],y[end]-1)` + +# Example +```julia-repl +julia> curves([1,2,3,4],[1,1,2,4]) +``` +""" +@shorthands curves + +"Plot a pie diagram" +pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) +pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) + +"Plot with seriestype :path3d" +plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) +plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) + +"Add title to an existing plot" +title!(s::AbstractString; kw...) = plot!(; title = s, kw...) + +"Add xlabel to an existing plot" +xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...) + +"Add ylabel to an existing plot" +ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...) + +"Set xlims for an existing plot" +xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...) + +"Set ylims for an existing plot" +ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...) + +"Set zlims for an existing plot" +zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...) + +xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...) +ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...) +zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...) + + +"Set xticks for an existing plot" +xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...) + +"Set yticks for an existing plot" +yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...) + +xticks!( +ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...) +yticks!( +ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...) + +""" + annotate!(anns...) + +Add annotations to an existing plot. + +# Arguments + +- `anns`: An `AbstractVector` of tuples of the form (x,y,text). The text object + can be an String or PlotText + +# Example +```julia-repl +julia> plot(1:10) +julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))]) +``` +""" +annotate!(anns...; kw...) = plot!(; annotation = anns, kw...) +annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...) + +"Flip the current plots' x axis" +xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...) + +"Flip the current plots' y axis" +yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...) + +"Specify x axis attributes for an existing plot" +xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) + +"Specify x axis attributes for an existing plot" +yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) +xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) +ygrid!(args...; kw...) = plot!(; ygrid = args, kw...) From dd28159564e788bd171905646acb35ab975e160c Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 10 Jan 2019 08:44:41 -0500 Subject: [PATCH 084/230] remove rand from example Co-Authored-By: sswatson --- src/shorthands.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index dc4af52d..7b216696 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -300,7 +300,8 @@ $xyzdoc # Example ```julia-repl -julia> surface(1:10,1:10,randn(10,10)) +julia> x = y = range(-3, 3, length = 100) +julia> surface(x, y, (x, y) -> sinc(norm([x, y]))) ``` """ @shorthands surface From 3765d5f549e0d694c798df166449479cc9400543 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 10 Jan 2019 08:46:38 -0500 Subject: [PATCH 085/230] change contour example Co-Authored-By: sswatson --- src/shorthands.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index 7b216696..cb244bcd 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -278,7 +278,8 @@ $xyzdoc # Example ```julia-repl -julia> contour(-20:20,-20:20,(x,y)->x^2+y^2) +julia> x = y = range(-20, 20, length = 100) +julia> contour(x, y, (x, y) -> x^2 + y^2) ``` """ @shorthands contour From 017bed1a07b98ede2afc97164fd25e382972f3ed Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 08:40:25 -0500 Subject: [PATCH 086/230] Remove xydoc and xyzdoc --- src/shorthands.jl | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index cb244bcd..7c5d7003 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -1,26 +1,9 @@ -xydoc = """ -- `x`: AbstractVector of x values. -- `y`: AbstractVector of y values. -""" - -xyzdoc = """ -- `x`: x-coordinates. Either a vector of length `size(z,1)` or a rectangular - array with the same dimensions as `z`. `1:size(z,1)` by default. -- `y`: y-coordinates. Either a vector of length `size(z,2)` or a rectangular - array with the same dimensions as `z`. `1:size(z,2)` by default. -- `z`: Rectangular array of height values for the contour lines, or a function to - apply to `x` and `y` to obtain such an array. -""" - """ scatter(x,y) scatter!(x,y) Make a scatter plot of y vs x. -# Arguments -$xydoc - # Examples ```julia-repl julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue]) @@ -37,7 +20,6 @@ Make a bar plot of y vs x. # Arguments -$xydoc - $(_document_argument("bar_position")) - $(_document_argument("bar_width")) - $(_document_argument("bar_edges")) @@ -111,7 +93,6 @@ Plot a two-dimensional histogram. # Arguments -$xydoc - `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) - `weights`: Vector of weights for the values in `x`. Each entry of x contributes its weight to the height of its bin. @@ -127,7 +108,7 @@ julia> histogram2d(randn(10_000),randn(10_000)) density(x) density!(x) -Make a line plot of a kernel density estimate of x +Make a line plot of a kernel density estimate of x. # Arguments @@ -145,11 +126,7 @@ julia> density(randn(100_000)) heatmap(x,y,z) heatmap!(x,y,z) -Plot a heatmap of the rectangular array `z` - -# Arguments -$xyzdoc - +Plot a heatmap of the rectangular array `z`. # Example ```julia-repl @@ -179,9 +156,6 @@ julia> hexbin(randn(10_000), randn(10_000)) Draw a stick plot of y vs x. -# Arguments -$xydoc - # Example ```julia-repl julia> sticks(1:10) @@ -272,7 +246,6 @@ julia> ohlc(y) Draw contour lines of the `Surface` z. # Arguments -$xyzdoc - `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`) - `fill`: Bool. Fill area between contours or draw contours only (false by default) @@ -296,9 +269,6 @@ julia> contour(x, y, (x, y) -> x^2 + y^2) Draw a 3D surface plot. -# Arguments -$xyzdoc - # Example ```julia-repl julia> x = y = range(-3, 3, length = 100) @@ -313,9 +283,6 @@ julia> surface(x, y, (x, y) -> sinc(norm([x, y]))) Draw a 3D wireframe plot. -# Arguments -$xyzdoc - # Example ```julia-repl julia> wireframe(1:10,1:10,randn(10,10)) @@ -356,9 +323,6 @@ julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) Make a box and whisker plot. -# Arguments -$xydoc - # Keyword arguments - `notch`: Bool. Notch the box plot? (false) - `range`: Real. Values more than range*IQR below the first quartile From f50862ac517ca2f3cfbfc538cbd98e3baa10c42b Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 08:43:43 -0500 Subject: [PATCH 087/230] Remove blank lines --- src/utils.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index a0bad5a8..7f582e81 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1233,6 +1233,3 @@ end function _document_argument(S::AbstractString) _fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S)) end - - - From 44a6707397541b03c427e0fd23c2438157f4a036 Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 10:28:46 -0500 Subject: [PATCH 088/230] Fix annotation font rotation --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 43211f50..7fb448d0 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1152,7 +1152,7 @@ function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText) color = py_color(val.font.color), horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign), verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign), - rotation = val.font.rotation * 180 / π, + rotation = val.font.rotation, size = py_thickness_scale(sp.plt, val.font.pointsize), zorder = 999 ) From 888ed9f0ae339f4b330f51c6fc74287e4c2c1f08 Mon Sep 17 00:00:00 2001 From: "Samuel S. Watson" Date: Wed, 16 Jan 2019 13:04:31 -0500 Subject: [PATCH 089/230] Support keyword arguments for font attributes --- src/components.jl | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/components.jl b/src/components.jl index f338432c..e6215624 100644 --- a/src/components.jl +++ b/src/components.jl @@ -258,24 +258,22 @@ end """ font(args...) - -Create a Font from an unordered list of features. - +Create a Font from a list of features. Values may be specified either as +arguments (which are distinguished by type/value) or as keyword arguments. # Arguments - - `family`: AbstractString. "serif" or "sans-serif" or "monospace" - `pointsize`: Integer. Size of font in points - `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right) - `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom) - `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type) - `color`: Colorant or Symbol - # Examples ```julia-repl -julia> text("sans-serif",8,:hcenter,45.0,:blue) +julia> font(8) +julia> font(family="serif",halign=:center,rotation=45.0) ``` """ -function font(args...) +function font(args...;kw...) # defaults family = "sans-serif" @@ -319,6 +317,32 @@ function font(args...) end end + for symbol in keys(kw) + if symbol == :family + family = kw[:family] + elseif symbol == :pointsize + pointsize = kw[:pointsize] + elseif symbol == :halign + halign = kw[:halign] + if halign == :center + halign = :hcenter + end + @assert halign in (:hcenter, :left, :right) + elseif symbol == :valign + valign = kw[:valign] + if valign == :center + valign = :vcenter + end + @assert valign in (:vcenter, :top, :bottom) + elseif symbol == :rotation + rotation = kw[:rotation] + elseif symbol == :color + color = parse(Colorant, kw[:color]) + else + @warn("Unused font kwarg: $symbol") + end + end + Font(family, pointsize, halign, valign, rotation, color) end @@ -362,15 +386,16 @@ end PlotText(str) = PlotText(string(str), font()) """ - text(string, args...) + text(string, args...; kw...) -Create a PlotText object wrapping a string with font info, for plot annotations +Create a PlotText object wrapping a string with font info, for plot annotations. +`args` and `kw` are passed to `font`. """ text(t::PlotText) = t text(t::PlotText, font::Font) = PlotText(t.str, font) text(str::AbstractString, f::Font) = PlotText(str, f) -function text(str, args...) - PlotText(string(str), font(args...)) +function text(str, args...;kw...) + PlotText(string(str), font(args...;kw...)) end Base.length(t::PlotText) = length(t.str) From 789a7fbb880dfba45ade2276fad4e29894ae2687 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 22 Jan 2019 13:00:56 +0100 Subject: [PATCH 090/230] fix grayscale image in pyplot --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 7fb448d0..06bce22e 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -667,7 +667,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end handle = ax[:imshow](z; zorder = series[:series_plotindex], - cmap = py_colormap([:black, :white]), + cmap = py_colormap(cgrad([:black, :white])), vmin = 0.0, vmax = 1.0, extent = (xmin, xmax, ymax, ymin) From c8c82811b3a2c20cfab5d92743fc209119e72bd4 Mon Sep 17 00:00:00 2001 From: djsegal Date: Tue, 22 Jan 2019 15:07:21 -0500 Subject: [PATCH 091/230] Fix bug where pyplot marker vec added blank legend --- src/backends/pyplot.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 5c0f84f0..f13032dd 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1330,12 +1330,12 @@ 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) + elseif series[:seriestype] in (:path, :straightline, :scatter) PyPlot.plt[:Line2D]((0,1),(0,0), color = py_color(get_linecolor(series), get_linealpha(series)), linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)), linestyle = py_linestyle(:path, get_linestyle(series)), - marker = py_marker(series[:markershape]), + marker = py_marker(first(series[:markershape])), markeredgecolor = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)), markerfacecolor = series[:marker_z] == nothing ? py_color(get_markercolor(series), get_markeralpha(series)) : py_color(series[:markercolor][0.5]) ) From f12d328cf76d5eda9efbb18a3baddf022db0bf53 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 22 Jan 2019 22:42:04 +0100 Subject: [PATCH 092/230] clamp image for backends not supporting image Does not work for GR or PyPlot which are supposed to support images natively --- src/series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index 33861bd6..fbf5ee10 100644 --- a/src/series.jl +++ b/src/series.jl @@ -335,7 +335,7 @@ end yflip --> true cbar --> false fillcolor --> ColorGradient([:black, :white]) - SliceIt, 1:m, 1:n, Surface(convert(Matrix{Float64}, mat)) + SliceIt, 1:m, 1:n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.)) end end From 5e2598936687de9b0fd54aef5e7813388bfd2190 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Wed, 23 Jan 2019 21:04:09 +0100 Subject: [PATCH 093/230] copy and clamp for greyscale images if outside (0,1) --- src/series.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/series.jl b/src/series.jl index fbf5ee10..ab2dd3a0 100644 --- a/src/series.jl +++ b/src/series.jl @@ -323,12 +323,14 @@ end # # images - grays +clamp_greys(mat::AMat{T}) where T<:Gray = Gray.(clamp!([m.val for m in mat], 0, 1)) @recipe function f(mat::AMat{T}) where T<:Gray n, m = size(mat) if is_seriestype_supported(:image) seriestype := :image yflip --> true + any(x-> x.val<0 || x.val >1, mat) && (mat = clamp_greys(mat)) SliceIt, 1:m, 1:n, Surface(mat) else seriestype := :heatmap From 877811979295f9b8200f5a7d0fc160fa7be71f41 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Wed, 23 Jan 2019 22:35:13 +0100 Subject: [PATCH 094/230] Inplace clamp --- src/series.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/series.jl b/src/series.jl index ab2dd3a0..fd9f5fdb 100644 --- a/src/series.jl +++ b/src/series.jl @@ -323,15 +323,20 @@ end # # images - grays -clamp_greys(mat::AMat{T}) where T<:Gray = Gray.(clamp!([m.val for m in mat], 0, 1)) +function clamp_greys!(mat::AMat{T}) where T<:Gray + for i in eachindex(mat) + mat[i].val < 0 && (mat[i] = Gray(0)) + mat[i].val > 1 && (mat[i] = Gray(1)) + end + mat +end @recipe function f(mat::AMat{T}) where T<:Gray n, m = size(mat) if is_seriestype_supported(:image) seriestype := :image yflip --> true - any(x-> x.val<0 || x.val >1, mat) && (mat = clamp_greys(mat)) - SliceIt, 1:m, 1:n, Surface(mat) + SliceIt, 1:m, 1:n, Surface(clamp_greys!(mat)) else seriestype := :heatmap yflip --> true From fef45dfc302f1b317b12d6bc9005c977e074f020 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Thu, 24 Jan 2019 20:37:33 +0100 Subject: [PATCH 095/230] gr: clamp rgb values --- src/backends/gr.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1d4fbca6..f7ba5e04 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1182,13 +1182,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) z = z[xinds, yinds] xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y]) if eltype(z) <: Colors.AbstractGray - grey = round.(UInt8, float(z) * 255) + grey = round.(UInt8, clamp.(float(z) * 255, 0, 255)) rgba = map(c -> UInt32( 0xff000000 + UInt(c)<<16 + UInt(c)<<8 + UInt(c) ), grey) else - rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 + - round(UInt, blue(c) * 255) << 16 + - round(UInt, green(c) * 255) << 8 + - round(UInt, red(c) * 255) ), z) + rgba = map(c -> UInt32( round(UInt, clamp(alpha(c) * 255, 0, 255)) << 24 + + round(UInt, clamp(blue(c) * 255, 0, 255)) << 16 + + round(UInt, clamp(green(c) * 255, 0, 255)) << 8 + + round(UInt, clamp(red(c) * 255, 0, 255)) ), z) end GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) end From 399a9b16f6b4a9259c5c844b38954bc56715a1ba Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 24 Jan 2019 23:24:17 +0100 Subject: [PATCH 096/230] StatPlots --> StatsPlots --- NEWS.md | 8 ++++---- src/args.jl | 4 ++-- src/plot.jl | 4 ++-- src/recipes.jl | 2 +- src/shorthands.jl | 4 ++-- test/REQUIRE | 2 +- test/imgcomp.jl | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/NEWS.md b/NEWS.md index 15d2aaa2..7ce23298 100644 --- a/NEWS.md +++ b/NEWS.md @@ -182,7 +182,7 @@ Many updates, min julia 1.0 - add `reset_defaults()` function to reset plot defaults - update syntax to 0.6 - make `fill = true` fill to 0 rather than to 1 -- use new `@df` syntax in StatPlots examples +- use new `@df` syntax in StatsPlots examples - allow changing the color of legend box - implement `title_location` for gr - add `hline` marker to pgfplots - fixes errorbars @@ -334,7 +334,7 @@ Many updates, min julia 1.0 - added dependency on PlotThemes - set_theme --> theme - remove Compat from REQUIRE -- warning for DataFrames without StatPlots +- warning for DataFrames without StatsPlots - closeall exported and implemented for gr/pyplot - fix DateTime recipe - reset theme with theme(:none) @@ -456,8 +456,8 @@ Many updates, min julia 1.0 #### 0.8.0 - added dependency on PlotUtils -- BREAKING: removed DataFrames support (now in StatPlots.jl) -- BREAKING: removed boxplot/violin/density recipes (now in StatPlots.jl) +- BREAKING: removed DataFrames support (now in StatsPlots.jl) +- BREAKING: removed boxplot/violin/density recipes (now in StatsPlots.jl) - GR: - inline iterm2 support - trisurface support diff --git a/src/args.jl b/src/args.jl index 1065f12e..3285571b 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1050,8 +1050,8 @@ function preprocessArgs!(plotattributes::KW) # warnings for moved recipes st = get(plotattributes, :seriestype, :path) - if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatPlots) - @warn("seriestype $st has been moved to StatPlots. To use: \`Pkg.add(\"StatPlots\"); using StatPlots\`") + if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatsPlots) + @warn("seriestype $st has been moved to StatsPlots. To use: \`Pkg.add(\"StatsPlots\"); using StatsPlots\`") end return diff --git a/src/plot.jl b/src/plot.jl index 7ac78601..2c2ecd48 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -166,9 +166,9 @@ end function _plot!(plt::Plot, plotattributes::KW, args::Tuple) plotattributes[:plot_object] = plt - if !isempty(args) && !isdefined(Main, :StatPlots) && + if !isempty(args) && !isdefined(Main, :StatsPlots) && first(split(string(typeof(args[1])), ".")) == "DataFrames" - @warn("You're trying to plot a DataFrame, but this functionality is provided by StatPlots") + @warn("You're trying to plot a DataFrame, but this functionality is provided by StatsPlots") end # -------------------------------- diff --git a/src/recipes.jl b/src/recipes.jl index 63a069c9..ff3090c0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -586,7 +586,7 @@ end end Plots.@deps stepbins path -wand_edges(x...) = (@warn("Load the StatPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto) +wand_edges(x...) = (@warn("Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto) function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N _cl(x) = ceil(Int, max(x, one(x))) diff --git a/src/shorthands.jl b/src/shorthands.jl index 7c5d7003..5d240482 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -116,7 +116,7 @@ Make a line plot of a kernel density estimate of x. # Example ```julia-repl -julia> using StatPlots +julia> using StatsPlots julia> density(randn(100_000)) ``` """ @@ -332,7 +332,7 @@ Make a box and whisker plot. # Example ```julia-repl -julia> using StatPlots +julia> using StatsPlots julia> boxplot(repeat([1,2,3],outer=100),randn(300)) ``` """ diff --git a/test/REQUIRE b/test/REQUIRE index a11706d9..06f37166 100644 --- a/test/REQUIRE +++ b/test/REQUIRE @@ -1,4 +1,4 @@ -StatPlots +StatsPlots Images ImageMagick @osx QuartzImageIO diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 526d695e..6d7dd457 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -18,7 +18,7 @@ end using Plots -# using StatPlots +# using StatsPlots import PlotReferenceImages using Random using Test From 182b937143b7c1444cd1d79593b1d435f6ccf358 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Wed, 31 Oct 2018 16:55:57 +0100 Subject: [PATCH 097/230] Refactor __init__() to make Plots load faster --- src/Plots.jl | 2 + src/fileio.jl | 24 +++++++++++ src/ijulia.jl | 59 ++++++++++++++++++++++++++++ src/init.jl | 107 +++++++++++--------------------------------------- 4 files changed, 107 insertions(+), 85 deletions(-) create mode 100644 src/fileio.jl create mode 100644 src/ijulia.jl diff --git a/src/Plots.jl b/src/Plots.jl index fb93c45f..d387275e 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -180,6 +180,8 @@ include("arg_desc.jl") include("plotattr.jl") include("backends.jl") include("output.jl") +include("ijulia.jl") +include("fileio.jl") include("init.jl") include("backends/plotly.jl") diff --git a/src/fileio.jl b/src/fileio.jl new file mode 100644 index 00000000..dbb0469e --- /dev/null +++ b/src/fileio.jl @@ -0,0 +1,24 @@ +# --------------------------------------------------------- +# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert + +_fileio_load(@nospecialize(filename::AbstractString)) = FileIO.load(filename::AbstractString) +_fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) = FileIO.save(filename::AbstractString, x) + +function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot) + fn = tempname() + + # first save a pdf file + pdf(plt, fn) + + # load that pdf into a FileIO Stream + s = _fileio_load(fn * ".pdf") + + # save a png + pngfn = fn * ".png" + _fileio_save(pngfn, s) + + # now write from the file + write(io, read(open(pngfn), String)) +end + +const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend} diff --git a/src/ijulia.jl b/src/ijulia.jl new file mode 100644 index 00000000..a54c0ca9 --- /dev/null +++ b/src/ijulia.jl @@ -0,0 +1,59 @@ +const use_local_dependencies = Ref(false) +const use_local_plotlyjs = Ref(false) + + +function _init_ijulia_plotting() + # IJulia is more stable with local file + use_local_plotlyjs[] = isfile(plotly_local_file_path) + + ENV["MPLBACKEND"] = "Agg" +end + + +""" +Add extra jupyter mimetypes to display_dict based on the plot backed. + +The default is nothing, except for plotly based backends, where it +adds data for `application/vnd.plotly.v1+json` that is used in +frontends like jupyterlab and nteract. +""" +_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out + +function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict) + out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o) + out +end + +function _ijulia__extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict) + out["application/vnd.plotly.v1+json"] = Dict( + :data => plotly_series(plt), + :layout => plotly_layout(plt) + ) + out +end + + +function _ijulia_display_dict(plt::Plot) + output_type = Symbol(plt.attr[:html_output_format]) + if output_type == :auto + output_type = get(_best_html_output_type, backend_name(plt.backend), :svg) + end + out = Dict() + if output_type == :txt + mime = "text/plain" + out[mime] = sprint(show, MIME(mime), plt) + elseif output_type == :png + mime = "image/png" + out[mime] = base64encode(show, MIME(mime), plt) + elseif output_type == :svg + mime = "image/svg+xml" + out[mime] = sprint(show, MIME(mime), plt) + elseif output_type == :html + mime = "text/html" + out[mime] = sprint(show, MIME(mime), plt) + else + error("Unsupported output type $output_type") + end + _ijulia__extra_mime_info!(plt, out) + out +end diff --git a/src/init.jl b/src/init.jl index 257ba4b8..1cd1fcd2 100644 --- a/src/init.jl +++ b/src/init.jl @@ -1,16 +1,22 @@ using REPL -const use_local_dependencies = Ref(false) + +function _plots_defaults() + if isdefined(Main, :PLOTS_DEFAULTS) + Main.PLOTS_DEFAULTS::Dict{Symbol,Any} + else + Dict{Symbol,Any}() + end +end + function __init__() - - if isdefined(Main, :PLOTS_DEFAULTS) - if haskey(Main.PLOTS_DEFAULTS, :theme) - theme(Main.PLOTS_DEFAULTS[:theme]) - end - for (k,v) in Main.PLOTS_DEFAULTS - k == :theme || default(k, v) - end + user_defaults = _plots_defaults() + if haskey(user_defaults, :theme) + theme(user_defaults[:theme]) + end + for (k,v) in user_defaults + k == :theme || default(k, v) end insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) @@ -29,95 +35,26 @@ function __init__() @require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" include(joinpath(@__DIR__, "backends", "pyplot.jl")) @require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" include(joinpath(@__DIR__, "backends", "unicodeplots.jl")) - # --------------------------------------------------------- - # IJulia - # --------------------------------------------------------- - use_local = false @require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin if IJulia.inited - # IJulia is more stable with local file - use_local = isfile(plotly_local_file_path) - """ - Add extra jupyter mimetypes to display_dict based on the plot backed. + _init_ijulia_plotting() - The default is nothing, except for plotly based backends, where it - adds data for `application/vnd.plotly.v1+json` that is used in - frontends like jupyterlab and nteract. - """ - _extra_mime_info!(plt::Plot, out::Dict) = out - function _extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict) - out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o) - out - end - - function _extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict) - out["application/vnd.plotly.v1+json"] = Dict( - :data => plotly_series(plt), - :layout => plotly_layout(plt) - ) - out - end - - function IJulia.display_dict(plt::Plot) - output_type = Symbol(plt.attr[:html_output_format]) - if output_type == :auto - output_type = get(_best_html_output_type, backend_name(plt.backend), :svg) - end - out = Dict() - if output_type == :txt - mime = "text/plain" - out[mime] = sprint(show, MIME(mime), plt) - elseif output_type == :png - mime = "image/png" - out[mime] = base64encode(show, MIME(mime), plt) - elseif output_type == :svg - mime = "image/svg+xml" - out[mime] = sprint(show, MIME(mime), plt) - elseif output_type == :html - mime = "text/html" - out[mime] = sprint(show, MIME(mime), plt) - else - error("Unsupported output type $output_type") - end - _extra_mime_info!(plt, out) - out - end - - ENV["MPLBACKEND"] = "Agg" + IJulia.display_dict(plt::Plot) = _ijulia_display_dict(plt) end end if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL") - use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true" - use_local_dependencies[] = isfile(plotly_local_file_path) && use_local - if use_local && !isfile(plotly_local_file_path) + use_local_plotlyjs[] = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true" + use_local_dependencies[] = isfile(plotly_local_file_path) && use_local_plotlyjs[] + if use_local_plotlyjs[] && !isfile(plotly_local_file_path) @warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true") end else - use_local_dependencies[] = use_local + use_local_dependencies[] = use_local_plotlyjs[] end - - # --------------------------------------------------------- - # A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert @require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin - PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend} - function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends}) - fn = tempname() - - # first save a pdf file - pdf(plt, fn) - - # load that pdf into a FileIO Stream - s = FileIO.load(fn * ".pdf") - - # save a png - pngfn = fn * ".png" - FileIO.save(pngfn, s) - - # now write from the file - write(io, read(open(pngfn), String)) - end + _show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt) end end From 7867df6079908b7d425ff1566b35b194f86241ce Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 18:15:50 +0100 Subject: [PATCH 098/230] _initialize_backend doesn't need to do anything for GRBackend --- src/backends.jl | 3 +++ src/backends/gr.jl | 1 + 2 files changed, 4 insertions(+) diff --git a/src/backends.jl b/src/backends.jl index eae321f8..4183cf3b 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -316,6 +316,9 @@ function _initialize_backend(pkg::AbstractBackend) end end +_initialize_backend(pkg::GRBackend) = nothing + + function add_backend_string(pkg::AbstractBackend) sym = backend_package_name(pkg) """ diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1d4fbca6..7b51fff6 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -6,6 +6,7 @@ import GR export GR + # -------------------------------------------------------------------------------------- const gr_linetype = KW( From 141845aa407bcb93aee4a9f8230fbb73a80c7c8f Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Fri, 2 Nov 2018 00:13:49 +0100 Subject: [PATCH 099/230] _initialize_backend doesn't need to do anything for PlotlyBackend --- src/backends.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backends.jl b/src/backends.jl index 4183cf3b..52231ae1 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -318,6 +318,8 @@ end _initialize_backend(pkg::GRBackend) = nothing +_initialize_backend(pkg::PlotlyBackend) = nothing + function add_backend_string(pkg::AbstractBackend) sym = backend_package_name(pkg) From 9aa1fd5c003cc6453743e60ef49456cc2f1b265b Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 18:18:04 +0100 Subject: [PATCH 100/230] macro init_backend can call backend() with backend instance --- src/backends.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends.jl b/src/backends.jl index 52231ae1..0ba8d5fc 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -26,7 +26,7 @@ macro init_backend(s) esc(quote struct $T <: AbstractBackend end export $sym - $sym(; kw...) = (default(; kw...); backend(Symbol($str))) + $sym(; kw...) = (default(; kw...); backend($T())) backend_name(::$T) = Symbol($str) backend_package_name(pkg::$T) = backend_package_name(Symbol($str)) push!(_backends, Symbol($str)) From f1719d6e9102e2cd77b9b2b3ffe96d7e5fc78afa Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 18:26:31 +0100 Subject: [PATCH 101/230] Improve implementation of backend(pkg::AbstractBackend) --- src/backends.jl | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 0ba8d5fc..e008283b 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -188,20 +188,13 @@ Set the plot backend. """ function backend(pkg::AbstractBackend) sym = backend_name(pkg) - if sym in _initialized_backends - CURRENT_BACKEND.sym = backend_name(pkg) - CURRENT_BACKEND.pkg = pkg - else - # try - _initialize_backend(pkg) - push!(_initialized_backends, sym) - CURRENT_BACKEND.sym = backend_name(pkg) - CURRENT_BACKEND.pkg = pkg - # catch - # add_backend(sym) - # end + if !(sym in _initialized_backends) + _initialize_backend(pkg) + push!(_initialized_backends, sym) end - backend() + CURRENT_BACKEND.sym = sym + CURRENT_BACKEND.pkg = pkg + pkg end function backend(sym::Symbol) From 420228c67b24c8e131eb34ee179b1ab2ba0f5de3 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 21:49:34 +0100 Subject: [PATCH 102/230] Remove function add_backend No longer in use. --- src/Plots.jl | 1 - src/backends.jl | 56 ------------------------------------------------- 2 files changed, 57 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index d387275e..10c599ff 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -84,7 +84,6 @@ export backends, backend_name, backend_object, - add_backend, aliases, Shape, diff --git a/src/backends.jl b/src/backends.jl index e008283b..f0445ff6 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -42,12 +42,6 @@ end # --------------------------------------------------------- -function add_backend(pkg::Symbol) - @info("To do a standard install of $pkg, copy and run this:\n\n") - println(add_backend_string(_backend_instance(pkg))) - println() -end - # don't do anything as a default _create_backend_figure(plt::Plot) = nothing _prepare_plot_object(plt::Plot) = nothing @@ -314,14 +308,6 @@ _initialize_backend(pkg::GRBackend) = nothing _initialize_backend(pkg::PlotlyBackend) = nothing -function add_backend_string(pkg::AbstractBackend) - sym = backend_package_name(pkg) - """ - using Pkg - Pkg.add("$sym") - """ -end - # ------------------------------------------------------------------------------ # gr @@ -377,13 +363,6 @@ const _gr_marker = _allMarkers const _gr_scale = [:identity, :log10] is_marker_supported(::GRBackend, shape::Shape) = true -function add_backend_string(::GRBackend) - """ - Pkg.add("GR") - Pkg.build("GR") - """ -end - # ------------------------------------------------------------------------------ # plotly @@ -445,14 +424,6 @@ const _plotly_scale = [:identity, :log10] # ------------------------------------------------------------------------------ # pgfplots -function add_backend_string(::PGFPlotsBackend) - """ - using Pkg - Pkg.add("PGFPlots") - Pkg.build("PGFPlots") - """ -end - const _pgfplots_attr = merge_with_base_supported([ :annotations, :background_color_legend, @@ -504,15 +475,6 @@ function _initialize_backend(pkg::PlotlyJSBackend) end end -function add_backend_string(::PlotlyJSBackend) - """ - using Pkg - Pkg.add(["PlotlyJS", "Blink", "ORCA"]) - import Blink - Blink.AtomShell.install() - """ -end - const _plotlyjs_attr = _plotly_attr const _plotlyjs_seriestype = _plotly_seriestype const _plotlyjs_style = _plotly_style @@ -533,16 +495,6 @@ function _initialize_backend(::PyPlotBackend) end end -function add_backend_string(::PyPlotBackend) - """ - using Pkg - withenv("PYTHON" => "") do - Pkg.add("PyPlot") - Pkg.build("PyPlot") - end - """ -end - const _pyplot_attr = merge_with_base_supported([ :annotations, :background_color_legend, :background_color_inside, :background_color_outside, @@ -596,14 +548,6 @@ const _pyplot_scale = [:identity, :ln, :log2, :log10] # ------------------------------------------------------------------------------ # unicodeplots -function add_backend_string(::UnicodePlotsBackend) - """ - using Pkg - Pkg.add("UnicodePlots") - Pkg.build("UnicodePlots") - """ -end - const _unicodeplots_attr = merge_with_base_supported([ :label, :legend, From 43245b5eb5f4a242c50d90cfd41d1188bc575043 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Fri, 2 Nov 2018 00:14:52 +0100 Subject: [PATCH 103/230] Clean up backend-related global vars and related functions --- src/backends.jl | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index f0445ff6..4106914d 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -7,16 +7,16 @@ const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none) const _backends = Symbol[] const _initialized_backends = Set{Symbol}() const _default_backends = (:none, :gr, :plotly) -const _backendPackage = Dict{Symbol, Symbol}() + +const _backend_packages = Dict{Symbol, Symbol}() "Returns a list of supported backends" backends() = _backends "Returns the name of the current backend" backend_name() = CURRENT_BACKEND.sym -_backend_instance(sym::Symbol) = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym") -backend_package(pkg::Symbol) = pkg in _default_backends ? :Plots : Symbol("Plots", _backendPackage[pkg]) -backend_package_name(sym::Symbol) = sym in _default_backends ? :Plots : _backendPackage[sym] +_backend_instance(sym::Symbol)::AbstractBackend = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym") +backend_package_name(sym::Symbol) = _backend_packages[sym] macro init_backend(s) package_str = string(s) @@ -32,7 +32,7 @@ macro init_backend(s) push!(_backends, Symbol($str)) _backendType[Symbol($str)] = $T _backendSymbol[$T] = Symbol($str) - _backendPackage[Symbol($str)] = Symbol($package_str) + _backend_packages[Symbol($str)] = Symbol($package_str) # include("backends/" * $str * ".jl") end) end @@ -148,15 +148,6 @@ function pickDefaultBackend() end end - # the ordering/inclusion of this package list is my semi-arbitrary guess at - # which one someone will want to use if they have the package installed...accounting for - # features, speed, and robustness - # for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR") - # if pkgstr in keys(Pkg.installed()) - # return backend(Symbol(lowercase(pkgstr))) - # end - # end - # the default if nothing else is installed backend(:gr) end @@ -196,8 +187,8 @@ function backend(sym::Symbol) backend(_backend_instance(sym)) else @warn("`:$sym` is not a supported backend.") + backend() end - backend() end const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize] @@ -468,7 +459,6 @@ const _pgfplots_scale = [:identity, :ln, :log2, :log10] # plotlyjs function _initialize_backend(pkg::PlotlyJSBackend) - sym = backend_package_name(pkg) @eval Main begin import PlotlyJS, ORCA export PlotlyJS From ffcdf986a3261be6f140fbcfb3dd451cd6b9cb92 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 23:07:58 +0100 Subject: [PATCH 104/230] Set explicit return type for function _backend_instance Inferred return type is Any, otherwise, not AbstractBackend. --- src/backends.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backends.jl b/src/backends.jl index 4106914d..13eada09 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -15,7 +15,11 @@ backends() = _backends "Returns the name of the current backend" backend_name() = CURRENT_BACKEND.sym -_backend_instance(sym::Symbol)::AbstractBackend = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym") + +function _backend_instance(sym::Symbol)::AbstractBackend + haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym") +end + backend_package_name(sym::Symbol) = _backend_packages[sym] macro init_backend(s) From b9b6439f472aba832008aad019bbba0debab759d Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 1 Nov 2018 23:08:52 +0100 Subject: [PATCH 105/230] Clean up backend default handling --- src/backends.jl | 23 ++++++++++++----------- src/utils.jl | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 13eada09..11d0a414 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -136,24 +136,27 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, _backend_instance(sym)) # --------------------------------------------------------- -function pickDefaultBackend() +_fallback_default_backend() = backend(GRBackend()) + +function _pick_default_backend() env_default = get(ENV, "PLOTS_DEFAULT_BACKEND", "") if env_default != "" sym = Symbol(lowercase(env_default)) if sym in _backends if sym in _initialized_backends - return backend(sym) + backend(sym) else @warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.") + _fallback_default_backend() end else @warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" * join(sort(_backends), "\n\t")) + _fallback_default_backend() end + else + _fallback_default_backend() end - - # the default if nothing else is installed - backend(:gr) end @@ -163,13 +166,11 @@ end Returns the current plotting package name. Initializes package on first call. """ function backend() + if CURRENT_BACKEND.sym == :none + _pick_default_backend() + end - global CURRENT_BACKEND - if CURRENT_BACKEND.sym == :none - pickDefaultBackend() - end - - CURRENT_BACKEND.pkg + CURRENT_BACKEND.pkg end """ diff --git a/src/utils.jl b/src/utils.jl index 7f582e81..bdb3f330 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -726,7 +726,7 @@ function with(f::Function, args...; kw...) # save the backend if CURRENT_BACKEND.sym == :none - pickDefaultBackend() + _pick_default_backend() end oldbackend = CURRENT_BACKEND.sym From 9d5ce9753a35e5d3a2642e60b509fa61c99a3875 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sun, 3 Feb 2019 14:19:32 -0500 Subject: [PATCH 106/230] Fixed MethodError --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index ff3090c0..37982a3d 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -47,7 +47,7 @@ end num_series(x::AMat) = size(x,2) num_series(x) = 1 -RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T")) +RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T")) # --------------------------------------------------------------------------- From 87af609a6f4c16748681d25b3e339a1dd37588eb Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 9 Feb 2019 12:25:02 +0300 Subject: [PATCH 107/230] Add test case for https://github.com/JuliaPlots/Plots.jl/issues/1904 --- test/runtests.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 1587d1bb..906c5804 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -33,7 +33,12 @@ end @test backend() == Plots.UnicodePlotsBackend() # lets just make sure it runs without error - @test isa(plot(rand(10)), Plots.Plot) == true + p = plot(rand(10)) + @test isa(p, Plots.Plot) == true + @test isa(display(p), Nothing) == true + p = bar(randn(10)) + @test isa(p, Plots.Plot) == true + @test isa(display(p), Nothing) == true end # The plotlyjs testimages return a connection error on travis: From 3a2b6296ac64f04770c9b440785f80c2b4d57ad5 Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 9 Feb 2019 12:38:57 +0300 Subject: [PATCH 108/230] Fix UndefVarError: series not defined --- src/backends/unicodeplots.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 370c9a87..a2e677c5 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -116,7 +116,7 @@ function addUnicodeSeries!(o, plotattributes::KW, addlegend::Bool, xlim, ylim) x, y = if st == :straightline straightline_data(plotattributes) elseif st == :shape - shape_data(series) + shape_data(plotattributes) else [collect(float(plotattributes[s])) for s in (:x, :y)] end From 8f30696a4d210eda84fc66c45626fee0aa2aaad4 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Sat, 16 Feb 2019 18:03:21 +0100 Subject: [PATCH 109/230] gr: added support for volume plots --- src/backends.jl | 2 +- src/backends/gr.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/backends.jl b/src/backends.jl index 11d0a414..70fba5da 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -351,7 +351,7 @@ const _gr_attr = merge_with_base_supported([ const _gr_seriestype = [ :path, :scatter, :straightline, :heatmap, :pie, :image, - :contour, :path3d, :scatter3d, :surface, :wireframe, + :contour, :path3d, :scatter3d, :surface, :wireframe, :volume, :shape ] const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 45a968d0..e79270c2 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1067,6 +1067,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.surface(x, y, z, GR.OPTION_FILLED_MESH) end + elseif st == :volume + sp[:legend] = :none + GR.gr3.clear() + dmin, dmax = GR.gr3.volume(y.v, 0) + elseif st == :heatmap xmin, xmax, ymin, ymax = xy_lims zmin, zmax = clims From c2af1a0666f392afddfc5c01548b2f0726040e96 Mon Sep 17 00:00:00 2001 From: yharel Date: Mon, 18 Feb 2019 04:02:31 +0200 Subject: [PATCH 110/230] Colorbar and contour fixes --- src/backends/gr.jl | 94 +++++++++++++++++++++++----------------------- src/utils.jl | 16 ++++++++ 2 files changed, 63 insertions(+), 47 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 7b51fff6..7cb46e4e 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -415,16 +415,24 @@ function gr_set_viewport_polar() end # add the colorbar -function gr_colorbar(sp::Subplot, clims) +function gr_colorbar(sp::Subplot, clims, levels) + GR.savestate() xmin, xmax = gr_xy_axislims(sp)[1:2] + zmin, zmax = clims[1:2] gr_set_viewport_cmap(sp) - l = zeros(Int32, 1, 256) - l[1,:] = Int[round(Int, _i) for _i in range(1000, stop=1255, length=256)] + l = if levels === nothing + (1000:1255)' + elseif length(levels) > 1 + min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels) + round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255) + else + Int32[1000, 1255] + end GR.setscale(0) - GR.setwindow(xmin, xmax, clims[1], clims[2]) - GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l) - ztick = 0.5 * GR.tick(clims[1], clims[2]) - GR.axes(0, ztick, xmax, clims[1], 0, 1, 0.005) + GR.setwindow(xmin, xmax, zmin, zmax) + GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l) + ztick = 0.5 * GR.tick(zmin, zmax) + GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005) gr_set_font(guidefont(sp[:yaxis])) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) @@ -432,7 +440,7 @@ function gr_colorbar(sp::Subplot, clims) gr_text(viewport_plotarea[2] + gr_colorbar_ratio, gr_view_ycenter(), sp[:colorbar_title]) - gr_set_viewport_plotarea() + GR.restorestate() end gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2]) @@ -470,8 +478,11 @@ end const _gr_gradient_alpha = ones(256) -function gr_set_gradient(c) - grad = isa(c, ColorGradient) ? c : cgrad() +function gr_set_gradient(c; ignore_colorant = true) + @show c + gradient(g::ColorGradient) = g + gradient(c::Colorant) = ignore_colorant ? cgrad() : ColorGradient([c,c]) + grad = gradient(c) for (i,z) in enumerate(range(0, stop=1, length=256)) c = grad[z] GR.setcolorrep(999+i, red(c), green(c), blue(c)) @@ -660,7 +671,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # reduced from before... set some flags based on the series in this subplot # TODO: can these be generic flags? outside_ticks = false - cmap = hascolorbar(sp) + # calculate the colorbar limits once for a subplot + clims = get_clims(sp) + clevels = nothing + draw_axes = sp[:framestyle] != :none # axes_2d = true for series in series_list(sp) @@ -682,6 +696,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) expand_extrema!(sp[:yaxis], y) data_lims = gr_xy_axislims(sp) end + + # color levels overwritten by the last relevant series + hascolorbar(series) && (clevels = colorbar_levels(series, clims)) end # set our plot area view @@ -730,11 +747,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.setlinewidth(sp.plt[:thickness_scaling]) if is3d(sp) + # TODO do we really need a different clims computation here from the one + # computed above using get_clims(sp)? zmin, zmax = gr_lims(zaxis, true) - clims = sp[:clims] - if is_2tuple(clims) - isfinite(clims[1]) && (zmin = clims[1]) - isfinite(clims[2]) && (zmax = clims[2]) + clims3d = sp[:clims] + if is_2tuple(clims3d) + isfinite(clims3d[1]) && (zmin = clims3d[1]) + isfinite(clims3d[2]) && (zmax = clims3d[2]) end GR.setspace(zmin, zmax, round.(Int, sp[:camera])...) xtick = GR.tick(xmin, xmax) / 2 @@ -939,15 +958,14 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # this needs to be here to point the colormap to the right indices GR.setcolormap(1000 + GR.COLORMAP_COOLWARM) - # calculate the colorbar limits once for a subplot - clims = get_clims(sp) - for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] # update the current stored gradient - if st in (:contour, :surface, :wireframe, :heatmap) + if st in (:surface, :heatmap) gr_set_gradient(series[:fillcolor]) #, series[:fillalpha]) + elseif st in (:contour, :wireframe) + gr_set_gradient(series[:linecolor])#, ignore_colorant=false) elseif series[:marker_z] != nothing series[:markercolor] = gr_set_gradient(series[:markercolor]) elseif series[:line_z] != nothing @@ -1023,34 +1041,23 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end elseif st == :contour - zmin, zmax = clims - GR.setspace(zmin, zmax, 0, 90) - if typeof(series[:levels]) <: AbstractArray - h = series[:levels] - else - h = series[:levels] > 1 ? range(zmin, stop=zmax, length=series[:levels]) : [(zmin + zmax) / 2] - end + GR.setspace(clims[1], clims[2], 0, 90) + h = colorbar_levels(series, clims) GR.setlinetype(gr_linetype[get_linestyle(series)]) GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) + is_lc_black = let black=plot_color(:black) + plot_color(series[:linecolor]) in (black,[black]) + end if series[:fillrange] != nothing + if series[:fillcolor] != series[:linecolor] && !is_lc_black + @warn("GR: filled contour only supported with black contour lines") + end GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0) else - coff = plot_color(series[:linecolor]) == [plot_color(:black)] ? 0 : 1000 + coff = is_lc_black ? 0 : 1000 GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0)) end - # create the colorbar of contour levels - if cmap - gr_set_line(1, :solid, yaxis[:foreground_color_axis]) - gr_set_viewport_cmap(sp) - l = (length(h) > 1) ? round.(Int32, 1000 .+ (h .- ignorenan_minimum(h)) ./ (ignorenan_maximum(h) - ignorenan_minimum(h)) .* 255) : Int32[1000, 1255] - GR.setwindow(xmin, xmax, zmin, zmax) - GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l) - ztick = 0.5 * GR.tick(zmin, zmax) - GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005) - gr_set_viewport_plotarea() - end - elseif st in [:surface, :wireframe] if st == :surface if length(x) == length(y) == length(z) @@ -1205,14 +1212,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end # draw the colorbar - GR.savestate() - # special colorbar with steps is drawn for contours - if cmap && any(series[:seriestype] != :contour for series in series_list(sp)) - gr_set_line(1, :solid, yaxis[:foreground_color_axis]) - gr_set_transparency(1) - gr_colorbar(sp, clims) - end - GR.restorestate() + hascolorbar(sp) && gr_colorbar(sp, clims, clevels) # add the legend if sp[:legend] != :none diff --git a/src/utils.jl b/src/utils.jl index bdb3f330..321ca936 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -610,6 +610,22 @@ function hascolorbar(sp::Subplot) hascbar end +function colorbar_levels(series::Series, clims) + if series[:seriestype] == :contour + zmin, zmax = clims + levels = series[:levels] + levels isa AbstractArray ? + levels : + levels > 1 ? + range(zmin, stop=zmax, length=levels) : + [(zmin + zmax) / 2] + else # including heatmap, surface + nothing + end +end + + + for comp in (:line, :fill, :marker) compcolor = string(comp, :color) From 44294306ce10e2cdeb04caaeee8de6b829e6b5ea Mon Sep 17 00:00:00 2001 From: yharel Date: Mon, 18 Feb 2019 04:50:16 +0200 Subject: [PATCH 111/230] Using fillcolor for contour with fill=true. Removed failed attempt at supporting single-color contours. --- src/backends/gr.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 7cb46e4e..ed964e66 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -478,11 +478,8 @@ end const _gr_gradient_alpha = ones(256) -function gr_set_gradient(c; ignore_colorant = true) - @show c - gradient(g::ColorGradient) = g - gradient(c::Colorant) = ignore_colorant ? cgrad() : ColorGradient([c,c]) - grad = gradient(c) +function gr_set_gradient(c) + grad = c isa ColorGradient ? c : cgrad() for (i,z) in enumerate(range(0, stop=1, length=256)) c = grad[z] GR.setcolorrep(999+i, red(c), green(c), blue(c)) @@ -962,10 +959,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) st = series[:seriestype] # update the current stored gradient - if st in (:surface, :heatmap) + if st in (:surface, :heatmap) || + (st == :contour && series[:fillrange] !== nothing) gr_set_gradient(series[:fillcolor]) #, series[:fillalpha]) elseif st in (:contour, :wireframe) - gr_set_gradient(series[:linecolor])#, ignore_colorant=false) + gr_set_gradient(series[:linecolor]) elseif series[:marker_z] != nothing series[:markercolor] = gr_set_gradient(series[:markercolor]) elseif series[:line_z] != nothing From 54b6051315deebd94a3fb8f25ce8d50196976a62 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 18 Feb 2019 11:37:15 +0100 Subject: [PATCH 112/230] bump GR version --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index a6b2ed11..789310a3 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.37.0 +GR 0.38.0 From 5b73a8ed1cda5f1037b11830a286b63313022935 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 19 Feb 2019 09:39:06 +0100 Subject: [PATCH 113/230] bump GR version to 0.38.1 --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index 789310a3..4bb39a85 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.38.0 +GR 0.38.1 From 757e08c6fe2b001604cfffcf02025b664bb8b029 Mon Sep 17 00:00:00 2001 From: harryscholes Date: Thu, 21 Feb 2019 17:59:27 +0000 Subject: [PATCH 114/230] Add Union{AVec,Tuple} to accepted types for ticksType --- src/utils.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index bdb3f330..55bb7f01 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -431,7 +431,7 @@ isvertical(series::Series) = isvertical(series.plotattributes) ticksType(ticks::AVec{T}) where {T<:Real} = :ticks ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels -ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels +ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = :ticks_and_labels ticksType(ticks) = :invalid limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits @@ -1208,8 +1208,8 @@ function _fmt_paragraph(io::IOBuffer, fillwidth=60, leadingspaces=0) - kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces) - + kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces) + m = match(r"(.*?) (.*)",remaining_text) if isa(m,Nothing) if column_count + length(remaining_text) ≤ fillwidth From a9ed4ac21db639a8e2cb7e05afbafe6bda42ce8a Mon Sep 17 00:00:00 2001 From: HMH Date: Fri, 22 Feb 2019 17:50:15 +0100 Subject: [PATCH 115/230] Add vline to PGFPlots. This enables proper vertical errorbars. --- src/backends.jl | 2 +- src/backends/pgfplots.jl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 70fba5da..d0d87a2f 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -457,7 +457,7 @@ const _pgfplots_attr = merge_with_base_supported([ ]) const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,] const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape) +const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline] #vcat(_allMarkers, Shape) const _pgfplots_scale = [:identity, :ln, :log2, :log10] # ------------------------------------------------------------------------------ diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index e060a2f1..1aebf6ef 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -26,7 +26,8 @@ const _pgfplots_markers = KW( :star6 => "asterisk", :diamond => "diamond*", :pentagon => "pentagon*", - :hline => "-" + :hline => "-", + :vline => "|" ) const _pgfplots_legend_pos = KW( From 022c79fa9536910e8be6b82736ea0ca4295cd81e Mon Sep 17 00:00:00 2001 From: HMH Date: Sat, 23 Feb 2019 00:35:52 +0100 Subject: [PATCH 116/230] Add LaTeX output for pyplot backend. Actually matplotlib supports outputting LaTeX via pgf: https://matplotlib.org/users/pgf.html --- src/backends/pyplot.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 9fa57271..1d354157 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1332,7 +1332,8 @@ const _pyplot_mimeformats = Dict( "application/pdf" => "pdf", "image/png" => "png", "application/postscript" => "ps", - "image/svg+xml" => "svg" + "image/svg+xml" => "svg", + "application/x-tex" => "pgf" ) From 9482a247e7722c98bebddeb113f30043d54129ac Mon Sep 17 00:00:00 2001 From: HMH Date: Sat, 23 Feb 2019 03:39:01 +0100 Subject: [PATCH 117/230] Remove 2 lines forgotten in 3c2cfa333c39b85155d6. --- src/output.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/output.jl b/src/output.jl index b3392cc5..fd37c10e 100644 --- a/src/output.jl +++ b/src/output.jl @@ -55,9 +55,7 @@ tex(fn::AbstractString) = tex(current(), fn) function html(plt::Plot, fn::AbstractString) fn = addExtension(fn, "html") io = open(fn, "w") - _use_remote[] = true show(io, MIME("text/html"), plt) - _use_remote[] = false close(io) end html(fn::AbstractString) = html(current(), fn) From 009d03f1f82bc0b808b8eb1df6013026c99b7ecf Mon Sep 17 00:00:00 2001 From: HMH Date: Sat, 23 Feb 2019 04:22:31 +0100 Subject: [PATCH 118/230] Set default output for plotly to html. There does not exist any other. --- src/backends.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backends.jl b/src/backends.jl index 70fba5da..51aeffa7 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -417,6 +417,8 @@ const _plotly_marker = [ ] const _plotly_scale = [:identity, :log10] +defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html" + # ------------------------------------------------------------------------------ # pgfplots From f4b14d0d8de336697d5493e27d707aff22a24ad1 Mon Sep 17 00:00:00 2001 From: Andrew Palugniok Date: Wed, 27 Feb 2019 10:30:34 +0000 Subject: [PATCH 119/230] Add 3D axes guides for GR --- src/backends/gr.jl | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 417caff3..27c6ae43 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -925,27 +925,31 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.settextalign(halign, GR.TEXT_VALIGN_TOP) gr_text(xpos, viewport_subplot[4], sp[:title]) end - - if xaxis[:guide] != "" + if is3d(sp) gr_set_font(guidefont(xaxis)) - if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) - GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide]) - else - GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide]) + GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide]) + else + if xaxis[:guide] != "" + gr_set_font(guidefont(xaxis)) + if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) + GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) + gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide]) + else + GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) + gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide]) + end end - end - if yaxis[:guide] != "" - gr_set_font(guidefont(yaxis)) - GR.setcharup(-1, 0) - if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) - GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) - else - GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) + if yaxis[:guide] != "" + gr_set_font(guidefont(yaxis)) + GR.setcharup(-1, 0) + if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) + GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) + gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) + else + GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) + gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) + end end end GR.restorestate() From 248f7cce909b91801148e2a58167da0c9a82441d Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 28 Feb 2019 23:32:57 +0100 Subject: [PATCH 120/230] update to `o.show` syntax --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 1d354157..0241e3d9 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1321,7 +1321,7 @@ end # display/output function _display(plt::Plot{PyPlotBackend}) - plt.o[:show]() + plt.o.show() end From a33b3cfbd8f95fffa9b24692c70c3a259b7ebb67 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 28 Feb 2019 23:50:06 +0100 Subject: [PATCH 121/230] check for pycall version --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 0241e3d9..972f22e0 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1321,7 +1321,7 @@ end # display/output function _display(plt::Plot{PyPlotBackend}) - plt.o.show() + isdefined(PyCall, :_setproperty!) ? plt.o.show() : plot.o[:show]() end From c4f2de198e1a4a2a396872617c88d4e89876de44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Ferenc=20Mezei?= Date: Sat, 2 Mar 2019 23:21:40 +0000 Subject: [PATCH 122/230] Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend. --- src/arg_desc.jl | 1 + src/args.jl | 1 + src/backends/pgfplots.jl | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 6fe8f068..32c4220f 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -63,6 +63,7 @@ const _arg_desc = KW( :link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).", :overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).", :html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.", +:tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.", :inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", :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.", diff --git a/src/args.jl b/src/args.jl index 3285571b..a5f043b4 100644 --- a/src/args.jl +++ b/src/args.jl @@ -298,6 +298,7 @@ const _plot_defaults = KW( :link => :none, :overwrite_figure => true, :html_output_format => :auto, + :tex_output_standalone => false, :inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are # the parent layout and the relative bounding box of inset subplots :dpi => DPI, # dots per inch for images, etc diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 1aebf6ef..4f6d99af 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -564,7 +564,7 @@ end function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend}) fn = tempname()*".tex" - PGFPlots.save(fn, backend_object(plt), include_preamble=false) + PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone]) write(io, read(open(fn), String)) end From 203d73ee265b9777ab2175a1967dd777fc3ef0e4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 5 Mar 2019 09:57:12 +0100 Subject: [PATCH 123/230] fix `ticks = :none` for gr --- src/axes.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index 1b2f693b..e67f9dac 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -614,14 +614,14 @@ function axis_drawing_info(sp::Subplot) end push!(xaxis_segs, (xmin, y1), (xmax, y1)) # don't show the 0 tick label for the origin framestyle - if sp[:framestyle] == :origin && !(xticks in (nothing,false)) && length(xticks) > 1 + if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1 showticks = xticks[1] .!= 0 xticks = (xticks[1][showticks], xticks[2][showticks]) end end sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine end - if !(xaxis[:ticks] in (nothing, false)) + if !(xaxis[:ticks] in (:none, nothing, false)) f = scalefunc(yaxis[:scale]) invf = invscalefunc(yaxis[:scale]) ticks_in = xaxis[:tick_direction] == :out ? -1 : 1 @@ -642,7 +642,7 @@ function axis_drawing_info(sp::Subplot) xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid end end - if !(xaxis[:minorticks] in (nothing, false)) || xaxis[:minorgrid] + if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid] f = scalefunc(yaxis[:scale]) invf = invscalefunc(yaxis[:scale]) ticks_in = xaxis[:tick_direction] == :out ? -1 : 1 @@ -675,14 +675,14 @@ function axis_drawing_info(sp::Subplot) end push!(yaxis_segs, (x1, ymin), (x1, ymax)) # don't show the 0 tick label for the origin framestyle - if sp[:framestyle] == :origin && !(yticks in (nothing,false)) && length(yticks) > 1 + if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1 showticks = yticks[1] .!= 0 yticks = (yticks[1][showticks], yticks[2][showticks]) end end sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine end - if !(yaxis[:ticks] in (nothing, false)) + if !(yaxis[:ticks] in (:none, nothing, false)) f = scalefunc(xaxis[:scale]) invf = invscalefunc(xaxis[:scale]) ticks_in = yaxis[:tick_direction] == :out ? -1 : 1 @@ -703,7 +703,7 @@ function axis_drawing_info(sp::Subplot) yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid end end - if !(yaxis[:minorticks] in (nothing, false)) || yaxis[:minorgrid] + if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid] f = scalefunc(xaxis[:scale]) invf = invscalefunc(xaxis[:scale]) ticks_in = yaxis[:tick_direction] == :out ? -1 : 1 From d728bfb90c9879a7ce02bf29f8049f6b3bf9fc9c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 5 Mar 2019 10:01:06 +0100 Subject: [PATCH 124/230] don't show labels for `ticks = :none` --- src/axes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index e67f9dac..fc1701f9 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -240,7 +240,7 @@ end # return (continuous_values, discrete_values) for the ticks on this axis function get_ticks(axis::Axis) ticks = _transform_ticks(axis[:ticks]) - ticks in (nothing, false) && return nothing + ticks in (:none, nothing, false) && return nothing # treat :native ticks as :auto ticks = ticks == :native ? :auto : ticks @@ -287,7 +287,7 @@ _transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.valu _transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2]) function get_minor_ticks(axis,ticks) - axis[:minorticks] in (nothing, false) && !axis[:minorgrid] && return nothing + axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing ticks = ticks[1] length(ticks) < 2 && return nothing From 80c01e74c67a53e46ce3df36c14b82c707c3f9ee Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 5 Mar 2019 10:34:05 +0100 Subject: [PATCH 125/230] plotly: fix yflip for `ticks = :none` --- src/backends/plotly.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 569e05e3..8beac943 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -186,11 +186,6 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot) ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis]) ax[:linecolor] = rgba_string(axis[:foreground_color_axis]) - # flip - if axis[:flip] - ax[:range] = reverse(ax[:range]) - end - # ticks if axis[:ticks] != :native ticks = get_ticks(axis) @@ -208,6 +203,10 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot) ax[:showgrid] = false end + # flip + if axis[:flip] + ax[:range] = reverse(ax[:range]) + end ax end From 2c8d51988b9e8332ebc978a8cc98623fabf18189 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 7 Mar 2019 19:04:18 +0100 Subject: [PATCH 126/230] support plotly mime type --- src/backends/plotlyjs.jl | 5 +++++ src/output.jl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 08e40762..83952c71 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -55,6 +55,11 @@ _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig( _show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf") _show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps") +function _show(io::IO, m::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) + show(io, m, plt.o) +end + + function write_temp_html(plt::Plot{PlotlyJSBackend}) filename = string(tempname(), ".html") savefig(plt, filename) diff --git a/src/output.jl b/src/output.jl index fd37c10e..27c7731e 100644 --- a/src/output.jl +++ b/src/output.jl @@ -189,7 +189,7 @@ end # for writing to io streams... first prepare, then callback for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml", "application/eps", "application/pdf", "application/postscript", - "application/x-tex") + "application/x-tex", "application/vnd.plotly.v1+json") @eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot) if haskey(io, :juno_plotsize) showjuno(io, m, plt) From 56525ced92cdfb31b04adc3e1d17e2d352056ac4 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 12 Mar 2019 12:59:19 +0100 Subject: [PATCH 127/230] also add plotly json mime to PlotlyBackend --- src/backends/plotly.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 8beac943..8d7a0f12 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -853,11 +853,16 @@ end # ---------------------------------------------------------------- - -function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend}) - write(io, html_head(plt) * html_body(plt)) +function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend}) + data = [] + for series in plot.series_list + append!(data, plotly_series(plot, series)) + end + layout = plotly_layout(plot) + JSON.print(io, Dict(:data => data, :layout => layout)) end + function _display(plt::Plot{PlotlyBackend}) standalone_html_window(plt) end From 79e978aac98d0803c73625829fff39cc0d7cbcef Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 12 Mar 2019 14:56:41 +0100 Subject: [PATCH 128/230] fix image axis limits --- src/backends/gr.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 27c6ae43..1dffd953 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -424,8 +424,8 @@ function gr_colorbar(sp::Subplot, clims, levels) (1000:1255)' elseif length(levels) > 1 min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels) - round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255) - else + round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255) + else Int32[1000, 1255] end GR.setscale(0) @@ -671,7 +671,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # calculate the colorbar limits once for a subplot clims = get_clims(sp) clevels = nothing - + draw_axes = sp[:framestyle] != :none # axes_2d = true for series in series_list(sp) @@ -693,7 +693,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) expand_extrema!(sp[:yaxis], y) data_lims = gr_xy_axislims(sp) end - + # color levels overwritten by the last relevant series hascolorbar(series) && (clevels = colorbar_levels(series, clims)) end @@ -744,7 +744,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.setlinewidth(sp.plt[:thickness_scaling]) if is3d(sp) - # TODO do we really need a different clims computation here from the one + # TODO do we really need a different clims computation here from the one # computed above using get_clims(sp)? zmin, zmax = gr_lims(zaxis, true) clims3d = sp[:clims] @@ -963,7 +963,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) st = series[:seriestype] # update the current stored gradient - if st in (:surface, :heatmap) || + if st in (:surface, :heatmap) || (st == :contour && series[:fillrange] !== nothing) gr_set_gradient(series[:fillcolor]) #, series[:fillalpha]) elseif st in (:contour, :wireframe) @@ -1048,7 +1048,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.setlinetype(gr_linetype[get_linestyle(series)]) GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) is_lc_black = let black=plot_color(:black) - plot_color(series[:linecolor]) in (black,[black]) + plot_color(series[:linecolor]) in (black,[black]) end if series[:fillrange] != nothing if series[:fillcolor] != series[:linecolor] && !is_lc_black @@ -1191,7 +1191,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif st == :image z = transpose_z(series, series[:z].surf, true)' - w, h = length(x), length(y) + w, h = size(z) xinds = sort(1:w, rev = xaxis[:flip]) yinds = sort(1:h, rev = yaxis[:flip]) z = z[xinds, yinds] From cab6ca3ef0890688b06a5abab4ac29fce90ec21a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 13 Mar 2019 13:40:05 +0100 Subject: [PATCH 129/230] default to radius 0 at center for polar plots --- src/axes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index 1b2f693b..c2784d5c 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -502,7 +502,7 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis) amin, amax = 0, 2pi elseif lims == :auto #widen max radius so ticks dont overlap with theta axis - amin, amax + 0.1 * abs(amax - amin) + 0, amax + 0.1 * abs(amax - amin) else amin, amax end From b21d98affd7c6dae3eb01fd598a3f37a744cb22a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 15 Mar 2019 15:13:57 +0100 Subject: [PATCH 130/230] switch to new PyCall API --- src/backends/pyplot.jl | 262 ++++++++++++++++++++--------------------- 1 file changed, 130 insertions(+), 132 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 972f22e0..9ea2efce 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -21,7 +21,7 @@ pyfont = PyPlot.pyimport("matplotlib.font_manager") pyticker = PyPlot.pyimport("matplotlib.ticker") pycmap = PyPlot.pyimport("matplotlib.cm") pynp = PyPlot.pyimport("numpy") -pynp["seterr"](invalid="ignore") +pynp."seterr"(invalid="ignore") pytransforms = PyPlot.pyimport("matplotlib.transforms") pycollections = PyPlot.pyimport("matplotlib.collections") pyart3d = PyPlot.art3D @@ -64,8 +64,8 @@ py_color(c::Colorant, α) = py_color(plot_color(c, α)) function py_colormap(grad::ColorGradient) pyvals = [(z, py_color(grad[z])) for z in grad.values] - cm = pycolors["LinearSegmentedColormap"][:from_list]("tmp", pyvals) - cm[:set_bad](color=(0,0,0,0.0), alpha=0.0) + cm = pycolors."LinearSegmentedColormap".from_list("tmp", pyvals) + cm.set_bad(color=(0,0,0,0.0), alpha=0.0) cm end py_colormap(c) = py_colormap(cgrad()) @@ -73,8 +73,8 @@ py_colormap(c) = py_colormap(cgrad()) function py_shading(c, z) cmap = py_colormap(c) - ls = pycolors["LightSource"](270,45) - ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft") + ls = pycolors."LightSource"(270,45) + ls.shade(z, cmap, vert_exag=0.1, blend_mode="soft") end # get the style (solid, dashed, etc) @@ -97,7 +97,7 @@ function py_marker(marker::Shape) mat[i,2] = y[i] end mat[n+1,:] = mat[1,:] - pypath["Path"](mat) + pypath."Path"(mat) end const _path_MOVETO = UInt8(1) @@ -182,7 +182,7 @@ end # end function get_locator_and_formatter(vals::AVec) - pyticker["FixedLocator"](1:length(vals)), pyticker["FixedFormatter"](vals) + pyticker."FixedLocator"(1:length(vals)), pyticker."FixedFormatter"(vals) end function add_pyfixedformatter(cbar, vals::AVec) @@ -204,7 +204,7 @@ end function py_mask_nans(z) # pynp["ma"][:masked_invalid](z))) - PyCall.pycall(pynp["ma"][:masked_invalid], Any, z) + PyCall.pycall(pynp."ma".masked_invalid, Any, z) # pynp["ma"][:masked_where](pynp["isnan"](z),z) end @@ -248,22 +248,22 @@ py_fillcolormap(series::Series) = py_colormap(series[:fillcolor]) # Figure utils -- F*** matplotlib for making me work so hard to figure this crap out # the drawing surface -py_canvas(fig) = fig[:canvas] +py_canvas(fig) = fig.canvas # the object controlling draw commands -py_renderer(fig) = py_canvas(fig)[:get_renderer]() +py_renderer(fig) = py_canvas(fig).get_renderer() # draw commands... paint the screen (probably updating internals too) -py_drawfig(fig) = fig[:draw](py_renderer(fig)) +py_drawfig(fig) = fig.draw(py_renderer(fig)) # py_drawax(ax) = ax[:draw](py_renderer(ax[:get_figure]())) # get a vector [left, right, bottom, top] in PyPlot coords (origin is bottom-left!) -py_extents(obj) = obj[:get_window_extent]()[:get_points]() +py_extents(obj) = obj.get_window_extent().get_points() # compute a bounding box (with origin top-left), however pyplot gives coords with origin bottom-left function py_bbox(obj) - fl, fr, fb, ft = py_extents(obj[:get_figure]()) + fl, fr, fb, ft = py_extents(obj.get_figure()) l, r, b, t = py_extents(obj) BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px) end @@ -279,13 +279,13 @@ end # bounding box: union of axis tick labels function py_bbox_ticks(ax, letter) - labels = ax[Symbol("get_"*letter*"ticklabels")]() + labels = getproperty(ax, Symbol("get_"*letter*"ticklabels"))() py_bbox(labels) end # bounding box: axis guide function py_bbox_axislabel(ax, letter) - pyaxis_label = ax[Symbol("get_"*letter*"axis")]()[:label] + pyaxis_label = getproperty(ax, Symbol("get_"*letter*"axis"))().label py_bbox(pyaxis_label) end @@ -301,7 +301,7 @@ end function py_bbox_title(ax) bb = defaultbox for s in (:title, :_left_title, :_right_title) - bb = bb + py_bbox(ax[s]) + bb = bb + py_bbox(getproperty(ax, s)) end bb end @@ -339,7 +339,7 @@ function py_init_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend}) proj = (proj in (nothing,:none) ? nothing : string(proj)) # add a new axis, and force it to create a new one by setting a distinct label - ax = fig[:add_axes]( + ax = fig.add_axes( [0,0,1,1], label = string(gensym()), projection = proj @@ -440,7 +440,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) # push!(handles, handle) # else for (i, rng) in enumerate(iter_segments(series)) - handle = ax[:plot]((arg[rng] for arg in xyargs)...; + handle = ax.plot((arg[rng] for arg in xyargs)...; label = i == 1 ? series[:label] : "", zorder = series[:series_plotindex], color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)), @@ -468,7 +468,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) :linestyle => py_linestyle(st, get_linestyle(series)), ) add_arrows(x, y) do xyprev, xy - ax[:annotate]("", + ax.annotate("", xytext = (0.001xyprev[1] + 0.999xy[1], 0.001xyprev[2] + 0.999xy[2]), xy = xy, arrowprops = arrowprops, @@ -514,7 +514,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) for i=1:length(y) extrakw[:c] = _cycle(markercolor, i) - push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i); + push!(handle, ax.scatter(_cycle(x,i), _cycle(y,i); label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = py_marker(_cycle(shapes,i)), @@ -553,7 +553,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) continue end - push!(handle, ax[:scatter](cur_x_list, cur_y_list; + push!(handle, ax.scatter(cur_x_list, cur_y_list; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = prev_marker, @@ -574,7 +574,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end if !isempty(cur_color_list) - push!(handle, ax[:scatter](cur_x_list, cur_y_list; + push!(handle, ax.scatter(cur_x_list, cur_y_list; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = prev_marker, @@ -589,7 +589,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) push!(handles, handle) else # do a normal scatter plot - handle = ax[:scatter](xyargs...; + handle = ax.scatter(xyargs...; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = py_marker(series[:markershape]), @@ -603,7 +603,7 @@ 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], @@ -635,7 +635,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end # contour lines - handle = ax[:contour](x, y, z, levelargs...; + handle = ax.contour(x, y, z, levelargs...; label = series[:label], zorder = series[:series_plotindex], linewidths = py_thickness_scale(plt, series[:linewidth]), @@ -643,13 +643,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) extrakw... ) if series[:contour_labels] == true - PyPlot.clabel(handle, handle[:levels]) + PyPlot.clabel(handle, handle.levels) end push!(handles, handle) # contour fills if series[:fillrange] != nothing - handle = ax[:contourf](x, y, z, levelargs...; + handle = ax.contourf(x, y, z, levelargs...; label = series[:label], zorder = series[:series_plotindex] + 0.5, extrakw... @@ -675,7 +675,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) extrakw[:cmap] = py_fillcolormap(series) end end - handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z; + handle = getproperty(ax, st == :surface ? :plot_surface : :plot_wireframe)(x, y, z; label = series[:label], zorder = series[:series_plotindex], rstride = series[:stride][1], @@ -690,7 +690,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) if series[:contours] for (zdir,mat) in (("x",x), ("y",y), ("z",z)) offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) - handle = ax[:contourf](x, y, z, levelargs...; + handle = ax.contourf(x, y, z, levelargs...; zdir = zdir, cmap = py_fillcolormap(series), offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane @@ -702,7 +702,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) elseif typeof(z) <: AbstractVector # tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots) - handle = ax[:plot_trisurf](x, y, z; + handle = ax.plot_trisurf(x, y, z; label = series[:label], zorder = series[:series_plotindex], cmap = py_fillcolormap(series), @@ -727,7 +727,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) else z # hopefully it's in a data format that will "just work" with imshow end - handle = ax[:imshow](z; + handle = ax.imshow(z; zorder = series[:series_plotindex], cmap = py_colormap(cgrad([:black, :white])), vmin = 0.0, @@ -737,7 +737,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) push!(handles, handle) # expand extrema... handle is AxesImage object - xmin, xmax, ymax, ymin = handle[:get_extent]() + xmin, xmax, ymax, ymin = handle.get_extent() expand_extrema!(sp, xmin, xmax, ymin, ymax) # sp[:yaxis].series[:flip] = true end @@ -752,7 +752,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) discrete_colorbar_values = dvals end - handle = ax[:pcolormesh](x, y, py_mask_nans(z); + handle = ax.pcolormesh(x, y, py_mask_nans(z); label = series[:label], zorder = series[:series_plotindex], cmap = py_fillcolormap(series), @@ -767,8 +767,8 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) handle = [] for (i, rng) in enumerate(iter_segments(series)) if length(rng) > 1 - path = pypath["Path"](hcat(x[rng], y[rng])) - patches = pypatches["PathPatch"]( + path = pypath."Path"(hcat(x[rng], y[rng])) + patches = pypatches."PathPatch"( path; label = series[:label], zorder = series[:series_plotindex], @@ -778,14 +778,14 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) linestyle = py_linestyle(st, get_linestyle(series, i)), fill = true ) - push!(handle, ax[:add_patch](patches)) + push!(handle, ax.add_patch(patches)) end end push!(handles, handle) end if st == :pie - handle = ax[:pie](y; + handle = ax.pie(y; # colors = # a vector of colors? labels = pie_labels(sp, series) )[1] @@ -820,7 +820,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) dim1, _cycle(fillrange[1], rng), _cycle(fillrange[2], rng) end - handle = ax[f](args..., trues(n), false, py_fillstepstyle(st); + handle = getproperty(ax, f)(args..., trues(n), false, py_fillstepstyle(st); zorder = series[:series_plotindex], facecolor = py_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)), linewidths = 0 @@ -841,27 +841,27 @@ end function py_set_lims(ax, axis::Axis) letter = axis[:letter] lfrom, lto = axis_limits(axis) - ax[Symbol("set_", letter, "lim")](lfrom, lto) + getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto) end function py_set_ticks(ax, ticks, letter) ticks == :auto && return - axis = ax[Symbol(letter,"axis")] + axis = getproperty(ax, Symbol(letter,"axis")) if ticks == :none || ticks == nothing || ticks == false kw = KW() for dir in (:top,:bottom,:left,:right) kw[dir] = kw[Symbol(:label,dir)] = false end - axis[:set_tick_params](;which="both", kw...) + axis.set_tick_params(;which="both", kw...) return end ttype = ticksType(ticks) if ttype == :ticks - axis[:set_ticks](ticks) + axis.set_ticks(ticks) elseif ttype == :ticks_and_labels - axis[:set_ticks](ticks[1]) - axis[:set_ticklabels](ticks[2]) + axis.set_ticks(ticks[1]) + axis.set_ticklabels(ticks[2]) else error("Invalid input for $(letter)ticks: $ticks") end @@ -891,7 +891,7 @@ function py_set_scale(ax, axis::Axis) scale = axis[:scale] letter = axis[:letter] scale in supported_scales() || return @warn("Unhandled scale value in pyplot: $scale") - func = ax[Symbol("set_", letter, "scale")] + func = getproperty(ax, Symbol("set_", letter, "scale")) kw = KW() arg = if scale == :identity "linear" @@ -911,16 +911,16 @@ end function py_set_axis_colors(sp, ax, a::Axis) - for (loc, spine) in ax[:spines] - spine[:set_color](py_color(a[:foreground_color_border])) + for (loc, spine) in ax.spines + spine.set_color(py_color(a[:foreground_color_border])) end axissym = Symbol(a[:letter], :axis) - if haskey(ax, axissym) + if PyCall.hasproperty(ax, axissym) tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis]) - ax[:tick_params](axis=string(a[:letter]), which="both", + ax.tick_params(axis=string(a[:letter]), which="both", colors=tickcolor, labelcolor=py_color(a[:tickfontcolor])) - ax[axissym][:label][:set_color](py_color(a[:guidefontcolor])) + getproperty(ax, axissym).label.set_color(py_color(a[:guidefontcolor])) end end @@ -932,14 +932,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # update the fig w, h = plt[:size] fig = plt.o - fig[:clear]() + fig.clear() dpi = plt[:dpi] - fig[:set_size_inches](w/DPI, h/DPI, forward = true) - fig[set_facecolor_sym](py_color(plt[:background_color_outside])) - fig[:set_dpi](plt[:dpi]) + fig.set_size_inches(w/DPI, h/DPI, forward = true) + getproperty(fig, set_facecolor_sym)(py_color(plt[:background_color_outside])) + fig.set_dpi(plt[:dpi]) # resize the window - PyPlot.plt[:get_current_fig_manager]()[:resize](w, h) + PyPlot.plt.get_current_fig_manager().resize(w, h) # initialize subplots for sp in plt.subplots @@ -973,10 +973,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) else :title end - ax[func][:set_text](sp[:title]) - ax[func][:set_fontsize](py_thickness_scale(plt, sp[:titlefontsize])) - ax[func][:set_family](sp[:titlefontfamily]) - ax[func][:set_color](py_color(sp[:titlefontcolor])) + getproperty(ax, func).set_text(sp[:title]) + getproperty(ax, func).set_fontsize(py_thickness_scale(plt, sp[:titlefontsize])) + getproperty(ax, func).set_family(sp[:titlefontfamily]) + getproperty(ax, func).set_color(py_color(sp[:titlefontcolor])) # ax[:set_title](sp[:title], loc = loc) end @@ -996,7 +996,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) kw[:boundaries] = vcat(0, kw[:values] + 0.5) elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z)) cmin, cmax = get_clims(sp) - norm = pycolors[:Normalize](vmin = cmin, vmax = cmax) + norm = pycolors.Normalize(vmin = cmin, vmax = cmax) f = if colorbar_series[:line_z] != nothing py_linecolormap elseif colorbar_series[:fill_z] != nothing @@ -1004,21 +1004,21 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) else py_markercolormap end - cmap = pycmap[:ScalarMappable](norm = norm, cmap = f(colorbar_series)) - cmap[:set_array]([]) + cmap = pycmap.ScalarMappable(norm = norm, cmap = f(colorbar_series)) + cmap.set_array([]) handle = cmap end # create and store the colorbar object (handle) and the axis that it is drawn on. # note: the colorbar axis is positioned independently from the subplot axis fig = plt.o - cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym())) - cb = fig[:colorbar](handle; cax = cbax, kw...) - cb[:set_label](sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor])) - for lab in cb[:ax][:yaxis][:get_ticklabels]() - lab[:set_fontsize](py_thickness_scale(plt, sp[:yaxis][:tickfontsize])) - lab[:set_family](sp[:yaxis][:tickfontfamily]) - lab[:set_color](py_color(sp[:yaxis][:tickfontcolor])) + cbax = fig.add_axes([0.8,0.1,0.03,0.8], label = string(gensym())) + cb = fig.colorbar(handle; cax = cbax, kw...) + cb.set_label(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor])) + for lab in cb.ax.yaxis.get_ticklabels() + lab.set_fontsize(py_thickness_scale(plt, sp[:yaxis][:tickfontsize])) + lab.set_family(sp[:yaxis][:tickfontfamily]) + lab.set_color(py_color(sp[:yaxis][:tickfontcolor])) end sp.attr[:cbar_handle] = cb sp.attr[:cbar_ax] = cbax @@ -1026,28 +1026,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # framestyle if !ispolar(sp) && !is3d(sp) - ax[:spines]["left"][:set_linewidth](py_thickness_scale(plt, 1)) - ax[:spines]["bottom"][:set_linewidth](py_thickness_scale(plt, 1)) + ax.spines["left"].set_linewidth(py_thickness_scale(plt, 1)) + ax.spines["bottom"].set_linewidth(py_thickness_scale(plt, 1)) if sp[:framestyle] == :semi intensity = 0.5 - ax[:spines]["right"][:set_alpha](intensity) - ax[:spines]["top"][:set_alpha](intensity) - ax[:spines]["right"][:set_linewidth](py_thickness_scale(plt, intensity)) - ax[:spines]["top"][:set_linewidth](py_thickness_scale(plt, intensity)) + ax.spines["right"].set_alpha(intensity) + ax.spines["top"].set_alpha(intensity) + ax.spines["right"].set_linewidth(py_thickness_scale(plt, intensity)) + ax.spines["top"].set_linewidth(py_thickness_scale(plt, intensity)) elseif sp[:framestyle] in (:axes, :origin) - ax[:spines]["right"][:set_visible](false) - ax[:spines]["top"][:set_visible](false) + ax.spines["right"].set_visible(false) + ax.spines["top"].set_visible(false) if sp[:framestyle] == :origin - ax[:spines]["bottom"][:set_position]("zero") - ax[:spines]["left"][:set_position]("zero") + ax.spines["bottom"].set_position("zero") + ax.spines["left"].set_position("zero") end elseif sp[:framestyle] in (:grid, :none, :zerolines) - for (loc, spine) in ax[:spines] - spine[:set_visible](false) + for (loc, spine) in ax.spines + spine.set_visible(false) end if sp[:framestyle] == :zerolines - ax[:axhline](y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) - ax[:axvline](x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) + ax.axhline(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) + ax.axvline(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) end end end @@ -1055,22 +1055,22 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # axis attributes for letter in (:x, :y, :z) axissym = Symbol(letter, :axis) - haskey(ax, axissym) || continue + PyCall.hasproperty(ax, axissym) || continue axis = sp[axissym] - pyaxis = ax[axissym] + pyaxis = getproperty(ax, axissym) if axis[:mirror] && letter != :z pos = letter == :x ? "top" : "right" - pyaxis[:set_label_position](pos) # the guides - pyaxis[:set_ticks_position]("both") # the hash marks - pyaxis[Symbol(:tick_, pos)]() # the tick labels + pyaxis.set_label_position(pos) # the guides + pyaxis.set_ticks_position("both") # the hash marks + getproperty(pyaxis, Symbol(:tick_, pos))() # the tick labels end if axis[:guide_position] != :auto && letter != :z - pyaxis[:set_label_position](axis[:guide_position]) + pyaxis.set_label_position(axis[:guide_position]) end py_set_scale(ax, axis) axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing if ispolar(sp) && letter == :y - ax[:set_rlabel_position](90) + ax.set_rlabel_position(90) end ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis) # don't show the 0 tick label for the origin framestyle @@ -1078,28 +1078,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) ticks[2][ticks[1] .== 0] .= "" end axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing - pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in") - ax[Symbol("set_", letter, "label")](axis[:guide]) + pyaxis.set_tick_params(direction = axis[:tick_direction] == :out ? "out" : "in") + getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide]) if get(axis.plotattributes, :flip, false) - ax[Symbol("invert_", letter, "axis")]() + getproperty(ax, Symbol("invert_", letter, "axis"))() end - pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize])) - pyaxis[:label][:set_family](axis[:guidefontfamily]) - for lab in ax[Symbol("get_", letter, "ticklabels")]() - lab[:set_fontsize](py_thickness_scale(plt, axis[:tickfontsize])) - lab[:set_family](axis[:tickfontfamily]) - lab[:set_rotation](axis[:rotation]) + pyaxis.label.set_fontsize(py_thickness_scale(plt, axis[:guidefontsize])) + pyaxis.label.set_family(axis[:guidefontfamily]) + for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))() + lab.set_fontsize(py_thickness_scale(plt, axis[:tickfontsize])) + lab.set_family(axis[:tickfontfamily]) + lab.set_rotation(axis[:rotation]) end if axis[:grid] && !(ticks in (:none, nothing, false)) fgcolor = py_color(axis[:foreground_color_grid]) - pyaxis[:grid](true, + pyaxis.grid(true, color = fgcolor, linestyle = py_linestyle(:line, axis[:gridstyle]), linewidth = py_thickness_scale(plt, axis[:gridlinewidth]), alpha = axis[:gridalpha]) - ax[:set_axisbelow](true) + ax.set_axisbelow(true) else - pyaxis[:grid](false) + pyaxis.grid(false) end py_set_axis_colors(sp, ax, axis) end @@ -1109,48 +1109,48 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) kw = KW() for dir in (:top, :bottom) if ispolar(sp) - ax[:spines]["polar"][:set_visible](false) + ax.spines."polar".set_visible(false) else - ax[:spines][string(dir)][:set_visible](false) + getproperty(ax.spines, dir).set_visible(false) end kw[dir] = kw[Symbol(:label,dir)] = false end - ax[:xaxis][:set_tick_params](; which="both", kw...) + ax.xaxis.set_tick_params(; which="both", kw...) end if !sp[:yaxis][:showaxis] kw = KW() for dir in (:left, :right) if !ispolar(sp) - ax[:spines][string(dir)][:set_visible](false) + getproperty(ax.spines, dir).set_visible(false) end kw[dir] = kw[Symbol(:label,dir)] = false end - ax[:yaxis][:set_tick_params](; which="both", kw...) + ax.yaxis.set_tick_params(; which="both", kw...) end # aspect ratio aratio = sp[:aspect_ratio] if aratio != :none - ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") + ax.set_aspect(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") end #camera/view angle if is3d(sp) #convert azimuthal to match GR behaviour #view_init(elevation, azimuthal) so reverse :camera args - ax[:view_init]((sp[:camera].-(90,0))[end:-1:1]...) + ax.view_init((sp[:camera].-(90,0))[end:-1:1]...) end # legend py_add_legend(plt, sp, ax) # this sets the bg color inside the grid - ax[set_facecolor_sym](py_color(sp[:background_color_inside])) + getproperty(ax, set_facecolor_sym)(py_color(sp[:background_color_inside])) # link axes x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o - ax != x_ax_link && ax[:get_shared_x_axes]()[:join](ax, sp[:xaxis].sps[1].o) - ax != y_ax_link && ax[:get_shared_y_axes]()[:join](ax, sp[:yaxis].sps[1].o) + ax != x_ax_link && ax.get_shared_x_axes().join(ax, sp[:xaxis].sps[1].o) + ax != y_ax_link && ax.get_shared_y_axes().join(ax, sp[:yaxis].sps[1].o) end py_drawfig(fig) end @@ -1181,7 +1181,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend}) # optionally add the width of colorbar labels and colorbar to rightpad if haskey(sp.attr, :cbar_ax) - bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]()) + bb = py_bbox(sp.attr[:cbar_handle].ax.get_yticklabels()) sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px) rightpad = rightpad + sp.attr[:cbar_width] end @@ -1202,13 +1202,13 @@ end function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val) ax = sp.o - ax[:annotate](val, xy = (x,y), zorder = 999) + ax.annotate(val, xy = (x,y), zorder = 999) end function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText) ax = sp.o - ax[:annotate](val.str, + ax.annotate(val.str, xy = (x,y), family = val.font.family, color = py_color(val.font.color), @@ -1244,14 +1244,14 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) if should_add_to_legend(series) # add a line/marker and a label push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing - pypatches[:Patch]( + pypatches.Patch( edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)), facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)), 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) - PyPlot.plt[:Line2D]((0,1),(0,0), + PyPlot.plt.Line2D((0,1),(0,0), color = py_color(get_linecolor(series, clims), get_linealpha(series)), linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)), linestyle = py_linestyle(:path, get_linestyle(series)), @@ -1268,7 +1268,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) # if anything was added, call ax.legend and set the colors if !isempty(handles) - leg = ax[:legend](handles, + leg = ax.legend(handles, labels, loc = get(_pyplot_legend_pos, leg, "best"), scatterpoints = 1, @@ -1277,13 +1277,13 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) edgecolor = py_color(sp[:foreground_color_legend]), framealpha = alpha(plot_color(sp[:background_color_legend])), ) - frame = leg[:get_frame]() - frame[:set_linewidth](py_thickness_scale(plt, 1)) - leg[:set_zorder](1000) - sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle]) + frame = leg.get_frame() + frame.set_linewidth(py_thickness_scale(plt, 1)) + leg.set_zorder(1000) + sp[:legendtitle] != nothing && leg.set_title(sp[:legendtitle]) - for txt in leg[:get_texts]() - PyPlot.plt[:setp](txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily]) + for txt in leg.get_texts() + PyPlot.plt.setp(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily]) end end end @@ -1301,7 +1301,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend}) figw, figh = sp.plt[:size] figw, figh = figw*px, figh*px pcts = bbox_to_pcts(sp.plotarea, figw, figh) - ax[:set_position](pcts) + ax.set_position(pcts) # set the cbar position if there is one if haskey(sp.attr, :cbar_ax) @@ -1311,7 +1311,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend}) has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7) cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm)) pcts = bbox_to_pcts(cb_bbox, figw, figh) - sp.attr[:cbar_ax][:set_position](pcts) + sp.attr[:cbar_ax].set_position(pcts) end end PyPlot.draw() @@ -1320,9 +1320,7 @@ end # ----------------------------------------------------------------- # display/output -function _display(plt::Plot{PyPlotBackend}) - isdefined(PyCall, :_setproperty!) ? plt.o.show() : plot.o[:show]() -end +_display(plt::Plot{PyPlotBackend}) = plt.o.show() @@ -1340,16 +1338,16 @@ const _pyplot_mimeformats = Dict( for (mime, fmt) in _pyplot_mimeformats @eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend}) fig = plt.o - fig[:canvas][:print_figure]( + fig.canvas.print_figure( io, format=$fmt, # bbox_inches = "tight", # figsize = map(px2inch, plt[:size]), - facecolor = fig[:get_facecolor](), + facecolor = fig.get_facecolor(), edgecolor = "none", dpi = plt[:dpi] ) end end -closeall(::PyPlotBackend) = PyPlot.plt[:close]("all") +closeall(::PyPlotBackend) = PyPlot.plt.close("all") From b79ea119ea7de7519442464085d93317cc2990f4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 15 Mar 2019 15:15:59 +0100 Subject: [PATCH 131/230] use a.''foo'' instead of a.foo --- src/backends/pyplot.jl | 204 ++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 9ea2efce..aa20d3d1 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -64,8 +64,8 @@ py_color(c::Colorant, α) = py_color(plot_color(c, α)) function py_colormap(grad::ColorGradient) pyvals = [(z, py_color(grad[z])) for z in grad.values] - cm = pycolors."LinearSegmentedColormap".from_list("tmp", pyvals) - cm.set_bad(color=(0,0,0,0.0), alpha=0.0) + cm = pycolors."LinearSegmentedColormap"."from_list"("tmp", pyvals) + cm."set_bad"(color=(0,0,0,0.0), alpha=0.0) cm end py_colormap(c) = py_colormap(cgrad()) @@ -74,7 +74,7 @@ py_colormap(c) = py_colormap(cgrad()) function py_shading(c, z) cmap = py_colormap(c) ls = pycolors."LightSource"(270,45) - ls.shade(z, cmap, vert_exag=0.1, blend_mode="soft") + ls."shade"(z, cmap, vert_exag=0.1, blend_mode="soft") end # get the style (solid, dashed, etc) @@ -204,7 +204,7 @@ end function py_mask_nans(z) # pynp["ma"][:masked_invalid](z))) - PyCall.pycall(pynp."ma".masked_invalid, Any, z) + PyCall.pycall(pynp."ma"."masked_invalid", Any, z) # pynp["ma"][:masked_where](pynp["isnan"](z),z) end @@ -248,22 +248,22 @@ py_fillcolormap(series::Series) = py_colormap(series[:fillcolor]) # Figure utils -- F*** matplotlib for making me work so hard to figure this crap out # the drawing surface -py_canvas(fig) = fig.canvas +py_canvas(fig) = fig."canvas" # the object controlling draw commands -py_renderer(fig) = py_canvas(fig).get_renderer() +py_renderer(fig) = py_canvas(fig)."get_renderer"() # draw commands... paint the screen (probably updating internals too) -py_drawfig(fig) = fig.draw(py_renderer(fig)) +py_drawfig(fig) = fig."draw"(py_renderer(fig)) # py_drawax(ax) = ax[:draw](py_renderer(ax[:get_figure]())) # get a vector [left, right, bottom, top] in PyPlot coords (origin is bottom-left!) -py_extents(obj) = obj.get_window_extent().get_points() +py_extents(obj) = obj."get_window_extent"()."get_points"() # compute a bounding box (with origin top-left), however pyplot gives coords with origin bottom-left function py_bbox(obj) - fl, fr, fb, ft = py_extents(obj.get_figure()) + fl, fr, fb, ft = py_extents(obj."get_figure"()) l, r, b, t = py_extents(obj) BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px) end @@ -339,7 +339,7 @@ function py_init_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend}) proj = (proj in (nothing,:none) ? nothing : string(proj)) # add a new axis, and force it to create a new one by setting a distinct label - ax = fig.add_axes( + ax = fig."add_axes"( [0,0,1,1], label = string(gensym()), projection = proj @@ -440,7 +440,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) # push!(handles, handle) # else for (i, rng) in enumerate(iter_segments(series)) - handle = ax.plot((arg[rng] for arg in xyargs)...; + handle = ax."plot"((arg[rng] for arg in xyargs)...; label = i == 1 ? series[:label] : "", zorder = series[:series_plotindex], color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)), @@ -468,7 +468,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) :linestyle => py_linestyle(st, get_linestyle(series)), ) add_arrows(x, y) do xyprev, xy - ax.annotate("", + ax."annotate"("", xytext = (0.001xyprev[1] + 0.999xy[1], 0.001xyprev[2] + 0.999xy[2]), xy = xy, arrowprops = arrowprops, @@ -514,7 +514,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) for i=1:length(y) extrakw[:c] = _cycle(markercolor, i) - push!(handle, ax.scatter(_cycle(x,i), _cycle(y,i); + push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i); label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = py_marker(_cycle(shapes,i)), @@ -553,7 +553,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) continue end - push!(handle, ax.scatter(cur_x_list, cur_y_list; + push!(handle, ax."scatter"(cur_x_list, cur_y_list; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = prev_marker, @@ -574,7 +574,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end if !isempty(cur_color_list) - push!(handle, ax.scatter(cur_x_list, cur_y_list; + push!(handle, ax."scatter"(cur_x_list, cur_y_list; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = prev_marker, @@ -589,7 +589,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) push!(handles, handle) else # do a normal scatter plot - handle = ax.scatter(xyargs...; + handle = ax."scatter"(xyargs...; label = series[:label], zorder = series[:series_plotindex] + 0.5, marker = py_marker(series[:markershape]), @@ -603,7 +603,7 @@ 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], @@ -635,7 +635,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end # contour lines - handle = ax.contour(x, y, z, levelargs...; + handle = ax."contour"(x, y, z, levelargs...; label = series[:label], zorder = series[:series_plotindex], linewidths = py_thickness_scale(plt, series[:linewidth]), @@ -643,13 +643,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) extrakw... ) if series[:contour_labels] == true - PyPlot.clabel(handle, handle.levels) + PyPlot."clabel"(handle, handle.levels) end push!(handles, handle) # contour fills if series[:fillrange] != nothing - handle = ax.contourf(x, y, z, levelargs...; + handle = ax."contourf"(x, y, z, levelargs...; label = series[:label], zorder = series[:series_plotindex] + 0.5, extrakw... @@ -690,7 +690,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) if series[:contours] for (zdir,mat) in (("x",x), ("y",y), ("z",z)) offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) - handle = ax.contourf(x, y, z, levelargs...; + handle = ax."contourf"(x, y, z, levelargs...; zdir = zdir, cmap = py_fillcolormap(series), offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane @@ -702,7 +702,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) elseif typeof(z) <: AbstractVector # tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots) - handle = ax.plot_trisurf(x, y, z; + handle = ax."plot_trisurf"(x, y, z; label = series[:label], zorder = series[:series_plotindex], cmap = py_fillcolormap(series), @@ -727,7 +727,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) else z # hopefully it's in a data format that will "just work" with imshow end - handle = ax.imshow(z; + handle = ax."imshow"(z; zorder = series[:series_plotindex], cmap = py_colormap(cgrad([:black, :white])), vmin = 0.0, @@ -737,7 +737,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) push!(handles, handle) # expand extrema... handle is AxesImage object - xmin, xmax, ymax, ymin = handle.get_extent() + xmin, xmax, ymax, ymin = handle."get_extent"() expand_extrema!(sp, xmin, xmax, ymin, ymax) # sp[:yaxis].series[:flip] = true end @@ -752,7 +752,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) discrete_colorbar_values = dvals end - handle = ax.pcolormesh(x, y, py_mask_nans(z); + handle = ax."pcolormesh"(x, y, py_mask_nans(z); label = series[:label], zorder = series[:series_plotindex], cmap = py_fillcolormap(series), @@ -778,14 +778,14 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) linestyle = py_linestyle(st, get_linestyle(series, i)), fill = true ) - push!(handle, ax.add_patch(patches)) + push!(handle, ax."add_patch"(patches)) end end push!(handles, handle) end if st == :pie - handle = ax.pie(y; + handle = ax."pie"(y; # colors = # a vector of colors? labels = pie_labels(sp, series) )[1] @@ -852,16 +852,16 @@ function py_set_ticks(ax, ticks, letter) for dir in (:top,:bottom,:left,:right) kw[dir] = kw[Symbol(:label,dir)] = false end - axis.set_tick_params(;which="both", kw...) + axis."set_tick_params"(;which="both", kw...) return end ttype = ticksType(ticks) if ttype == :ticks - axis.set_ticks(ticks) + axis."set_ticks"(ticks) elseif ttype == :ticks_and_labels - axis.set_ticks(ticks[1]) - axis.set_ticklabels(ticks[2]) + axis."set_ticks"(ticks[1]) + axis."set_ticklabels"(ticks[2]) else error("Invalid input for $(letter)ticks: $ticks") end @@ -912,12 +912,12 @@ end function py_set_axis_colors(sp, ax, a::Axis) for (loc, spine) in ax.spines - spine.set_color(py_color(a[:foreground_color_border])) + spine."set_color"(py_color(a[:foreground_color_border])) end axissym = Symbol(a[:letter], :axis) if PyCall.hasproperty(ax, axissym) tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis]) - ax.tick_params(axis=string(a[:letter]), which="both", + ax."tick_params"(axis=string(a[:letter]), which="both", colors=tickcolor, labelcolor=py_color(a[:tickfontcolor])) getproperty(ax, axissym).label.set_color(py_color(a[:guidefontcolor])) @@ -932,14 +932,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # update the fig w, h = plt[:size] fig = plt.o - fig.clear() + fig."clear"() dpi = plt[:dpi] - fig.set_size_inches(w/DPI, h/DPI, forward = true) + fig."set_size_inches"(w/DPI, h/DPI, forward = true) getproperty(fig, set_facecolor_sym)(py_color(plt[:background_color_outside])) - fig.set_dpi(plt[:dpi]) + fig."set_dpi"(plt[:dpi]) # resize the window - PyPlot.plt.get_current_fig_manager().resize(w, h) + PyPlot.plt."get_current_fig_manager"().resize(w, h) # initialize subplots for sp in plt.subplots @@ -973,10 +973,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) else :title end - getproperty(ax, func).set_text(sp[:title]) - getproperty(ax, func).set_fontsize(py_thickness_scale(plt, sp[:titlefontsize])) - getproperty(ax, func).set_family(sp[:titlefontfamily]) - getproperty(ax, func).set_color(py_color(sp[:titlefontcolor])) + getproperty(ax, func)."set_text"(sp[:title]) + getproperty(ax, func)."set_fontsize"(py_thickness_scale(plt, sp[:titlefontsize])) + getproperty(ax, func)."set_family"(sp[:titlefontfamily]) + getproperty(ax, func)."set_color"(py_color(sp[:titlefontcolor])) # ax[:set_title](sp[:title], loc = loc) end @@ -996,7 +996,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) kw[:boundaries] = vcat(0, kw[:values] + 0.5) elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z)) cmin, cmax = get_clims(sp) - norm = pycolors.Normalize(vmin = cmin, vmax = cmax) + norm = pycolors."Normalize"(vmin = cmin, vmax = cmax) f = if colorbar_series[:line_z] != nothing py_linecolormap elseif colorbar_series[:fill_z] != nothing @@ -1004,21 +1004,21 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) else py_markercolormap end - cmap = pycmap.ScalarMappable(norm = norm, cmap = f(colorbar_series)) - cmap.set_array([]) + cmap = pycmap."ScalarMappable"(norm = norm, cmap = f(colorbar_series)) + cmap."set_array"([]) handle = cmap end # create and store the colorbar object (handle) and the axis that it is drawn on. # note: the colorbar axis is positioned independently from the subplot axis fig = plt.o - cbax = fig.add_axes([0.8,0.1,0.03,0.8], label = string(gensym())) - cb = fig.colorbar(handle; cax = cbax, kw...) - cb.set_label(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor])) - for lab in cb.ax.yaxis.get_ticklabels() - lab.set_fontsize(py_thickness_scale(plt, sp[:yaxis][:tickfontsize])) - lab.set_family(sp[:yaxis][:tickfontfamily]) - lab.set_color(py_color(sp[:yaxis][:tickfontcolor])) + cbax = fig."add_axes"([0.8,0.1,0.03,0.8], label = string(gensym())) + cb = fig."colorbar"(handle; cax = cbax, kw...) + cb."set_label"(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor])) + for lab in cb."ax"."yaxis"."get_ticklabels"() + lab."set_fontsize"(py_thickness_scale(plt, sp[:yaxis][:tickfontsize])) + lab."set_family"(sp[:yaxis][:tickfontfamily]) + lab."set_color"(py_color(sp[:yaxis][:tickfontcolor])) end sp.attr[:cbar_handle] = cb sp.attr[:cbar_ax] = cbax @@ -1026,28 +1026,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # framestyle if !ispolar(sp) && !is3d(sp) - ax.spines["left"].set_linewidth(py_thickness_scale(plt, 1)) - ax.spines["bottom"].set_linewidth(py_thickness_scale(plt, 1)) + ax.spines["left"]."set_linewidth"(py_thickness_scale(plt, 1)) + ax.spines["bottom"]."set_linewidth"(py_thickness_scale(plt, 1)) if sp[:framestyle] == :semi intensity = 0.5 - ax.spines["right"].set_alpha(intensity) - ax.spines["top"].set_alpha(intensity) - ax.spines["right"].set_linewidth(py_thickness_scale(plt, intensity)) - ax.spines["top"].set_linewidth(py_thickness_scale(plt, intensity)) + ax.spines["right"]."set_alpha"(intensity) + ax.spines["top"]."set_alpha"(intensity) + ax.spines["right"]."set_linewidth"(py_thickness_scale(plt, intensity)) + ax.spines["top"]."set_linewidth"(py_thickness_scale(plt, intensity)) elseif sp[:framestyle] in (:axes, :origin) - ax.spines["right"].set_visible(false) - ax.spines["top"].set_visible(false) + ax.spines["right"]."set_visible"(false) + ax.spines["top"]."set_visible"(false) if sp[:framestyle] == :origin - ax.spines["bottom"].set_position("zero") - ax.spines["left"].set_position("zero") + ax.spines["bottom"]."set_position"("zero") + ax.spines["left"]."set_position"("zero") end elseif sp[:framestyle] in (:grid, :none, :zerolines) for (loc, spine) in ax.spines - spine.set_visible(false) + spine."set_visible"(false) end if sp[:framestyle] == :zerolines - ax.axhline(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) - ax.axvline(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) + ax."axhline"(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) + ax."axvline"(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75)) end end end @@ -1060,17 +1060,17 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) pyaxis = getproperty(ax, axissym) if axis[:mirror] && letter != :z pos = letter == :x ? "top" : "right" - pyaxis.set_label_position(pos) # the guides - pyaxis.set_ticks_position("both") # the hash marks + pyaxis."set_label_position"(pos) # the guides + pyaxis."set_ticks_position"("both") # the hash marks getproperty(pyaxis, Symbol(:tick_, pos))() # the tick labels end if axis[:guide_position] != :auto && letter != :z - pyaxis.set_label_position(axis[:guide_position]) + pyaxis."set_label_position"(axis[:guide_position]) end py_set_scale(ax, axis) axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing if ispolar(sp) && letter == :y - ax.set_rlabel_position(90) + ax."set_rlabel_position"(90) end ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis) # don't show the 0 tick label for the origin framestyle @@ -1078,28 +1078,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) ticks[2][ticks[1] .== 0] .= "" end axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing - pyaxis.set_tick_params(direction = axis[:tick_direction] == :out ? "out" : "in") + pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in") getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide]) if get(axis.plotattributes, :flip, false) getproperty(ax, Symbol("invert_", letter, "axis"))() end - pyaxis.label.set_fontsize(py_thickness_scale(plt, axis[:guidefontsize])) - pyaxis.label.set_family(axis[:guidefontfamily]) + pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize])) + pyaxis."label"."set_family"(axis[:guidefontfamily]) for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))() - lab.set_fontsize(py_thickness_scale(plt, axis[:tickfontsize])) - lab.set_family(axis[:tickfontfamily]) - lab.set_rotation(axis[:rotation]) + lab."set_fontsize"(py_thickness_scale(plt, axis[:tickfontsize])) + lab."set_family"(axis[:tickfontfamily]) + lab."set_rotation"(axis[:rotation]) end if axis[:grid] && !(ticks in (:none, nothing, false)) fgcolor = py_color(axis[:foreground_color_grid]) - pyaxis.grid(true, + pyaxis."grid"(true, color = fgcolor, linestyle = py_linestyle(:line, axis[:gridstyle]), linewidth = py_thickness_scale(plt, axis[:gridlinewidth]), alpha = axis[:gridalpha]) - ax.set_axisbelow(true) + ax."set_axisbelow"(true) else - pyaxis.grid(false) + pyaxis."grid"(false) end py_set_axis_colors(sp, ax, axis) end @@ -1109,13 +1109,13 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) kw = KW() for dir in (:top, :bottom) if ispolar(sp) - ax.spines."polar".set_visible(false) + ax."spines"."polar"."set_visible"(false) else getproperty(ax.spines, dir).set_visible(false) end kw[dir] = kw[Symbol(:label,dir)] = false end - ax.xaxis.set_tick_params(; which="both", kw...) + ax."xaxis"."set_tick_params"(; which="both", kw...) end if !sp[:yaxis][:showaxis] kw = KW() @@ -1125,20 +1125,20 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) end kw[dir] = kw[Symbol(:label,dir)] = false end - ax.yaxis.set_tick_params(; which="both", kw...) + ax."yaxis"."set_tick_params"(; which="both", kw...) end # aspect ratio aratio = sp[:aspect_ratio] if aratio != :none - ax.set_aspect(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") + ax."set_aspect"(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") end #camera/view angle if is3d(sp) #convert azimuthal to match GR behaviour #view_init(elevation, azimuthal) so reverse :camera args - ax.view_init((sp[:camera].-(90,0))[end:-1:1]...) + ax."view_init"((sp[:camera].-(90,0))[end:-1:1]...) end # legend @@ -1149,8 +1149,8 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # link axes x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o - ax != x_ax_link && ax.get_shared_x_axes().join(ax, sp[:xaxis].sps[1].o) - ax != y_ax_link && ax.get_shared_y_axes().join(ax, sp[:yaxis].sps[1].o) + ax != x_ax_link && ax."get_shared_x_axes"()."join"(ax, sp[:xaxis].sps[1].o) + ax != y_ax_link && ax."get_shared_y_axes"()."join"(ax, sp[:yaxis].sps[1].o) end py_drawfig(fig) end @@ -1181,7 +1181,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend}) # optionally add the width of colorbar labels and colorbar to rightpad if haskey(sp.attr, :cbar_ax) - bb = py_bbox(sp.attr[:cbar_handle].ax.get_yticklabels()) + bb = py_bbox(sp.attr[:cbar_handle]."ax"."get_yticklabels"()) sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px) rightpad = rightpad + sp.attr[:cbar_width] end @@ -1202,13 +1202,13 @@ end function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val) ax = sp.o - ax.annotate(val, xy = (x,y), zorder = 999) + ax."annotate"(val, xy = (x,y), zorder = 999) end function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText) ax = sp.o - ax.annotate(val.str, + ax."annotate"(val.str, xy = (x,y), family = val.font.family, color = py_color(val.font.color), @@ -1244,14 +1244,14 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) if should_add_to_legend(series) # add a line/marker and a label push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing - pypatches.Patch( + pypatches."Patch"( edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)), facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)), 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) - PyPlot.plt.Line2D((0,1),(0,0), + PyPlot.plt."Line2D"((0,1),(0,0), color = py_color(get_linecolor(series, clims), get_linealpha(series)), linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)), linestyle = py_linestyle(:path, get_linestyle(series)), @@ -1268,7 +1268,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) # if anything was added, call ax.legend and set the colors if !isempty(handles) - leg = ax.legend(handles, + leg = ax."legend"(handles, labels, loc = get(_pyplot_legend_pos, leg, "best"), scatterpoints = 1, @@ -1277,13 +1277,13 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) edgecolor = py_color(sp[:foreground_color_legend]), framealpha = alpha(plot_color(sp[:background_color_legend])), ) - frame = leg.get_frame() - frame.set_linewidth(py_thickness_scale(plt, 1)) - leg.set_zorder(1000) - sp[:legendtitle] != nothing && leg.set_title(sp[:legendtitle]) + frame = leg."get_frame"() + frame."set_linewidth"(py_thickness_scale(plt, 1)) + leg."set_zorder"(1000) + sp[:legendtitle] != nothing && leg."set_title"(sp[:legendtitle]) - for txt in leg.get_texts() - PyPlot.plt.setp(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily]) + for txt in leg."get_texts"() + PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily]) end end end @@ -1301,7 +1301,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend}) figw, figh = sp.plt[:size] figw, figh = figw*px, figh*px pcts = bbox_to_pcts(sp.plotarea, figw, figh) - ax.set_position(pcts) + ax."set_position"(pcts) # set the cbar position if there is one if haskey(sp.attr, :cbar_ax) @@ -1311,7 +1311,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend}) has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7) cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm)) pcts = bbox_to_pcts(cb_bbox, figw, figh) - sp.attr[:cbar_ax].set_position(pcts) + sp.attr[:cbar_ax]."set_position"(pcts) end end PyPlot.draw() @@ -1320,7 +1320,7 @@ end # ----------------------------------------------------------------- # display/output -_display(plt::Plot{PyPlotBackend}) = plt.o.show() +_display(plt::Plot{PyPlotBackend}) = plt.o."show"() @@ -1338,16 +1338,16 @@ const _pyplot_mimeformats = Dict( for (mime, fmt) in _pyplot_mimeformats @eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend}) fig = plt.o - fig.canvas.print_figure( + fig."canvas"."print_figure"( io, format=$fmt, # bbox_inches = "tight", # figsize = map(px2inch, plt[:size]), - facecolor = fig.get_facecolor(), + facecolor = fig."get_facecolor"(), edgecolor = "none", dpi = plt[:dpi] ) end end -closeall(::PyPlotBackend) = PyPlot.plt.close("all") +closeall(::PyPlotBackend) = PyPlot.plt."close"("all") From 0e5df883d06c81aed972c0d6d1b3cab48c1bbc6a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 16 Mar 2019 10:42:45 +0100 Subject: [PATCH 132/230] add warning for PyCall version --- src/backends/pyplot.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index aa20d3d1..1e3ca98d 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -34,6 +34,11 @@ else :set_facecolor end +# PyCall API changes in v1.90.0 +if !isdefined(PyCall, :_setproperty!) + @warn "Plots no longer supports PyCall < 1.90.0 and PyPlot < 2.8.0. Either update PyCall and PyPlot or pin Plots to a version <= 0.23.2." +end + # # convert colorant to 4-tuple RGBA # py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha)) From 5e445b4a71ce36d0ae1492a915cbcde99b017b21 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 16 Mar 2019 19:33:35 +0100 Subject: [PATCH 133/230] update NEWS.md --- NEWS.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/Plots.jl | 4 ++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7ce23298..489f9444 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,51 @@ --- ## (current master) +## 0.24.0 +- Update to the new PyCall and PyPlot API + +## 0.23.2 +- pyplot fixes +- Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend. +- fix ticks +- support plotly json mime +- fix image axis limits +- default to radius 0 at center for polar plots + +## 0.23.1 +- slightly faster load time +- fixed errant MethodError +- fix bar plots with unicodeplots +- better colorbars for contour +- add volume seriestype for GR +- fix passing a tuple to custom ticks +- add vline to pgfplots +- add tex output for pyplot +- better 3d axis labels for GR + +## 0.23.0 +- compatible with StatPlots -> StatsPlots name shift +- fix histograms for vectors with NaN and Inf +- change gif behaviour (remove cache-busting) +- improved docstrings for shorthands functions +- fix font rotation for pyplot +- fix greyscale images for pyplot +- clamp greyscale images with values outside 0,1 +- support keyword argument for font options +- allow vector of markers for pyplot scatter + +## 0.22.5 +- improve behaviour of plotlyjs backend + +## 0.22.4 +- Add support for discrete contourf plots with GR + +## 0.22.3 +- Fix the `showtheme` function + +## 0.22.2 +- Allow annotations to accept a Tuple instead of the result of a text call (making it possible to specify font characteristics in recipes). E.g. `annotations = (2, 4, ("test", :right, 8, :red))` is the same as `annotations = (2, 4, text("test", :right, 8, :red))` + ## 0.22.1 - push PlotsDisplay just after REPLDisplay diff --git a/src/Plots.jl b/src/Plots.jl index 10c599ff..30fb4a9a 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,6 +1,6 @@ module Plots -_current_plots_version = v"0.20.6" +_current_plots_version = v"0.24.0" using Reexport @@ -187,7 +187,7 @@ include("backends/plotly.jl") include("backends/gr.jl") include("backends/web.jl") -include("shorthands.jl") +include("shorthands.jl") let PlotOrSubplot = Union{Plot, Subplot} global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...) From b78da20d04e59f4250268ab762c36c19c8a469d8 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 19 Mar 2019 12:40:40 +0100 Subject: [PATCH 134/230] add support for gif mime --- src/animation.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/animation.jl b/src/animation.jl index e8017ff1..59de784e 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -106,6 +106,14 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) end +# Only gifs can be shown via image/gif +Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif" + +function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif) + write(io, read(agif.filename)) +end + + # ----------------------------------------------- function _animate(forloop::Expr, args...; callgif = false) From 19fba27951137c7f04de6976510f36500ee11474 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 19 Mar 2019 14:23:25 +0100 Subject: [PATCH 135/230] don't read into a buffer first --- src/animation.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/animation.jl b/src/animation.jl index 59de784e..4f9ff6da 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -110,7 +110,7 @@ end Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif" function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif) - write(io, read(agif.filename)) + open(fio-> write(io, fio), agif.filename) end From a7be08ef461e61e000f8f38401c5424620fcfc68 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 25 Mar 2019 09:46:37 +0100 Subject: [PATCH 136/230] fix init error if PLOTS_DEFAULTS <: Dict{Symbol, Symbol} --- src/init.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.jl b/src/init.jl index 1cd1fcd2..bffc99f2 100644 --- a/src/init.jl +++ b/src/init.jl @@ -3,7 +3,7 @@ using REPL function _plots_defaults() if isdefined(Main, :PLOTS_DEFAULTS) - Main.PLOTS_DEFAULTS::Dict{Symbol,Any} + Dict{Symbol,Any}(Main.PLOTS_DEFAULTS) else Dict{Symbol,Any}() end From cbc379daa9e203824ce24145a1bab1528487f825 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 25 Mar 2019 17:15:06 +0100 Subject: [PATCH 137/230] gr: fixed problem with blank figures see https://github.com/jheinen/GR.jl/issues/202 --- src/backends/gr.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1dffd953..9388acd1 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -236,6 +236,7 @@ end function gr_fill_viewport(vp::AVec{Float64}, c) GR.savestate() GR.selntran(0) + GR.setscale(0) GR.setfillintstyle(GR.INTSTYLE_SOLID) gr_set_fillcolor(c) GR.fillrect(vp...) From 484977243545d956d7d780716d400573ce0cd2c0 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 26 Mar 2019 14:30:14 +0100 Subject: [PATCH 138/230] gr: improve Y label alignment --- src/backends/gr.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 9388acd1..e844c881 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -944,12 +944,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:guide] != "" gr_set_font(guidefont(yaxis)) GR.setcharup(-1, 0) + x_margin = 0.075 * (viewport_subplot[2] - viewport_subplot[1]) if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) + gr_text(viewport_plotarea[2] + x_margin, gr_view_ycenter(), yaxis[:guide]) else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) + gr_text(viewport_plotarea[1] - x_margin, gr_view_ycenter(), yaxis[:guide]) end end end From 5ec80ad1f1bbdbf4a498fed061c1cab2bae0050f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 27 Mar 2019 17:37:47 +0100 Subject: [PATCH 139/230] fix multiple drawing of discrete ticks --- src/axes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index fc0cc3ae..84876980 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -251,7 +251,7 @@ function get_ticks(axis::Axis) # discrete ticks... n = length(dvals) rng = if ticks == :auto - Int[round(Int,i) for i in range(1, stop=n, length=15)] + Int[round(Int,i) for i in range(1, stop=n, length=min(n,15))] else # if ticks == :all 1:n end From dd02a69e8f0b08ace5d94fff0d6ac6bd833538bf Mon Sep 17 00:00:00 2001 From: yharel Date: Thu, 28 Mar 2019 02:21:25 +0200 Subject: [PATCH 140/230] Consistent interpretation of contour levels across PyPlot,GR,Plotly[JS] backends. GR: fixed colorbar rendering/alignment for contour[f]. Merged colorbar for mutiple series. :colorbar_entry property to include series in colorbar. --- src/args.jl | 1 + src/backends.jl | 7 +-- src/backends/gr.jl | 130 +++++++++++++++++++++++++++++++---------- src/backends/plotly.jl | 8 +-- src/utils.jl | 22 ++++--- 5 files changed, 123 insertions(+), 45 deletions(-) diff --git a/src/args.jl b/src/args.jl index a5f043b4..c869bc5c 100644 --- a/src/args.jl +++ b/src/args.jl @@ -232,6 +232,7 @@ const _bar_width = 0.8 const _series_defaults = KW( :label => "AUTO", + :colorbar_entry => true, :seriescolor => :auto, :seriesalpha => nothing, :seriestype => :path, diff --git a/src/backends.jl b/src/backends.jl index 8f24be72..8cb4c0ce 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -332,7 +332,7 @@ const _gr_attr = merge_with_base_supported([ :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, :guidefontrotation, :guidefontcolor, :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, :colorbar_title, + :legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry, :fill_z, :line_z, :marker_z, :levels, :ribbon, :quiver, :orientation, @@ -386,7 +386,7 @@ const _plotly_attr = merge_with_base_supported([ :guide, :lims, :ticks, :scale, :flip, :rotation, :tickfont, :guidefont, :legendfont, :grid, :gridalpha, :gridlinewidth, - :legend, :colorbar, :colorbar_title, + :legend, :colorbar, :colorbar_title, :colorbar_entry, :marker_z, :fill_z, :line_z, :levels, :ribbon, :quiver, :orientation, @@ -511,7 +511,7 @@ const _pyplot_attr = merge_with_base_supported([ :tickfontfamily, :tickfontsize, :tickfontcolor, :guidefontfamily, :guidefontsize, :guidefontcolor, :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, + :legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry, :marker_z, :line_z, :fill_z, :levels, :ribbon, :quiver, :arrow, @@ -524,7 +524,6 @@ const _pyplot_attr = merge_with_base_supported([ :clims, :inset_subplots, :dpi, - :colorbar_title, :stride, :framestyle, :tick_direction, diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e844c881..3831ffda 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -415,24 +415,92 @@ function gr_set_viewport_polar() r end +mutable struct GRColorbar + heatmapseries::Union{Series,Nothing} + fillseries::Union{Series,Nothing} + linesseries::Union{Series,Nothing} + GRColorbar() = new(nothing,nothing,nothing) +end + +function gr_update_colorbar!(cbar::GRColorbar, series::Series) + if iscontour(series) + if isfilledcontour(series) + cbar.fillseries = series + else + cbar.linesseries = series + end + elseif series[:seriestype] == :heatmap + cbar.heatmapseries = series + end +end + +function gr_contour_levels(series::Series, clims) + levels = contour_levels(series, clims) + if isfilledcontour(series) + # GR implicitly uses the maximal z value as the highest level + if levels[end] < clims[2] + @warn("GR: highest contour level less than maximal z value is not supported.") + end + levels = levels[1:end-1] + end + levels +end + +function gr_colorbar_colors(series::Series, clims) + if iscontour(series) + levels = gr_contour_levels(series, clims) + if isfilledcontour(series) + # GR.contourf uses a color range according to supplied levels + zrange = ignorenan_extrema(levels) + else + # GR.contour uses a color range according to data range + zrange = clims + end + colors = 1000 .+ 255 .* (levels .- zrange[1]) ./ (zrange[2] - zrange[1]) + else + colors = 1000:1255 + end + round.(Int,colors) +end + # add the colorbar -function gr_colorbar(sp::Subplot, clims, levels) +function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) GR.savestate() xmin, xmax = gr_xy_axislims(sp)[1:2] zmin, zmax = clims[1:2] gr_set_viewport_cmap(sp) - l = if levels === nothing - (1000:1255)' - elseif length(levels) > 1 - min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels) - round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255) - else - Int32[1000, 1255] - end GR.setscale(0) GR.setwindow(xmin, xmax, zmin, zmax) - GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l) + if (hm = cbar.heatmapseries) !== nothing + gr_set_gradient!(hm) + # TODO should use z limits of the specific series + GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) + end + + if (series = cbar.fillseries) !== nothing + gr_set_gradient!(cbar.fillseries) + GR.setfillintstyle(GR.INTSTYLE_SOLID) + levels = contour_levels(series, clims) + colors = gr_colorbar_colors(series, clims) + for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) + GR.setfillcolorind(color) + GR.fillrect( xmin, xmax, from, to ) + end + end + + if (series = cbar.linesseries) !== nothing + gr_set_gradient!(series) + gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) + levels = contour_levels(series, clims) + colors = gr_colorbar_colors(series, clims) + for (line, color) in zip(levels, colors) + GR.setlinecolorind(color) + GR.polyline([xmin,xmax], [line,line] ) + end + end + ztick = 0.5 * GR.tick(zmin, zmax) + gr_set_line(1, :solid, plot_color(:black)) GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005) gr_set_font(guidefont(sp[:yaxis])) @@ -489,6 +557,21 @@ function gr_set_gradient(c) grad end +function gr_set_gradient!(series::Series) + st = series[:seriestype] + if st in (:surface, :heatmap) || isfilledcontour(series) + gr_set_gradient(series[:fillcolor]) + elseif st in (:contour, :wireframe) + gr_set_gradient(series[:linecolor]) + elseif series[:marker_z] != nothing + series[:markercolor] = gr_set_gradient(series[:markercolor]) + elseif series[:line_z] != nothing + series[:linecolor] = gr_set_gradient(series[:linecolor]) + elseif series[:fill_z] != nothing + series[:fillcolor] = gr_set_gradient(series[:fillcolor]) + end +end + # this is our new display func... set up the viewport_canvas, compute bounding boxes, and display each subplot function gr_display(plt::Plot, fmt="") GR.clearws() @@ -671,7 +754,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) outside_ticks = false # calculate the colorbar limits once for a subplot clims = get_clims(sp) - clevels = nothing + cbar = GRColorbar() draw_axes = sp[:framestyle] != :none # axes_2d = true @@ -695,8 +778,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) data_lims = gr_xy_axislims(sp) end - # color levels overwritten by the last relevant series - hascolorbar(series) && (clevels = colorbar_levels(series, clims)) + hascolorbar(series) && gr_update_colorbar!(cbar,series) end # set our plot area view @@ -963,24 +1045,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] - - # update the current stored gradient - if st in (:surface, :heatmap) || - (st == :contour && series[:fillrange] !== nothing) - gr_set_gradient(series[:fillcolor]) #, series[:fillalpha]) - elseif st in (:contour, :wireframe) - gr_set_gradient(series[:linecolor]) - elseif series[:marker_z] != nothing - series[:markercolor] = gr_set_gradient(series[:markercolor]) - elseif series[:line_z] != nothing - series[:linecolor] = gr_set_gradient(series[:linecolor]) - elseif series[:fill_z] != nothing - series[:fillcolor] = gr_set_gradient(series[:fillcolor]) - end + + # update the current stored gradient and the series + gr_set_gradient!(series) GR.savestate() - # update the bounding window if ispolar(sp) gr_set_viewport_polar() @@ -1046,12 +1116,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif st == :contour GR.setspace(clims[1], clims[2], 0, 90) - h = colorbar_levels(series, clims) GR.setlinetype(gr_linetype[get_linestyle(series)]) GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) is_lc_black = let black=plot_color(:black) plot_color(series[:linecolor]) in (black,[black]) end + h = gr_contour_levels(series, clims) if series[:fillrange] != nothing if series[:fillcolor] != series[:linecolor] && !is_lc_black @warn("GR: filled contour only supported with black contour lines") @@ -1221,7 +1291,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end # draw the colorbar - hascolorbar(sp) && gr_colorbar(sp, clims, clevels) + hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims) # add the legend if sp[:legend] != :none diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 8d7a0f12..3fd226de 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -506,13 +506,13 @@ function plotly_series(plt::Plot, series::Series) plotattributes_out[:showscale] = hascolorbar(sp) elseif st == :contour + filled = isfilledcontour(series) plotattributes_out[:type] = "contour" plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z - # plotattributes_out[:showscale] = series[:colorbar] != :none - plotattributes_out[:ncontours] = series[:levels] - plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true) + plotattributes_out[:ncontours] = series[:levels] + 2 + plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true) plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha]) - plotattributes_out[:showscale] = hascolorbar(sp) + plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series) elseif st in (:surface, :wireframe) plotattributes_out[:type] = "surface" diff --git a/src/utils.jl b/src/utils.jl index 687b0e49..472f67c4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -582,6 +582,9 @@ end _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) function hascolorbar(series::Series) + if get(series, :colorbar_entry, true) == false + return false + end st = series[:seriestype] hascbar = st == :heatmap if st == :contour @@ -610,15 +613,20 @@ function hascolorbar(sp::Subplot) hascbar end -function colorbar_levels(series::Series, clims) - if series[:seriestype] == :contour +iscontour(series::Series) = series[:seriestype] == :contour +isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing + +function contour_levels(series::Series, clims) + if iscontour(series) zmin, zmax = clims levels = series[:levels] - levels isa AbstractArray ? - levels : - levels > 1 ? - range(zmin, stop=zmax, length=levels) : - [(zmin + zmax) / 2] + if levels isa Integer + levels = range(zmin, stop=zmax, length=levels+2) + if !isfilledcontour(series) + levels = levels[2:end-1] + end + end + levels else # including heatmap, surface nothing end From 78059bf825277171434146aa015ef86031f0de7b Mon Sep 17 00:00:00 2001 From: yharel Date: Thu, 28 Mar 2019 02:28:19 +0200 Subject: [PATCH 141/230] Support for non-gradient colors in surface-like plots (useful for contour) --- src/args.jl | 28 +++++++++++++++------------- src/backends/gr.jl | 2 +- src/backends/plotly.jl | 2 +- src/backends/pyplot.jl | 2 +- src/utils.jl | 3 +++ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/args.jl b/src/args.jl index c869bc5c..f721e754 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1510,19 +1510,19 @@ function has_black_border_for_default(st::Symbol) like_histogram(st) || st in (:hexbin, :bar, :shape) end - -# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically -function getSeriesRGBColor(c, sp::Subplot, n::Int) +# converts a symbol or string into a Colorant or ColorGradient +# and assigns a color automatically +function get_series_color(c, sp::Subplot, n::Int, seriestype) if c == :auto - c = autopick(sp[:color_palette], n) + c = like_surface(seriestype) ? cgrad() : autopick(sp[:color_palette], n) elseif isa(c, Int) c = autopick(sp[:color_palette], c) end plot_color(c) end -function getSeriesRGBColor(c::AbstractArray, sp::Subplot, n::Int) - map(x->getSeriesRGBColor(x, sp, n), c) +function get_series_color(c::AbstractArray, sp::Subplot, n::Int, seriestype) + map(x->get_series_color(x, sp, n), c, seriestype) end function ensure_gradient!(plotattributes::KW, csym::Symbol, asym::Symbol) @@ -1567,21 +1567,23 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot) end # update series color - plotattributes[:seriescolor] = getSeriesRGBColor(plotattributes[:seriescolor], sp, plotIndex) + scolor = plotattributes[:seriescolor] + stype = plotattributes[:seriestype] + plotattributes[:seriescolor] = scolor = get_series_color(scolor, sp, plotIndex, stype) # update other colors for s in (:line, :marker, :fill) csym, asym = Symbol(s,:color), Symbol(s,:alpha) plotattributes[csym] = if plotattributes[csym] == :auto - plot_color(if has_black_border_for_default(plotattributes[:seriestype]) && s == :line + plot_color(if has_black_border_for_default(stype) && s == :line sp[:foreground_color_subplot] else - plotattributes[:seriescolor] + scolor end) elseif plotattributes[csym] == :match - plot_color(plotattributes[:seriescolor]) + plot_color(scolor) else - getSeriesRGBColor(plotattributes[csym], sp, plotIndex) + get_series_color(plotattributes[csym], sp, plotIndex, stype) end end @@ -1589,9 +1591,9 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot) plotattributes[:markerstrokecolor] = if plotattributes[:markerstrokecolor] == :match plot_color(sp[:foreground_color_subplot]) elseif plotattributes[:markerstrokecolor] == :auto - getSeriesRGBColor(plotattributes[:markercolor], sp, plotIndex) + get_series_color(plotattributes[:markercolor], sp, plotIndex, stype) else - getSeriesRGBColor(plotattributes[:markerstrokecolor], sp, plotIndex) + get_series_color(plotattributes[:markerstrokecolor], sp, plotIndex, stype) end # if marker_z, fill_z or line_z are set, ensure we have a gradient diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 3831ffda..b7111562 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -548,7 +548,7 @@ end const _gr_gradient_alpha = ones(256) function gr_set_gradient(c) - grad = c isa ColorGradient ? c : cgrad() + grad = _as_gradient(c) for (i,z) in enumerate(range(0, stop=1, length=256)) c = grad[z] GR.setcolorrep(999+i, red(c), green(c), blue(c)) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3fd226de..dc06ed45 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -354,7 +354,7 @@ end function plotly_colorscale(grad::ColorGradient, α) [[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)] end -plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α) +plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α) function plotly_colorscale(c::AbstractVector{<:RGBA}, α) if length(c) == 1 return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]] diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 1e3ca98d..8697c07f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -73,7 +73,7 @@ function py_colormap(grad::ColorGradient) cm."set_bad"(color=(0,0,0,0.0), alpha=0.0) cm end -py_colormap(c) = py_colormap(cgrad()) +py_colormap(c::Colorant) = py_colormap(_as_gradient(c)) function py_shading(c, z) diff --git a/src/utils.jl b/src/utils.jl index 472f67c4..4b9c7ceb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -273,6 +273,9 @@ _cycle(v, indices::AVec{Int}) = fill(v, length(indices)) _cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx) _cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices) +_as_gradient(grad::ColorGradient) = grad +_as_gradient(c::Colorant) = ColorGradient([c,c]) + makevec(v::AVec) = v makevec(v::T) where {T} = T[v] From 61d13b9b2d783f2ffa8cebb2518843951c25f20e Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Thu, 28 Mar 2019 08:39:15 +0100 Subject: [PATCH 142/230] gr: improved positioning of Y labels --- src/backends/gr.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e844c881..be38832f 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -944,13 +944,20 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:guide] != "" gr_set_font(guidefont(yaxis)) GR.setcharup(-1, 0) - x_margin = 0.075 * (viewport_subplot[2] - viewport_subplot[1]) if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(viewport_plotarea[2] + x_margin, gr_view_ycenter(), yaxis[:guide]) + if viewport_plotarea[1] - viewport_subplot[1] > 0.1 + gr_text(viewport_plotarea[2] + 0.025, gr_view_ycenter(), yaxis[:guide]) + else + gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) + end else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(viewport_plotarea[1] - x_margin, gr_view_ycenter(), yaxis[:guide]) + if viewport_plotarea[1] - viewport_subplot[1] > 0.1 + gr_text(viewport_plotarea[1] - 0.075, gr_view_ycenter(), yaxis[:guide]) + else + gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) + end end end end From 577d434bc82325ff9fb5ca081b044a3068095d64 Mon Sep 17 00:00:00 2001 From: Sebastian Rollen <38324289+SebRollen@users.noreply.github.com> Date: Thu, 28 Mar 2019 09:54:23 -0400 Subject: [PATCH 143/230] Update `yaxis!` description Just fixing a small typo. The description for `yaxis!` used to read "Specify x axis attributes for an existing plot", changed to "Specify y axis attributes for an existing plot" --- src/shorthands.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shorthands.jl b/src/shorthands.jl index 5d240482..6f379a73 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -449,7 +449,7 @@ yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip "Specify x axis attributes for an existing plot" xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) -"Specify x axis attributes for an existing plot" +"Specify y axis attributes for an existing plot" yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) ygrid!(args...; kw...) = plot!(; ygrid = args, kw...) From 65ab45ff1bcb6cd134aa862e3f85099a7ad804ab Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 29 Mar 2019 10:38:22 +0100 Subject: [PATCH 144/230] don't draw ticks twice in gr for framestyle in (:zerolines, :grid) --- src/backends/gr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index be38832f..9b3a8bb5 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -837,7 +837,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0) else gr_set_line(1, :solid, xaxis[:foreground_color_axis]) end @@ -847,7 +847,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0) else gr_set_line(1, :solid, yaxis[:foreground_color_axis]) end From 8982a67902b61cd80320b80b3c3b3a5e4b7e9eb5 Mon Sep 17 00:00:00 2001 From: yharel Date: Fri, 29 Mar 2019 21:20:36 +0300 Subject: [PATCH 145/230] Fix colorbar for misc. series types with line_z,fill_z,marker_z. --- src/backends/gr.jl | 62 ++++++++++++++++++++++-------------------- src/utils.jl | 67 ++++++++++++++++++++-------------------------- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b7111562..4cbee0d0 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -415,32 +415,30 @@ function gr_set_viewport_polar() r end -mutable struct GRColorbar - heatmapseries::Union{Series,Nothing} - fillseries::Union{Series,Nothing} - linesseries::Union{Series,Nothing} +struct GRColorbar + gradient::Ref{Union{Series,Nothing}} + fill::Ref{Union{Series,Nothing}} + lines::Ref{Union{Series,Nothing}} GRColorbar() = new(nothing,nothing,nothing) end function gr_update_colorbar!(cbar::GRColorbar, series::Series) - if iscontour(series) - if isfilledcontour(series) - cbar.fillseries = series - else - cbar.linesseries = series - end - elseif series[:seriestype] == :heatmap - cbar.heatmapseries = series + style = colorbar_style(series) + style === nothing && return + ref = style == cbar_gradient ? cbar.gradient : + style == cbar_fill ? cbar.fill : + style == cbar_lines ? cbar.lines : + error("Unknown colorbar style: $style.") + if ref[] !== nothing + @warn "Overwriting colorbar entry" end + ref[] = series end function gr_contour_levels(series::Series, clims) levels = contour_levels(series, clims) if isfilledcontour(series) # GR implicitly uses the maximal z value as the highest level - if levels[end] < clims[2] - @warn("GR: highest contour level less than maximal z value is not supported.") - end levels = levels[1:end-1] end levels @@ -471,16 +469,22 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) gr_set_viewport_cmap(sp) GR.setscale(0) GR.setwindow(xmin, xmax, zmin, zmax) - if (hm = cbar.heatmapseries) !== nothing - gr_set_gradient!(hm) - # TODO should use z limits of the specific series + if (series = cbar.gradient[]) !== nothing + gr_set_gradient(series) GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) end - if (series = cbar.fillseries) !== nothing - gr_set_gradient!(cbar.fillseries) + if (series = cbar.fill[]) !== nothing + gr_set_gradient(series) GR.setfillintstyle(GR.INTSTYLE_SOLID) levels = contour_levels(series, clims) + # GR implicitly uses the maximal z value as the highest level + if levels[end] < clims[2] + @warn("GR: highest contour level less than maximal z value is not supported.") + # replace levels, rather than assign to levels[end], to ensure type + # promotion in case levels is an integer array + levels = [levels[1:end-1]; clims[2]] + end colors = gr_colorbar_colors(series, clims) for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) GR.setfillcolorind(color) @@ -488,8 +492,8 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) end end - if (series = cbar.linesseries) !== nothing - gr_set_gradient!(series) + if (series = cbar.lines[]) !== nothing + gr_set_gradient(series) gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) levels = contour_levels(series, clims) colors = gr_colorbar_colors(series, clims) @@ -557,18 +561,18 @@ function gr_set_gradient(c) grad end -function gr_set_gradient!(series::Series) +function gr_set_gradient(series::Series) st = series[:seriestype] if st in (:surface, :heatmap) || isfilledcontour(series) gr_set_gradient(series[:fillcolor]) elseif st in (:contour, :wireframe) gr_set_gradient(series[:linecolor]) elseif series[:marker_z] != nothing - series[:markercolor] = gr_set_gradient(series[:markercolor]) + gr_set_gradient(series[:markercolor]) elseif series[:line_z] != nothing - series[:linecolor] = gr_set_gradient(series[:linecolor]) + gr_set_gradient(series[:linecolor]) elseif series[:fill_z] != nothing - series[:fillcolor] = gr_set_gradient(series[:fillcolor]) + gr_set_gradient(series[:fillcolor]) end end @@ -778,7 +782,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) data_lims = gr_xy_axislims(sp) end - hascolorbar(series) && gr_update_colorbar!(cbar,series) + gr_update_colorbar!(cbar,series) end # set our plot area view @@ -1046,8 +1050,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] - # update the current stored gradient and the series - gr_set_gradient!(series) + # update the current stored gradient + gr_set_gradient(series) GR.savestate() diff --git a/src/utils.jl b/src/utils.jl index 4b9c7ceb..bea33a07 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -584,55 +584,46 @@ end _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) -function hascolorbar(series::Series) - if get(series, :colorbar_entry, true) == false - return false +@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines + +function colorbar_style(series::Series) + colorbar_entry = series[:colorbar_entry] + if !(colorbar_entry isa Bool) + @warn "Non-boolean colorbar_entry ignored." + colorbar_entry = true end - st = series[:seriestype] - hascbar = st == :heatmap - if st == :contour - hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1) + + if !colorbar_entry + nothing + elseif isfilledcontour(series) + cbar_fill + elseif iscontour(series) + cbar_lines + elseif series[:seriestype] ∈ (:heatmap,:surface) || + any(series[z] !== nothing for z ∈ [:marker_z,:line_z,:fill_z]) + cbar_gradient + else + nothing end - if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing - hascbar = true - end - # no colorbar if we are creating a surface LightSource - if xor(st == :surface, series[:fill_z] != nothing) - hascbar = true - end - return hascbar end -function hascolorbar(sp::Subplot) - cbar = sp[:colorbar] - hascbar = false - if cbar != :none - for series in series_list(sp) - if hascolorbar(series) - hascbar = true - end - end - end - hascbar -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 isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing function contour_levels(series::Series, clims) - if iscontour(series) - zmin, zmax = clims - levels = series[:levels] - if levels isa Integer - levels = range(zmin, stop=zmax, length=levels+2) - if !isfilledcontour(series) - levels = levels[2:end-1] - end + iscontour(series) || error("Not a contour series") + zmin, zmax = clims + levels = series[:levels] + if levels isa Integer + levels = range(zmin, stop=zmax, length=levels+2) + if !isfilledcontour(series) + levels = levels[2:end-1] end - levels - else # including heatmap, surface - nothing end + levels end From 0075103ddfd83e26a0f4d08a3abf63fd90412029 Mon Sep 17 00:00:00 2001 From: yharel Date: Fri, 29 Mar 2019 22:01:28 +0300 Subject: [PATCH 146/230] Proportional colorbar spacing in pyplot --- src/backends/pyplot.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 8697c07f..d3e0e091 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1013,6 +1013,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) cmap."set_array"([]) handle = cmap end + kw[:spacing] = "proportional" # create and store the colorbar object (handle) and the axis that it is drawn on. # note: the colorbar axis is positioned independently from the subplot axis From 5d2538c4c26f20fb325c0bdc7708fb2c96f4d0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hamza=20Yusuf=20=C3=87ak=C4=B1r?= <32282514+hycakir@users.noreply.github.com> Date: Sat, 30 Mar 2019 12:09:17 +0300 Subject: [PATCH 147/230] fix `abline!` description It should be `ax+b` rather than `a+bx`. --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 37982a3d..6f3fbdf0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1061,7 +1061,7 @@ end # ------------------------------------------------- -"Adds a+bx... straight line over the current plot, without changing the axis limits" +"Adds ax+b... straight line over the current plot, without changing the axis limits" abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...) abline!(args...; kw...) = abline!(current(), args...; kw...) From d61c86b54b357156fc10e10a982d535f7fa4cd36 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 1 Apr 2019 13:14:06 +0200 Subject: [PATCH 148/230] fix alpha for colorbar in GR --- src/backends/gr.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1644c70e..7412ff14 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -79,7 +79,7 @@ gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(_cycle(c,1))) gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1))) gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1))) gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1)) -function gr_set_transparency(::Nothing) end +gr_set_transparency(::Nothing) = GR.settransparency(1) # -------------------------------------------------------------------------------------- @@ -442,8 +442,8 @@ function gr_contour_levels(series::Series, clims) levels = levels[1:end-1] end levels -end - +end + function gr_colorbar_colors(series::Series, clims) if iscontour(series) levels = gr_contour_levels(series, clims) @@ -471,6 +471,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) GR.setwindow(xmin, xmax, zmin, zmax) if (series = cbar.gradient[]) !== nothing gr_set_gradient(series) + gr_set_transparency(get_fillalpha(series)) GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) end @@ -488,6 +489,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) colors = gr_colorbar_colors(series, clims) for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) GR.setfillcolorind(color) + gr_set_transparency(get_fillalpha(series)) GR.fillrect( xmin, xmax, from, to ) end end @@ -495,6 +497,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) if (series = cbar.lines[]) !== nothing gr_set_gradient(series) gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) + gr_set_transparency(get_linealpha(series)) levels = contour_levels(series, clims) colors = gr_colorbar_colors(series, clims) for (line, color) in zip(levels, colors) @@ -502,7 +505,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) GR.polyline([xmin,xmax], [line,line] ) end end - + ztick = 0.5 * GR.tick(zmin, zmax) gr_set_line(1, :solid, plot_color(:black)) GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005) @@ -1056,7 +1059,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] - + # update the current stored gradient gr_set_gradient(series) From 7c26ffee512820f17c15d80444608bb15016feba Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 1 Apr 2019 14:05:32 +0200 Subject: [PATCH 149/230] gr: use correct workstation type after savefig() --- src/backends/gr.jl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1644c70e..e66ce61a 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1428,16 +1428,7 @@ const _gr_mimeformats = Dict( "image/svg+xml" => "svg", ) -const _gr_wstype_default = @static if Sys.islinux() - "x11" - # "cairox11" -elseif Sys.isapple() - "quartz" -else - "use_default" -end - -const _gr_wstype = Ref(get(ENV, "GKSwstype", _gr_wstype_default)) +const _gr_wstype = Ref(get(ENV, "GKSwstype", "")) gr_set_output(wstype::String) = (_gr_wstype[] = wstype) for (mime, fmt) in _gr_mimeformats @@ -1472,7 +1463,7 @@ function _display(plt::Plot{GRBackend}) rm(filepath) else ENV["GKS_DOUBLE_BUF"] = true - if _gr_wstype[] != "use_default" + if _gr_wstype[] != "" ENV["GKSwstype"] = _gr_wstype[] end gr_display(plt) From 9774eca8e27556d89062cc47c8a0c1a6b028b441 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 2 Apr 2019 20:55:51 +0200 Subject: [PATCH 150/230] bump GR version to 0.39.0 --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index 4bb39a85..a8329ecf 100644 --- a/REQUIRE +++ b/REQUIRE @@ -13,4 +13,4 @@ JSON NaNMath Requires Contour -GR 0.38.1 +GR 0.39.0 From 7f2a1db64a7c6eb1977211ff602299ce93706d3e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Apr 2019 11:26:12 +0200 Subject: [PATCH 151/230] fix passing a vector of colors --- src/args.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/args.jl b/src/args.jl index f721e754..13423b33 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1522,7 +1522,7 @@ function get_series_color(c, sp::Subplot, n::Int, seriestype) end function get_series_color(c::AbstractArray, sp::Subplot, n::Int, seriestype) - map(x->get_series_color(x, sp, n), c, seriestype) + map(x->get_series_color(x, sp, n, seriestype), c) end function ensure_gradient!(plotattributes::KW, csym::Symbol, asym::Symbol) @@ -1567,7 +1567,7 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot) end # update series color - scolor = plotattributes[:seriescolor] + scolor = plotattributes[:seriescolor] stype = plotattributes[:seriestype] plotattributes[:seriescolor] = scolor = get_series_color(scolor, sp, plotIndex, stype) From 841b05631d342752472b02c3b2d820693cec848f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 7 Apr 2019 16:20:15 +0200 Subject: [PATCH 152/230] replace StaticArrays with GeometryTypes --- REQUIRE | 2 +- src/Plots.jl | 2 +- src/components.jl | 17 +++++++---------- src/series.jl | 14 +++++++------- src/utils.jl | 22 +++++++++++----------- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/REQUIRE b/REQUIRE index a8329ecf..bd236535 100644 --- a/REQUIRE +++ b/REQUIRE @@ -4,7 +4,7 @@ RecipesBase 0.6.0 PlotUtils 0.4.1 PlotThemes 0.1.3 Reexport -StaticArrays 0.5 +GeometryTypes FixedPointNumbers 0.3 Measures Showoff diff --git a/src/Plots.jl b/src/Plots.jl index 30fb4a9a..6587033c 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -4,7 +4,7 @@ _current_plots_version = v"0.24.0" using Reexport -import StaticArrays +import GeometryTypes using Dates, Printf, Statistics, Base64, LinearAlgebra, Random import SparseArrays: findnz diff --git a/src/components.jl b/src/components.jl index e6215624..097aee19 100644 --- a/src/components.jl +++ b/src/components.jl @@ -1,7 +1,7 @@ -const P2 = StaticArrays.SVector{2,Float64} -const P3 = StaticArrays.SVector{3,Float64} +const P2 = GeometryTypes.Point2{Float64} +const P3 = GeometryTypes.Point3{Float64} nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b)) nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b)) @@ -261,13 +261,13 @@ end Create a Font from a list of features. Values may be specified either as arguments (which are distinguished by type/value) or as keyword arguments. # Arguments -- `family`: AbstractString. "serif" or "sans-serif" or "monospace" +- `family`: AbstractString. "serif" or "sans-serif" or "monospace" - `pointsize`: Integer. Size of font in points - `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right) - `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom) - `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type) - `color`: Colorant or Symbol -# Examples +# Examples ```julia-repl julia> font(8) julia> font(family="serif",halign=:center,rotation=45.0) @@ -388,8 +388,8 @@ PlotText(str) = PlotText(string(str), font()) """ text(string, args...; kw...) -Create a PlotText object wrapping a string with font info, for plot annotations. -`args` and `kw` are passed to `font`. +Create a PlotText object wrapping a string with font info, for plot annotations. +`args` and `kw` are passed to `font`. """ text(t::PlotText) = t text(t::PlotText, font::Font) = PlotText(t.str, font) @@ -779,7 +779,7 @@ end # ----------------------------------------------------------------------- "create a BezierCurve for plotting" -mutable struct BezierCurve{T <: StaticArrays.SVector} +mutable struct BezierCurve{T <: GeometryTypes.Point} control_points::Vector{T} end @@ -792,9 +792,6 @@ function (bc::BezierCurve)(t::Real) p end -# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality -# mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array - @deprecate curve_points coords coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50)) diff --git a/src/series.jl b/src/series.jl index fd9f5fdb..9bfcafc7 100644 --- a/src/series.jl +++ b/src/series.jl @@ -554,7 +554,7 @@ end # # # # -------------------------------------------------------------------- -# # Lists of tuples and StaticArrays +# # Lists of tuples and GeometryTypes.Points # # -------------------------------------------------------------------- # # # if we get an unhandled tuple, just splat it in @@ -576,14 +576,14 @@ end # -# # 2D StaticArrays -@recipe f(xy::AVec{StaticArrays.SVector{2,T}}) where {T<:Number} = unzip(xy) -@recipe f(xy::StaticArrays.SVector{2,T}) where {T<:Number} = [xy[1]], [xy[2]] +# # 2D Points +@recipe f(xy::AVec{GeometryTypes.Point{2,T}}) where {T<:Number} = unzip(xy) +@recipe f(xy::GeometryTypes.Point{2,T}) where {T<:Number} = [xy[1]], [xy[2]] # -# # 3D StaticArrays -@recipe f(xyz::AVec{StaticArrays.SVector{3,T}}) where {T<:Number} = unzip(xyz) -@recipe f(xyz::StaticArrays.SVector{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] +# # 3D Points +@recipe f(xyz::AVec{GeometryTypes.Point{3,T}}) where {T<:Number} = unzip(xyz) +@recipe f(xyz::GeometryTypes.Point{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] # # # -------------------------------------------------------------------- diff --git a/src/utils.jl b/src/utils.jl index bea33a07..9d0316b7 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -290,14 +290,14 @@ unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz] unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv] -unzip(xy::AVec{StaticArrays.SVector{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy] -unzip(xy::StaticArrays.SVector{2,T}) where {T} = T[xy[1]], T[xy[2]] +unzip(xy::AVec{GeometryTypes.Point{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy] +unzip(xy::GeometryTypes.Point{2,T}) where {T} = T[xy[1]], T[xy[2]] -unzip(xyz::AVec{StaticArrays.SVector{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz] -unzip(xyz::StaticArrays.SVector{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]] +unzip(xyz::AVec{GeometryTypes.Point{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz] +unzip(xyz::GeometryTypes.Point{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]] -unzip(xyuv::AVec{StaticArrays.SVector{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv] -unzip(xyuv::StaticArrays.SVector{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]] +unzip(xyuv::AVec{GeometryTypes.Point{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv] +unzip(xyuv::GeometryTypes.Point{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]] # given 2-element lims and a vector of data x, widen lims to account for the extrema of x function _expand_limits(lims, x) @@ -592,15 +592,15 @@ function colorbar_style(series::Series) @warn "Non-boolean colorbar_entry ignored." colorbar_entry = true end - + if !colorbar_entry nothing - elseif isfilledcontour(series) + elseif isfilledcontour(series) cbar_fill elseif iscontour(series) cbar_lines - elseif series[:seriestype] ∈ (:heatmap,:surface) || - any(series[z] !== nothing for z ∈ [:marker_z,:line_z,:fill_z]) + elseif series[:seriestype] ∈ (:heatmap,:surface) || + any(series[z] !== nothing for z ∈ [:marker_z,:line_z,:fill_z]) cbar_gradient else nothing @@ -626,7 +626,7 @@ function contour_levels(series::Series, clims) levels end - + for comp in (:line, :fill, :marker) From c2da4acb4802d2dfcc693d05ac09b84fd3bd4561 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 7 Apr 2019 16:23:26 +0200 Subject: [PATCH 153/230] update news --- NEWS.md | 6 ++++++ src/Plots.jl | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 489f9444..7c3d71ac 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,8 +11,14 @@ --- ## (current master) +## 0.25.0 +- Replace StaticArrays with GeometryTypes +- Contour fixes for GR + ## 0.24.0 - Update to the new PyCall and PyPlot API +- fix drawing of ticks +- fix y label position with GR ## 0.23.2 - pyplot fixes diff --git a/src/Plots.jl b/src/Plots.jl index 6587033c..0849c20b 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,6 +1,6 @@ module Plots -_current_plots_version = v"0.24.0" +_current_plots_version = v"0.25.0" using Reexport From 0b3dafcd1891cd2df95189d633c0a98324de9986 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 9 Apr 2019 17:50:19 +0200 Subject: [PATCH 154/230] fix plotattr `plotattr` would fail when the description did not have a period (`.`) in it, e.g. for `ticks`. This seemed safer than to edit the argument descriptions --- src/plotattr.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plotattr.jl b/src/plotattr.jl index fb7170e4..d695d16e 100644 --- a/src/plotattr.jl +++ b/src/plotattr.jl @@ -50,8 +50,13 @@ function plotattr(attrtype::Symbol, attribute::AbstractString) desc = get(_arg_desc, attribute, "") first_period_idx = findfirst(isequal('.'), desc) - typedesc = desc[1:first_period_idx-1] - desc = strip(desc[first_period_idx+1:end]) + if isnothing(first_period_idx) + typedesc = "" + desc = strip(desc) + else + typedesc = desc[1:first_period_idx-1] + desc = strip(desc[first_period_idx+1:end]) + end als = keys(filter(x->x[2]==attribute, _keyAliases)) |> collect |> sort als = join(map(string,als), ", ") def = _attribute_defaults[attrtype][attribute] From 5506c0543c9330d378703c7cf32f19dc4517e7a6 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 12 Apr 2019 09:24:28 +0200 Subject: [PATCH 155/230] don't let `marker = true` set the marker size to 1 --- src/args.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/args.jl b/src/args.jl index 13423b33..c443b5bb 100644 --- a/src/args.jl +++ b/src/args.jl @@ -737,6 +737,10 @@ function processMarkerArg(plotattributes::KW, arg) elseif allAlphas(arg) plotattributes[:markeralpha] = arg + # bool + elseif typeof(arg) <: Bool + plotattributes[:markershape] = arg ? :auto : :none + # markersize elseif allReals(arg) plotattributes[:markersize] = arg From b6b00c843a55423f838e0330ccc52ab2fb121ec9 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 12 Apr 2019 09:42:19 +0200 Subject: [PATCH 156/230] set default to :circle instead of :auto for marker = true --- src/args.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/args.jl b/src/args.jl index c443b5bb..24676d01 100644 --- a/src/args.jl +++ b/src/args.jl @@ -739,7 +739,7 @@ function processMarkerArg(plotattributes::KW, arg) # bool elseif typeof(arg) <: Bool - plotattributes[:markershape] = arg ? :auto : :none + plotattributes[:markershape] = arg ? :circle : :none # markersize elseif allReals(arg) From a37a1a0004a1eb2b4fb4fba331b63cca5c19c6dc Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 12 Apr 2019 12:41:49 +0200 Subject: [PATCH 157/230] sort vector attributes for seriestype line --- src/recipes.jl | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/recipes.jl b/src/recipes.jl index 6f3fbdf0..220ab221 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -53,10 +53,41 @@ RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where # for seriestype `line`, need to sort by x values + +const POTENTIAL_VECTOR_ARGUMENTS = [ + :seriescolor, :seriesalpha, + :linecolor, :linealpha, :linewidth, :linestyle, :line_z, + :fillcolor, :fillalpha, :fill_z, + :markercolor, :markeralpha, :markershape, :marker_z, + :markerstrokecolor, :markerstrokealpha, + :yerror, :yerror, + :series_annotations, :fillrange +] + @recipe function f(::Type{Val{:line}}, x, y, z) indices = sortperm(x) x := x[indices] y := y[indices] + + # sort vector arguments + for arg in POTENTIAL_VECTOR_ARGUMENTS + if typeof(plotattributes[arg]) <: AVec + plotattributes[arg] = _cycle(plotattributes[arg], indices) + end + end + + # a tuple as fillrange has to be handed differently + if typeof(plotattributes[:fillrange]) <: Tuple + lower, upper = plotattributes[:fillrange] + if typeof(lower) <: AVec + lower = _cycle(lower, indices) + end + if typeof(upper) <: AVec + upper = _cycle(upper, indices) + end + plotattributes[:fillrange] = (lower, upper) + end + if typeof(z) <: AVec z := z[indices] end From 8a81b398cfc124cd5d0247dac55fb3bfbafe036e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 12 Apr 2019 12:44:34 +0200 Subject: [PATCH 158/230] fix typo --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 220ab221..ca2468e1 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -76,7 +76,7 @@ const POTENTIAL_VECTOR_ARGUMENTS = [ end end - # a tuple as fillrange has to be handed differently + # a tuple as fillrange has to be handled differently if typeof(plotattributes[:fillrange]) <: Tuple lower, upper = plotattributes[:fillrange] if typeof(lower) <: AVec From 0c67a61e7d90259c7e3174ce0c65986ccfcb8b7f Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 15 Apr 2019 09:07:52 +0200 Subject: [PATCH 159/230] fix io --- src/axes.jl | 2 +- src/utils.jl | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index 84876980..c95b5db7 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -117,7 +117,7 @@ end # ------------------------------------------------------------------------- -Base.show(io::IO, axis::Axis) = dumpdict(axis.plotattributes, "Axis", true) +Base.show(io::IO, axis::Axis) = dumpdict(io, axis.plotattributes, "Axis", true) # Base.getindex(axis::Axis, k::Symbol) = getindex(axis.plotattributes, k) Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.plotattributes, v, ks...) Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k) diff --git a/src/utils.jl b/src/utils.jl index 9d0316b7..c41eb8a7 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -814,10 +814,10 @@ function debugplots(on = true) _debugMode.on = on end -debugshow(x) = show(x) -debugshow(x::AbstractArray) = print(summary(x)) +debugshow(io, x) = show(io, x) +debugshow(io, x::AbstractArray) = print(io, summary(x)) -function dumpdict(plotattributes::KW, prefix = "", alwaysshow = false) +function dumpdict(io::IO, plotattributes::KW, prefix = "", alwaysshow = false) _debugMode.on || alwaysshow || return println() if prefix != "" @@ -825,13 +825,13 @@ function dumpdict(plotattributes::KW, prefix = "", alwaysshow = false) end for k in sort(collect(keys(plotattributes))) @printf("%14s: ", k) - debugshow(plotattributes[k]) + debugshow(io, plotattributes[k]) println() end println() end -DD(plotattributes::KW, prefix = "") = dumpdict(plotattributes, prefix, true) - +DD(io::IO, plotattributes::KW, prefix = "") = dumpdict(io, plotattributes, prefix, true) +DD(plotattributes::KW, prefix = "") = DD(stdout, plotattributes, prefix) function dumpcallstack() error() # well... you wanted the stacktrace, didn't you?!? From 6131154dd04cc29634db5907fb07dea40d0f9dbf Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 15 Apr 2019 15:13:22 +0200 Subject: [PATCH 160/230] mixing ios in println --- src/utils.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index c41eb8a7..7ae64796 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -819,16 +819,16 @@ debugshow(io, x::AbstractArray) = print(io, summary(x)) function dumpdict(io::IO, plotattributes::KW, prefix = "", alwaysshow = false) _debugMode.on || alwaysshow || return - println() + println(io) if prefix != "" - println(prefix, ":") + println(io, prefix, ":") end for k in sort(collect(keys(plotattributes))) @printf("%14s: ", k) debugshow(io, plotattributes[k]) - println() + println(io) end - println() + println(io) end DD(io::IO, plotattributes::KW, prefix = "") = dumpdict(io, plotattributes, prefix, true) DD(plotattributes::KW, prefix = "") = DD(stdout, plotattributes, prefix) From b053366b060cadcb7e29ca16b7b3b1b9b4e625dc Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 26 Apr 2019 13:03:03 +0200 Subject: [PATCH 161/230] don't filter polar data --- src/backends/pgfplots.jl | 2 +- src/backends/plotly.jl | 2 +- src/utils.jl | 26 +------------------------- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 4f6d99af..a59fd19d 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -171,7 +171,7 @@ function pgf_series(sp::Subplot, series::Series) elseif st == :shape shape_data(series) elseif ispolar(sp) - theta, r = filter_radial_data(plotattributes[:x], plotattributes[:y], axis_limits(sp[:yaxis])) + theta, r = plotattributes[:x], plotattributes[:y] rad2deg.(theta), r else plotattributes[:x], plotattributes[:y] diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index dc06ed45..b642979f 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -774,7 +774,7 @@ end function plotly_polar!(plotattributes_out::KW, series::Series) # convert polar plots x/y to theta/radius if ispolar(series[:subplot]) - theta, r = filter_radial_data(pop!(plotattributes_out, :x), pop!(plotattributes_out, :y), axis_limits(series[:subplot][:yaxis])) + theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y) plotattributes_out[:t] = rad2deg.(theta) plotattributes_out[:r] = r end diff --git a/src/utils.jl b/src/utils.jl index 7ae64796..2d8172f5 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -373,38 +373,14 @@ function heatmap_edges(v::AVec, scale::Symbol = :identity) map(invf, _heatmap_edges(map(f,v))) end -function calc_r_extrema(x, y) - xmin, xmax = ignorenan_extrema(x) - ymin, ymax = ignorenan_extrema(y) - r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin) - ignorenan_extrema(r) -end - -function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y)) +function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r)) rmin, rmax = r_extrema - theta, r = filter_radial_data(x, y, r_extrema) r = (r .- rmin) ./ (rmax .- rmin) x = r.*cos.(theta) y = r.*sin.(theta) x, y end -# Filters radial data for points within the axis limits -function filter_radial_data(theta, r, r_extrema::Tuple{Real, Real}) - n = max(length(theta), length(r)) - rmin, rmax = r_extrema - x, y = zeros(n), zeros(n) - for i in 1:n - x[i] = _cycle(theta, i) - y[i] = _cycle(r, i) - end - points = map((a, b) -> (a, b), x, y) - filter!(a -> a[2] >= rmin && a[2] <= rmax, points) - x = map(a -> a[1], points) - y = map(a -> a[2], points) - x, y -end - function fakedata(sz...) y = zeros(sz...) for r in 2:size(y,1) From a6588daa3e92312261129f2bbe85ebb9b858306d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 26 Apr 2019 13:17:29 +0200 Subject: [PATCH 162/230] allow negative radii in polar plots for pyplot --- src/backends/pyplot.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index d3e0e091..3618412f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -376,6 +376,18 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) elseif st == :shape x, y = shape_data(series) end + + if ispolar(series) + # make negative radii positive and flip the angle + # (PyPlot ignores negative radii) + for i in eachindex(y) + if y[i] < 0 + y[i] = -y[i] + x[i] -= π + end + end + end + xyargs = (st in _3dTypes ? (x,y,z) : (x,y)) # handle zcolor and get c/cmap From 39605bccc2fa5deedaa3bc35a268ec3cb655ee53 Mon Sep 17 00:00:00 2001 From: 8uurg Date: Sat, 27 Apr 2019 20:13:36 +0200 Subject: [PATCH 163/230] Make legend=:outertopright work Move x to the right of the plot viewport Perform legend size computation earlier as this computed width is required for adjusting the width of the plotarea viewport. This adjustment has to be done before any further computations requiring this plotarea viewport width. --- src/backends/gr.jl | 67 +++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 9220db05..69b278fd 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -528,7 +528,12 @@ function gr_legend_pos(s::Symbol,w,h) str = "topright" end if occursin("right", str) - xpos = viewport_plotarea[2] - 0.05 - w + if occursin("outer", str) + # As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525 + xpos = viewport_plotarea[2] + 0.11 + else + xpos = viewport_plotarea[2] - 0.05 - w + end elseif occursin("left", str) xpos = viewport_plotarea[1] + 0.11 else @@ -752,6 +757,43 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end end + # calculate legend size + # has to be done now due to a potential adjustment to the plotarea given an outer legend. + legendn = 0 + legendw = 0 + legendi = 0 + if sp[:legend] != :none + GR.savestate() + GR.selntran(0) + GR.setscale(0) + gr_set_font(legendfont(sp)) + if sp[:legendtitle] != nothing + tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle])) + legendw = tbx[3] - tbx[1] + legendn += 1 + end + for series in series_list(sp) + should_add_to_legend(series) || continue + legendn += 1 + if typeof(series[:label]) <: Array + legendi += 1 + lab = series[:label][i] + else + lab = series[:label] + end + tbx, tby = gr_inqtext(0, 0, string(lab)) + legendw = max(legendw, tbx[3] - tbx[1]) + end + + GR.setscale(1) + GR.selntran(1) + GR.restorestate() + end + + if occursin("outer", string(sp[:legend])) + viewport_plotarea[2] -= legendw + 0.1 + end + # fill in the plot area background bg = plot_color(sp[:background_color_inside]) gr_fill_viewport(viewport_plotarea, bg) @@ -1313,26 +1355,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.selntran(0) GR.setscale(0) gr_set_font(legendfont(sp)) - w = 0 - i = 0 - n = 0 - if sp[:legendtitle] != nothing - tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle])) - w = tbx[3] - tbx[1] - n += 1 - end - for series in series_list(sp) - should_add_to_legend(series) || continue - n += 1 - if typeof(series[:label]) <: Array - i += 1 - lab = series[:label][i] - else - lab = series[:label] - end - tbx, tby = gr_inqtext(0, 0, string(lab)) - w = max(w, tbx[3] - tbx[1]) - end + w = legendw + i = legendi + n = legendn if w > 0 dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 h = dy*n From 4742ec972b50b873884597f58efd50dbd7333994 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 30 Apr 2019 15:25:08 +0200 Subject: [PATCH 164/230] allow numeric legend positioning in pyplot --- src/backends/gr.jl | 2 +- src/backends/pyplot.jl | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 69b278fd..2c8341f5 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -784,7 +784,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) tbx, tby = gr_inqtext(0, 0, string(lab)) legendw = max(legendw, tbx[3] - tbx[1]) end - + GR.setscale(1) GR.selntran(1) GR.restorestate() diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 3618412f..773b1932 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1251,6 +1251,12 @@ const _pyplot_legend_pos = KW( :topleft => "upper left" ) +py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, "best") +py_legend_pos(pos) = "lower left" + +py_legend_bbox(pos::Symbol) = (0, 0, 1, 1) +py_legend_bbox(pos) = pos + function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] clims = get_clims(sp) @@ -1288,7 +1294,8 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) if !isempty(handles) leg = ax."legend"(handles, labels, - loc = get(_pyplot_legend_pos, leg, "best"), + loc = py_legend_pos(leg), + bbox_to_anchor = py_legend_bbox(leg), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 710123aab4d5ee42fd6184a7a8455a3deb1977c1 Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 1 May 2019 00:15:13 +0200 Subject: [PATCH 165/230] Add attribute draw_arrow for axes. The draw_arrow attribute enables drawing an arrow at the end of an axis. Currently supported only by the PGFPlots backend. --- src/arg_desc.jl | 1 + src/args.jl | 1 + src/backends/pgfplots.jl | 8 ++++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 32c4220f..13e42645 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -150,4 +150,5 @@ const _arg_desc = KW( :tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`", :showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`", :widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.", +:draw_arrow => "Bool. Draw arrow at the end of the axis.", ) diff --git a/src/args.jl b/src/args.jl index 24676d01..f4bc8d82 100644 --- a/src/args.jl +++ b/src/args.jl @@ -392,6 +392,7 @@ const _axis_defaults = KW( :minorgrid => false, :showaxis => true, :widen => true, + :draw_arrow => false, ) const _suppress_warnings = Set{Symbol}([ diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index a59fd19d..e7c805d0 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -399,8 +399,12 @@ function pgf_axis(sp::Subplot, letter) # framestyle if framestyle in (:axes, :origin) axispos = framestyle == :axes ? "left" : "middle" - # the * after lines disables the arrows at the axes - push!(style, string("axis lines* = ", axispos)) + if axis[:draw_arrow] + push!(style, string("axis ", letter, " line = ", axispos)) + else + # the * after line disables the arrow at the axis + push!(style, string("axis ", letter, " line* = ", axispos)) + end end if framestyle == :zerolines From 03325533bf63ba74c4c83691e561b6a67c0bf9da Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 1 May 2019 12:08:35 +0200 Subject: [PATCH 166/230] outer legend positions for pyplot --- src/args.jl | 2 +- src/backends/pyplot.jl | 45 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/args.jl b/src/args.jl index 24676d01..f7ab6d06 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1186,7 +1186,7 @@ function convertLegendValue(val::Symbol) :best elseif val in (:no, :none) :none - elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright) + elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright, :outertopleft, :outertop, :outerright, :outerleft, :outerbottomright, :outerbottomleft, :outerbottom) val else error("Invalid symbol for legend: $val") diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 773b1932..6a8a925d 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -311,6 +311,9 @@ function py_bbox_title(ax) bb end +# bounding box: legend +py_bbox_legend(ax) = py_bbox(ax."get_legend"()) + function py_thickness_scale(plt::Plot{PyPlotBackend}, ptsz) ptsz * plt[:thickness_scaling] end @@ -1188,7 +1191,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend}) toppad = 0mm rightpad = 0mm bottompad = 0mm - for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax)) + for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax), py_bbox_legend(ax)) if ispositive(width(bb)) && ispositive(height(bb)) leftpad = max(leftpad, left(plotbb) - left(bb)) toppad = max(toppad, top(plotbb) - top(bb)) @@ -1251,11 +1254,43 @@ const _pyplot_legend_pos = KW( :topleft => "upper left" ) -py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, "best") +const _pyplot_legend_pos_outer = KW( + :outerright => "center left", + :outerleft => "right", + :outertop => "lower center", + :outerbottom => "upper center", + :outerbottomleft => "lower right", + :outerbottomright => "lower left", + :outertopright => "upper left", + :outertopleft => "upper right" +) + +py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, get(_pyplot_legend_pos_outer, pos, "best")) py_legend_pos(pos) = "lower left" -py_legend_bbox(pos::Symbol) = (0, 0, 1, 1) -py_legend_bbox(pos) = pos +function py_legend_bbox_outer(pos, ax) + pos_str = string(pos) + hor = if occursin("left", pos_str) + -0.15 + elseif occursin("right", pos_str) + 1.0 + else + 0.5 + end + ver = if pos == :outerbottom + -0.15 + elseif occursin("bottom", pos_str) + 0.0 + elseif occursin("top", pos_str) + 1.0 + else + 0.5 + end + return hor, ver, 0.0, 0.0 +end + +py_legend_bbox(pos::Symbol, ax) = pos in keys(_pyplot_legend_pos_outer) ? py_legend_bbox_outer(pos, ax) : (0.0, 0.0, 1.0, 1.0) +py_legend_bbox(pos, ax) = pos function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] @@ -1295,7 +1330,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) leg = ax."legend"(handles, labels, loc = py_legend_pos(leg), - bbox_to_anchor = py_legend_bbox(leg), + bbox_to_anchor = py_legend_bbox(leg, ax), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 903cb404c3d712f3a470d38d28f62f0e538e629c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 1 May 2019 12:12:51 +0200 Subject: [PATCH 167/230] shorter implementation --- src/backends/pyplot.jl | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 6a8a925d..100f15ee 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1268,29 +1268,19 @@ const _pyplot_legend_pos_outer = KW( py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, get(_pyplot_legend_pos_outer, pos, "best")) py_legend_pos(pos) = "lower left" -function py_legend_bbox_outer(pos, ax) - pos_str = string(pos) - hor = if occursin("left", pos_str) - -0.15 - elseif occursin("right", pos_str) - 1.0 - else - 0.5 - end - ver = if pos == :outerbottom - -0.15 - elseif occursin("bottom", pos_str) - 0.0 - elseif occursin("top", pos_str) - 1.0 - else - 0.5 - end - return hor, ver, 0.0, 0.0 -end +const _pyplot_legend_bbox_outer = KW( + :outerright => (1.0, 0.5, 0.0, 0.0), + :outerleft => (-0.15, 0.5, 0.0, 0.0), + :outertop => (0.5, 1.0, 0.0, 0.0), + :outerbottom => (0.5, -0.15, 0.0, 0.0), + :outerbottomleft => (-0.15, 0.0, 0.0, 0.0), + :outerbottomright => (1.0, 0.0, 0.0, 0.0), + :outertopright => (1.0, 1.0, 0.0, 0.0), + :outertopleft => (-0.15, 1.0, 0.0, 0.0) +) -py_legend_bbox(pos::Symbol, ax) = pos in keys(_pyplot_legend_pos_outer) ? py_legend_bbox_outer(pos, ax) : (0.0, 0.0, 1.0, 1.0) -py_legend_bbox(pos, ax) = pos +py_legend_bbox(pos::Symbol) = get(_pyplot_legend_bbox_outer, pos, (0.0, 0.0, 1.0, 1.0)) +py_legend_bbox(pos) = pos function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] @@ -1330,7 +1320,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) leg = ax."legend"(handles, labels, loc = py_legend_pos(leg), - bbox_to_anchor = py_legend_bbox(leg, ax), + bbox_to_anchor = py_legend_bbox(leg), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 0e3a9f0b8fa0c327ddd4e81b8430f7b5a150a64e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:18:17 +0200 Subject: [PATCH 168/230] outer legends for GR --- src/backends/gr.jl | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 2c8341f5..88995a3f 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -535,14 +535,26 @@ function gr_legend_pos(s::Symbol,w,h) xpos = viewport_plotarea[2] - 0.05 - w end elseif occursin("left", str) - xpos = viewport_plotarea[1] + 0.11 + if occursin("outer", str) + xpos = viewport_plotarea[1] - 0.11 - w + else + xpos = viewport_plotarea[1] + 0.11 + end else xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 - w/2 +.04 end if occursin("top", str) - ypos = viewport_plotarea[4] - 0.06 + if s == :outertop + ypos = viewport_plotarea[4] + h + 0.01 + else + ypos = viewport_plotarea[4] - 0.06 + end elseif occursin("bottom", str) - ypos = viewport_plotarea[3] + h + 0.06 + if s == :outerbottom + ypos = viewport_plotarea[3] - 0.11 + else + ypos = viewport_plotarea[3] + h + 0.06 + end else ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + h/2 end @@ -790,8 +802,19 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.restorestate() end - if occursin("outer", string(sp[:legend])) - viewport_plotarea[2] -= legendw + 0.1 + dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 + legendh = dy * legendn + leg_str = string(sp[:legend]) + if occursin("outer", leg_str) + if occursin("right", leg_str) + viewport_plotarea[2] -= legendw + 0.1 + elseif occursin("left", leg_str) + viewport_plotarea[1] += legendw + 0.13 + elseif occursin("top", leg_str) + viewport_plotarea[4] -= legendh + 0.06 + elseif occursin("bottom", leg_str) + viewport_plotarea[3] += legendh + 0.09 + end end # fill in the plot area background From 21774dc36b3a1ba4c74750df4d999822a37b03b5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:27:16 +0200 Subject: [PATCH 169/230] consider rotation in gr_get_ticks_size --- src/backends/gr.jl | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 88995a3f..fde597c1 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -668,17 +668,29 @@ function gr_set_yticks_font(sp) return flip, mirror end -function gr_get_ticks_size(ticks, i) +text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h +text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h + +function gr_text_size(str, rot) GR.savestate() GR.selntran(0) - l = 0.0 - for (cv, dv) in zip(ticks...) - tb = gr_inqtext(0, 0, string(dv))[i] - tb_min, tb_max = extrema(tb) - l = max(l, tb_max - tb_min) - end + xs, ys = gr_inqtext(0, 0, string(str)) + l, r = extrema(xs) + b, t = extrema(ys) + w = text_box_width(r - l, t - b, rot) + h = text_box_height(r - l, t - b, rot) GR.restorestate() - return l + return w, h +end + +function gr_get_ticks_size(ticks, rot) + w, h = 0.0, 0.0 + for (cv, dv) in zip(ticks...) + wi, hi = gr_text_size(dv, rot) + w = max(w, wi) + h = max(h, hi) + end + return w, h end function _update_min_padding!(sp::Subplot{GRBackend}) @@ -701,7 +713,7 @@ function _update_min_padding!(sp::Subplot{GRBackend}) xticks, yticks = axis_drawing_info(sp)[1:2] if !(xticks in (nothing, false, :none)) flip, mirror = gr_set_xticks_font(sp) - l = gr_get_ticks_size(xticks, 2) + l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) if mirror toppad += 1mm + gr_plot_size[2] * l * px else @@ -710,7 +722,7 @@ function _update_min_padding!(sp::Subplot{GRBackend}) end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) - l = gr_get_ticks_size(yticks, 1) + l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) if mirror rightpad += 1mm + gr_plot_size[1] * l * px else From bf0bb68e28537a1bca90f81c119c66eda37f2eeb Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:31:20 +0200 Subject: [PATCH 170/230] only add half of ticks text size to min padding --- src/backends/gr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index fde597c1..bdbcfab2 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -715,18 +715,18 @@ function _update_min_padding!(sp::Subplot{GRBackend}) flip, mirror = gr_set_xticks_font(sp) l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) if mirror - toppad += 1mm + gr_plot_size[2] * l * px + toppad += 1mm + gr_plot_size[2] * l * px / 2 else - bottompad += 1mm + gr_plot_size[2] * l * px + bottompad += 1mm + gr_plot_size[2] * l * px / 2 end end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) if mirror - rightpad += 1mm + gr_plot_size[1] * l * px + rightpad += 1mm + gr_plot_size[1] * l * px / 2 else - leftpad += 1mm + gr_plot_size[1] * l * px + leftpad += 1mm + gr_plot_size[1] * l * px / 2 end end # Add margin for x label From 65173e6dd2de3c605bb0a382c2ffca32e0da482f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 12:48:06 +0200 Subject: [PATCH 171/230] fix recipe error --- src/backends/gr.jl | 4 ++-- src/backends/pyplot.jl | 16 +++++++++------- src/utils.jl | 4 +++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 69b278fd..e9aea7d5 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -784,7 +784,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) tbx, tby = gr_inqtext(0, 0, string(lab)) legendw = max(legendw, tbx[3] - tbx[1]) end - + GR.setscale(1) GR.selntran(1) GR.restorestate() @@ -1139,7 +1139,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end if st in (:path, :scatter, :straightline) - if length(x) > 1 + if x != nothing && length(x) > 1 lz = series[:line_z] segments = iter_segments(series) # do area fill diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 3618412f..624c01f9 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -216,13 +216,15 @@ end # --------------------------------------------------------------------------- function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series) - x, y = series[:x], series[:y] - nx, ny = length(x), length(y) - if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny - if nx < ny - series[:x] = Float64[x[mod1(i,nx)] for i=1:ny] - else - series[:y] = Float64[y[mod1(i,ny)] for i=1:nx] + if series[:x] != nothing + x, y = series[:x], series[:y] + nx, ny = length(x), length(y) + if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny + if nx < ny + series[:x] = Float64[x[mod1(i,nx)] for i=1:ny] + else + series[:y] = Float64[y[mod1(i,ny)] for i=1:nx] + end end end end diff --git a/src/utils.jl b/src/utils.jl index 2d8172f5..6a8cb81e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -194,7 +194,9 @@ end function iter_segments(series::Series) x, y, z = series[:x], series[:y], series[:z] - if has_attribute_segments(series) + if x == nothing + return UnitRange{Int}[] + elseif has_attribute_segments(series) if series[:seriestype] in (:scatter, :scatter3d) return [[i] for i in 1:length(y)] else From dcabb2c5790c9efb1a46fc31d9e183de49dee0a4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 23:04:35 +0200 Subject: [PATCH 172/230] ticks, guides, margins for gr --- src/backends/gr.jl | 123 +++++++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 37 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index bdbcfab2..eb537223 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -522,21 +522,28 @@ end gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2]) gr_view_ycenter() = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4]) -function gr_legend_pos(s::Symbol,w,h) +function gr_legend_pos(sp::Subplot, w, h) + s = sp[:legend] + typeof(s) <: Symbol || return gr_legend_pos(s, w, h) str = string(s) if str == "best" str = "topright" end + if occursin("outer", str) + xaxis, yaxis = sp[:xaxis], sp[:yaxis] + xmirror = xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) + ymirror = yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) + end if occursin("right", str) if occursin("outer", str) # As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525 - xpos = viewport_plotarea[2] + 0.11 + xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_yaxis_width(sp) else xpos = viewport_plotarea[2] - 0.05 - w end elseif occursin("left", str) if occursin("outer", str) - xpos = viewport_plotarea[1] - 0.11 - w + xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_yaxis_width(sp) else xpos = viewport_plotarea[1] + 0.11 end @@ -545,13 +552,13 @@ function gr_legend_pos(s::Symbol,w,h) end if occursin("top", str) if s == :outertop - ypos = viewport_plotarea[4] + h + 0.01 + ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_xaxis_height(sp) else ypos = viewport_plotarea[4] - 0.06 end elseif occursin("bottom", str) if s == :outerbottom - ypos = viewport_plotarea[3] - 0.11 + ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_xaxis_height(sp) else ypos = viewport_plotarea[3] + h + 0.06 end @@ -668,8 +675,17 @@ function gr_set_yticks_font(sp) return flip, mirror end -text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h -text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h +function gr_text_size(str) + GR.savestate() + GR.selntran(0) + xs, ys = gr_inqtext(0, 0, string(str)) + l, r = extrema(xs) + b, t = extrema(ys) + w = r - l + h = t - b + GR.restorestate() + return w, h +end function gr_text_size(str, rot) GR.savestate() @@ -683,6 +699,9 @@ function gr_text_size(str, rot) return w, h end +text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h +text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h + function gr_get_ticks_size(ticks, rot) w, h = 0.0, 0.0 for (cv, dv) in zip(ticks...) @@ -693,6 +712,30 @@ function gr_get_ticks_size(ticks, rot) return w, h end +function gr_xaxis_height(sp) + xaxis = sp[:xaxis] + xticks, yticks = axis_drawing_info(sp)[1:2] + gr_set_font(tickfont(xaxis)) + h = (xticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(xticks, xaxis[:rotation]))) + if xaxis[:guide] != "" + gr_set_font(guidefont(xaxis)) + h += last(gr_text_size(xaxis[:guide])) + end + return h +end + +function gr_yaxis_width(sp) + yaxis = sp[:yaxis] + xticks, yticks = axis_drawing_info(sp)[1:2] + gr_set_font(tickfont(yaxis)) + w = (xticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(yticks, yaxis[:rotation]))) + if yaxis[:guide] != "" + gr_set_font(guidefont(yaxis)) + w += last(gr_text_size(yaxis[:guide])) + end + return w +end + function _update_min_padding!(sp::Subplot{GRBackend}) dpi = sp.plt[:thickness_scaling] if !haskey(ENV, "GKSwstype") @@ -701,48 +744,59 @@ function _update_min_padding!(sp::Subplot{GRBackend}) end end # Add margin given by the user - leftpad = 4mm + sp[:left_margin] + leftpad = 2mm + sp[:left_margin] toppad = 2mm + sp[:top_margin] - rightpad = 4mm + sp[:right_margin] + rightpad = 2mm + sp[:right_margin] bottompad = 2mm + sp[:bottom_margin] # Add margin for title if sp[:title] != "" - toppad += 5mm + gr_set_font(titlefont(sp)) + l = last(last(gr_text_size(sp[:title]))) + h = 1mm + gr_plot_size[2] * l * px + toppad += h end # Add margin for x and y ticks xticks, yticks = axis_drawing_info(sp)[1:2] if !(xticks in (nothing, false, :none)) flip, mirror = gr_set_xticks_font(sp) - l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) + l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) + h = 1mm + gr_plot_size[2] * l * px if mirror - toppad += 1mm + gr_plot_size[2] * l * px / 2 + toppad += h else - bottompad += 1mm + gr_plot_size[2] * l * px / 2 + bottompad += h end end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) - l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) + l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) + w = 1mm + gr_plot_size[1] * l * px if mirror - rightpad += 1mm + gr_plot_size[1] * l * px / 2 + rightpad += w else - leftpad += 1mm + gr_plot_size[1] * l * px / 2 + leftpad += w end end # Add margin for x label if sp[:xaxis][:guide] != "" + gr_set_font(guidefont(sp[:xaxis])) + l = last(gr_text_size(sp[:xaxis][:guide])) + h = 1mm + gr_plot_size[2] * l * px if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true) - toppad += 4mm + toppad += h else - bottompad += 4mm + bottompad += h end end # Add margin for y label if sp[:yaxis][:guide] != "" + gr_set_font(guidefont(sp[:yaxis])) + l = last(gr_text_size(sp[:yaxis][:guide])) + w = 1mm + gr_plot_size[2] * l * px if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true) - rightpad += 4mm + rightpad += w else - leftpad += 4mm + leftpad += w end end if sp[:colorbar_title] != "" @@ -819,13 +873,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) leg_str = string(sp[:legend]) if occursin("outer", leg_str) if occursin("right", leg_str) - viewport_plotarea[2] -= legendw + 0.1 + viewport_plotarea[2] -= legendw + 0.11 elseif occursin("left", leg_str) - viewport_plotarea[1] += legendw + 0.13 + viewport_plotarea[1] += legendw + 0.11 elseif occursin("top", leg_str) - viewport_plotarea[4] -= legendh + 0.06 + viewport_plotarea[4] -= legendh + 0.03 elseif occursin("bottom", leg_str) - viewport_plotarea[3] += legendh + 0.09 + viewport_plotarea[3] += legendh + 0.04 end end @@ -1096,34 +1150,29 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) gr_set_font(guidefont(xaxis)) GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide]) else + xticks, yticks = axis_drawing_info(sp)[1:2] if xaxis[:guide] != "" + h = 0.01 + gr_xaxis_height(sp) gr_set_font(guidefont(xaxis)) if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide]) + gr_text(gr_view_xcenter(), viewport_plotarea[4] + h, xaxis[:guide]) else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide]) + gr_text(gr_view_xcenter(), viewport_plotarea[3] - h, xaxis[:guide]) end end if yaxis[:guide] != "" + w = 0.02 + gr_yaxis_width(sp) gr_set_font(guidefont(yaxis)) GR.setcharup(-1, 0) if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - if viewport_plotarea[1] - viewport_subplot[1] > 0.1 - gr_text(viewport_plotarea[2] + 0.025, gr_view_ycenter(), yaxis[:guide]) - else - gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) - end + gr_text(viewport_plotarea[2] + w, gr_view_ycenter(), yaxis[:guide]) else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - if viewport_plotarea[1] - viewport_subplot[1] > 0.1 - gr_text(viewport_plotarea[1] - 0.075, gr_view_ycenter(), yaxis[:guide]) - else - gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) - end + gr_text(viewport_plotarea[1] - w, gr_view_ycenter(), yaxis[:guide]) end end end @@ -1396,7 +1445,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if w > 0 dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 h = dy*n - (xpos,ypos) = gr_legend_pos(sp[:legend],w,h) + xpos, ypos = gr_legend_pos(sp, w, h) GR.setfillintstyle(GR.INTSTYLE_SOLID) gr_set_fillcolor(sp[:background_color_legend]) GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n) From c3990922611ab76c83a43ac9996589004b42f59a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 4 May 2019 20:43:49 +0200 Subject: [PATCH 173/230] fix animations for pyplot --- src/backends/pyplot.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 100f15ee..f38914ab 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -273,6 +273,8 @@ function py_bbox(obj) BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px) end +py_bbox(::Nothing) = BoundingBox(0mm, 0mm) + # get the bounding box of the union of the objects function py_bbox(v::AVec) bbox_union = defaultbox From 0dba83daf605404c0da273a1ec20ed1489c6fa6a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 May 2019 13:08:03 +0200 Subject: [PATCH 174/230] fix gr alphas --- src/backends/gr.jl | 82 ++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index eb537223..e3a543e4 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -80,6 +80,8 @@ gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1))) gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1))) gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1)) gr_set_transparency(::Nothing) = GR.settransparency(1) +gr_set_transparency(c, α) = gr_set_transparency(α) +gr_set_transparency(c::Colorant, ::Nothing) = GR.settransparency(alpha(c)) # -------------------------------------------------------------------------------------- @@ -167,7 +169,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot) #draw angular grid if xaxis[:grid] gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) for i in 1:length(α) GR.polyline([sinf[i], 0], [cosf[i], 0]) end @@ -176,7 +178,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot) #draw radial grid if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) for i in 1:length(rtick_values) r = (rtick_values[i] - rmin) / (rmax - rmin) if r <= 1.0 && r >= 0.0 @@ -296,15 +298,17 @@ function gr_draw_markers(series::Series, x, y, clims, msize = series[:markersize # draw a filled in shape, slightly bigger, to estimate a stroke if series[:markerstrokewidth] > 0 - cfunc(get_markerstrokecolor(series, i)) - gr_set_transparency(get_markerstrokealpha(series, i)) + c = get_markerstrokecolor(series, i) + cfunc(c) + gr_set_transparency(c, get_markerstrokealpha(series, i)) gr_draw_marker(x[i], y[i], msi + series[:markerstrokewidth], shape) end # draw the shape - don't draw filled area if marker shape is 1D if !(shape in (:hline, :vline, :+, :x)) - cfunc(get_markercolor(series, clims, i)) - gr_set_transparency(get_markeralpha(series, i)) + c = get_markercolor(series, clims, i) + cfunc(c) + gr_set_transparency(c, get_markeralpha(series, i)) gr_draw_marker(x[i], y[i], msi, shape) end end @@ -981,21 +985,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:grid] gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0) end if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0) end if zaxis[:grid] gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid]) - gr_set_transparency(zaxis[:gridalpha]) + gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha]) GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2) end gr_set_line(1, :solid, xaxis[:foreground_color_axis]) - gr_set_transparency(1) + gr_set_transparency(xaxis[:foreground_color_axis]) GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize) GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize) @@ -1018,24 +1022,24 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # gr_set_linecolor(sp[:foreground_color_grid]) # GR.grid(xtick, ytick, 0, 0, majorx, majory) gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) gr_polyline(coords(xgrid_segs)...) end if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) gr_polyline(coords(ygrid_segs)...) end if xaxis[:minorgrid] # gr_set_linecolor(sp[:foreground_color_grid]) # GR.grid(xtick, ytick, 0, 0, majorx, majory) gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid]) - gr_set_transparency(xaxis[:minorgridalpha]) + gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha]) gr_polyline(coords(xminorgrid_segs)...) end if yaxis[:minorgrid] gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid]) - gr_set_transparency(yaxis[:minorgridalpha]) + gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha]) gr_polyline(coords(yminorgrid_segs)...) end gr_set_transparency(1.0) @@ -1057,7 +1061,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0) else gr_set_line(1, :solid, xaxis[:foreground_color_axis]) end @@ -1067,7 +1071,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0) else gr_set_line(1, :solid, yaxis[:foreground_color_axis]) end @@ -1119,10 +1123,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) intensity = sp[:framestyle] == :semi ? 0.5 : 1.0 if sp[:framestyle] in (:box, :semi) gr_set_line(intensity, :solid, xaxis[:foreground_color_border]) - gr_set_transparency(intensity) + gr_set_transparency(xaxis[:foreground_color_border], intensity) gr_polyline(coords(xborder_segs)...) gr_set_line(intensity, :solid, yaxis[:foreground_color_border]) - gr_set_transparency(intensity) + gr_set_transparency(yaxis[:foreground_color_border], intensity) gr_polyline(coords(yborder_segs)...) end end @@ -1231,10 +1235,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.setfillintstyle(GR.INTSTYLE_SOLID) fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng)) for (i, rng) in enumerate(segments) - gr_set_fillcolor(get_fillcolor(series, clims, i)) + fc = get_fillcolor(series, clims, i) + gr_set_fillcolor(fc) fx = _cycle(x, vcat(rng, reverse(rng))) fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng))) - gr_set_transparency(get_fillalpha(series, i)) + gr_set_transparency(fc, get_fillalpha(series, i)) GR.fillarea(fx, fy) end end @@ -1242,8 +1247,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # draw the line(s) if st in (:path, :straightline) for (i, rng) in enumerate(segments) - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha]) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) + gr_set_transparency(lc, get_linealpha(series, i)) arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none gr_polyline(x[rng], y[rng]; arrowside = arrowside) end @@ -1317,8 +1323,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) lz = series[:line_z] segments = iter_segments(series) for (i, rng) in enumerate(segments) - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha]) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) + gr_set_transparency(lc, get_linealpha(series, i)) GR.polyline3d(x[rng], y[rng], z[rng]) end end @@ -1389,13 +1396,15 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) xseg, yseg = x[rng], y[rng] # draw the interior - gr_set_fill(get_fillcolor(series, clims, i)) - gr_set_transparency(get_fillalpha(series, i)) + fc = get_fillcolor(series, clims, i) + gr_set_fill(fc) + gr_set_transparency(fc, get_fillalpha(series, i)) GR.fillarea(xseg, yseg) # draw the shapes - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) + gr_set_transparency(lc, get_linealpha(series, i)) GR.polyline(xseg, yseg) end end @@ -1455,30 +1464,33 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if sp[:legendtitle] != nothing GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF) gr_set_textcolor(sp[:legendfontcolor]) - gr_set_transparency(1) + gr_set_transparency(sp[:legendfontcolor]) gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle])) ypos -= dy end for series in series_list(sp) should_add_to_legend(series) || continue st = series[:seriestype] - gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) #, series[:linealpha]) + lc = get_linecolor(series, clims) + gr_set_line(get_linewidth(series), get_linestyle(series), lc) #, series[:linealpha]) if (st == :shape || series[:fillrange] != nothing) && series[:ribbon] == nothing - gr_set_fill(get_fillcolor(series, clims)) #, series[:fillalpha]) + fc = get_fillcolor(series, clims) + gr_set_fill(fc) #, series[:fillalpha]) l, r = xpos-0.07, xpos-0.01 b, t = ypos-0.4dy, ypos+0.4dy x = [l, r, r, l, l] y = [b, b, t, t, b] - gr_set_transparency(get_fillalpha(series)) + gr_set_transparency(fc, get_fillalpha(series)) gr_polyline(x, y, GR.fillarea) - gr_set_transparency(get_linealpha(series)) - gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) + lc = get_linecolor(series, clims) + gr_set_transparency(lc, get_linealpha(series)) + gr_set_line(get_linewidth(series), get_linestyle(series), lc) st == :shape && gr_polyline(x, y) end if st in (:path, :straightline) - gr_set_transparency(get_linealpha(series)) + gr_set_transparency(lc, get_linealpha(series)) if series[:fillrange] == nothing || series[:ribbon] != nothing GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos]) else From 34cff752f10a082a6ce9f0504ab1ccf363ab543c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 May 2019 13:22:16 +0200 Subject: [PATCH 175/230] missing method for gr_set_transparency --- src/backends/gr.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e3a543e4..8da4520e 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -81,7 +81,8 @@ gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1))) gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1)) gr_set_transparency(::Nothing) = GR.settransparency(1) gr_set_transparency(c, α) = gr_set_transparency(α) -gr_set_transparency(c::Colorant, ::Nothing) = GR.settransparency(alpha(c)) +gr_set_transparency(c::Colorant, ::Nothing) = gr_set_transparency(c) +gr_set_transparency(c::Colorant) = GR.settransparency(alpha(c)) # -------------------------------------------------------------------------------------- From 169851564ce9d7a5d72081b04ee5879f6c8c798c Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Wed, 8 May 2019 17:23:36 +0200 Subject: [PATCH 176/230] use Project.toml + clean up test deps --- .gitignore | 1 + .travis.yml | 50 ++++------------------------------------ Project.toml | 55 ++++++++++++++++++++++++++++++++++++++++++++ test/REQUIRE | 10 -------- test/add_packages.jl | 46 ------------------------------------ test/runtests.jl | 7 +++++- test/snoop.jl | 36 ----------------------------- 7 files changed, 67 insertions(+), 138 deletions(-) create mode 100644 Project.toml delete mode 100644 test/REQUIRE delete mode 100644 test/add_packages.jl delete mode 100644 test/snoop.jl diff --git a/.gitignore b/.gitignore index 8b7142dd..1bac5f19 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ examples/meetup/.ipynb_checkpoints/* deps/plotly-latest.min.js deps/build.log deps/deps.jl +Manifest.toml diff --git a/.travis.yml b/.travis.yml index e236fe4f..fc303b0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,57 +4,17 @@ os: - linux # - osx julia: - # - 1.0 + - 1.1 - nightly -# matrix: -# allow_failures: -# - julia: nightly - -# # before install: -# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi -# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install wkhtmltopdf; fi - -# ref: http://askubuntu.com/a/556672 for the wkhtmltopdf apt repository info + +matrix: + allow_failures: + - julia: nightly sudo: required before_install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./test/install_wkhtmltoimage.sh ; fi -# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:pov/wkhtmltopdf ; fi -# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi -# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y wkhtmltopdf ; fi -# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltopdf -V ; fi -# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltoimage -V ; fi -# echo 'exec xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@"' | sudo tee /usr/local/bin/wkhtmltopdf.sh >/dev/null -# sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh - -# # borrowed from Blink.jl's travis file -# matrix: -# include: -# - os: linux -# julia: 0.4 -# env: TESTCMD="xvfb-run julia" -# - os: osx -# julia: 0.4 -# env: TESTCMD="julia" - - notifications: email: true -# uncomment the following lines to override the default test script -# script: - # - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - # - julia -e 'import Pkg; Pkg.add(Pkg.PackageSpec(path=pwd())); Pkg.build("Plots")' - # - julia test/travis_commands.jl - # - julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")' - # - julia -e 'Pkg.clone("GR"); Pkg.build("GR")' - # # - julia -e 'Pkg.clone("https://github.com/tbreloff/ImageMagick.jl.git"); Pkg.checkout("ImageMagick","tb_write"); Pkg.build("ImageMagick")' - # - julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");' - # # - julia -e 'Pkg.clone("https://github.com/JunoLab/Blink.jl.git"); Pkg.build("Blink"); import Blink; Blink.AtomShell.install()' - # # - julia -e 'Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")' - # - julia -e 'ENV["PYTHON"] = ""; Pkg.add("PyPlot"); Pkg.build("PyPlot")' - # - # # - $TESTCMD -e 'Pkg.test("Plots"; coverage=false)' - # - julia -e 'Pkg.test("Plots"; coverage=false)' - # # - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())' diff --git a/Project.toml b/Project.toml new file mode 100644 index 00000000..e59e581a --- /dev/null +++ b/Project.toml @@ -0,0 +1,55 @@ +name = "Plots" +uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" + +[deps] +Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e" +NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlotReferenceImages = "c5e800db-1e6b-5f72-915a-308d267b7a19" +PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" +PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +Requires = "ae029012-a4dd-5104-9daa-d747884805df" +Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[compat] +FixedPointNumbers = "≥ 0.3.0" +GR = "≥ 0.31.0" +PlotThemes = "≥ 0.1.3" +PlotUtils = "≥ 0.4.1" +RecipesBase = "≥ 0.6.0" +StatsBase = "≥ 0.14.0" +julia = "≥ 1.0.0" + +[extras] +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" +Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" +LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" +VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" + +[targets] +test = ["Pkg", "GR", "Test", "Random", "StatsPlots", "VisualRegressionTests", "LaTeXStrings", "Images", "ImageMagick", "RDatasets", "FileIO", "UnicodePlots"] diff --git a/test/REQUIRE b/test/REQUIRE deleted file mode 100644 index 06f37166..00000000 --- a/test/REQUIRE +++ /dev/null @@ -1,10 +0,0 @@ -StatsPlots -Images -ImageMagick -@osx QuartzImageIO -FileIO -GR 0.31.0 -RDatasets -VisualRegressionTests -UnicodePlots -LaTeXStrings diff --git a/test/add_packages.jl b/test/add_packages.jl deleted file mode 100644 index 4e27bb30..00000000 --- a/test/add_packages.jl +++ /dev/null @@ -1,46 +0,0 @@ -using Pkg - -# need this to use Conda -# ENV["PYTHON"] = "" - -to_add = [ - # PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"), - PackageSpec(name="PlotUtils", rev="master"), - PackageSpec(name="RecipesBase", rev="master"), - # PackageSpec(name="Blink", rev="master"), - # PackageSpec(name="Rsvg", rev="master"), - # PackageSpec(name="PlotlyJS", rev="master"), - # PackageSpec(name="VisualRegressionTests", rev="master"), - # PackageSpec("PyPlot"), - # PackageSpec("InspectDR"), -] - -if isinteractive() - Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) - append!(to_add, [ - PackageSpec(name="FileIO"), - PackageSpec(name="ImageMagick"), - PackageSpec(name="UnicodePlots"), - PackageSpec(name="VisualRegressionTests"), - PackageSpec(name="Gtk"), - # PlotlyJS: - # PackageSpec(name="PlotlyJS"), - # PackageSpec(name="Blink"), - # PackageSpec(name="ORCA"), - # PyPlot: - # PackageSpec(name="PyPlot"), - # PackageSpec(name="PyCall"), - # PackageSpec(name="LaTeXStrings"), - ]) -else - push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git")) -end - -Pkg.add(to_add) - -Pkg.build("ImageMagick") -# Pkg.build("GR") -# Pkg.build("Blink") -# import Blink -# Blink.AtomShell.install() -# Pkg.build("PyPlot") diff --git a/test/runtests.jl b/test/runtests.jl index 906c5804..924aa2ea 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,13 @@ module PlotsTests -include("add_packages.jl") +using Pkg + +# This should be fine since it's run in it's own test env? +pkg"add https://github.com/JuliaPlots/PlotReferenceImages.jl.git" + include("imgcomp.jl") + # don't actually show the plots Random.seed!(1234) default(show=false, reuse=true) diff --git a/test/snoop.jl b/test/snoop.jl deleted file mode 100644 index cf137d63..00000000 --- a/test/snoop.jl +++ /dev/null @@ -1,36 +0,0 @@ -import SnoopCompile - -### Log the compiles -# This only needs to be run once (to generate "/tmp/plots_compiles.csv") - -# SnoopCompile.@snoop "/tmp/plots_compiles.csv" begin -# include(joinpath(dirname(@__FILE__), "runtests.jl")) -# end - -# ---------------------------------------------------------- - -### Parse the compiles and generate precompilation scripts -# This can be run repeatedly to tweak the scripts - -# IMPORTANT: we must have the module(s) defined for the parcelation -# step, otherwise we will get no precompiles for the Plots module -using Plots - -data = SnoopCompile.read("/tmp/plots_compiles.csv") - -# The Plots tests are run inside a module PlotsTest, so all -# the precompiles get credited to PlotsTest. Credit them to Plots instead. -subst = Dict("PlotsTests"=>"Plots") - -# Blacklist helps fix problems: -# - MIME uses type-parameters with symbols like :image/png, which is -# not parseable -blacklist = ["MIME"] - -# Use these two lines if you want to create precompile functions for -# individual packages -pc, discards = SnoopCompile.parcel(data[end:-1:1,2], subst=subst, blacklist=blacklist) -SnoopCompile.write("/tmp/precompile", pc) - -pdir = joinpath(dirname(@__FILE__), "..") -run(`cp /tmp/precompile/precompile_Plots.jl $pdir/src/precompile.jl`) From 63f8f52c9f27b7cd00bba7fa1bdd89b3f215fb0c Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 11:06:22 +0200 Subject: [PATCH 177/230] remove REQUIRES --- REQUIRE | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 REQUIRE diff --git a/REQUIRE b/REQUIRE deleted file mode 100644 index bd236535..00000000 --- a/REQUIRE +++ /dev/null @@ -1,16 +0,0 @@ -julia 1.0 - -RecipesBase 0.6.0 -PlotUtils 0.4.1 -PlotThemes 0.1.3 -Reexport -GeometryTypes -FixedPointNumbers 0.3 -Measures -Showoff -StatsBase 0.14.0 -JSON -NaNMath -Requires -Contour -GR 0.39.0 From a3be970f29f42e4b714caef6e4009fbde573a274 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 11:48:40 +0200 Subject: [PATCH 178/230] get around registered PLotReferenceImages by downloading source of tags --- Project.toml => .Project.toml | 0 REQUIRE | 16 +++++++++++ test/.gitignore | 1 + test/REQUIRE | 11 ++++++++ test/imgcomp.jl | 51 ++++++++++++++++++++--------------- test/runtests.jl | 3 --- 6 files changed, 57 insertions(+), 25 deletions(-) rename Project.toml => .Project.toml (100%) create mode 100644 REQUIRE create mode 100644 test/.gitignore create mode 100644 test/REQUIRE diff --git a/Project.toml b/.Project.toml similarity index 100% rename from Project.toml rename to .Project.toml diff --git a/REQUIRE b/REQUIRE new file mode 100644 index 00000000..bd236535 --- /dev/null +++ b/REQUIRE @@ -0,0 +1,16 @@ +julia 1.0 + +RecipesBase 0.6.0 +PlotUtils 0.4.1 +PlotThemes 0.1.3 +Reexport +GeometryTypes +FixedPointNumbers 0.3 +Measures +Showoff +StatsBase 0.14.0 +JSON +NaNMath +Requires +Contour +GR 0.39.0 diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 00000000..2a6ccb02 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +reference_images diff --git a/test/REQUIRE b/test/REQUIRE new file mode 100644 index 00000000..f357d290 --- /dev/null +++ b/test/REQUIRE @@ -0,0 +1,11 @@ +FileIO +ImageMagick +Images +LaTeXStrings +RDatasets +Random +StatsPlots +Test +UnicodePlots +VisualRegressionTests +BinaryProvider diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 6d7dd457..c8ae9966 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -1,26 +1,7 @@ - using VisualRegressionTests -# using ExamplePlots - -if isinteractive() - @eval Main import Gtk -end - -# import DataFrames, RDatasets - -# don't let pyplot use a gui... it'll crash -# note: Agg will set gui -> :none in PyPlot -# ENV["MPLBACKEND"] = "Agg" -# try -# @eval import PyPlot -# @info("Matplotlib version: $(PyPlot.matplotlib[:__version__])") -# end - - using Plots -# using StatsPlots -import PlotReferenceImages using Random +using BinaryProvider using Test default(size=(500,300)) @@ -31,6 +12,33 @@ default(size=(500,300)) import Plots._current_plots_version +# Taken from MakieGallery +""" +Downloads the reference images from ReferenceImages for a specific version +""" +function download_reference(version = v"0.0.1") + download_dir = abspath(@__DIR__, "reference_images") + isdir(download_dir) || mkpath(download_dir) + tarfile = joinpath(download_dir, "reference_images.zip") + url = "https://github.com/JuliaPlots/PlotReferenceImages.jl/archive/v$(version).tar.gz" + refpath = joinpath(download_dir, "PlotReferenceImages.jl-$(version)") + if !isdir(refpath) # if not yet downloaded + @info "downloading reference images for version $version" + download(url, tarfile) + BinaryProvider.unpack(tarfile, download_dir) + # check again after download + if !isdir(refpath) + error("Something went wrong while downloading reference images. Plots can't be compared to references") + else + rm(tarfile, force = true) + end + else + @info "using reference images for version $version (already downloaded)" + end + refpath +end + +const ref_image_dir = download_reference() function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) Plots._debugMode.on = debug @@ -43,8 +51,7 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is Random.seed!(1234) # reference image directory setup - # refdir = joinpath(Pkg.dir("ExamplePlots"), "test", "refimg", string(pkg)) - refdir = joinpath(dirname(pathof(PlotReferenceImages)), "..", "Plots", string(pkg)) + refdir = joinpath(ref_image_dir, "Plots", string(pkg)) fn = "ref$idx.png" # firgure out version info diff --git a/test/runtests.jl b/test/runtests.jl index 924aa2ea..167eb6a1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,9 +2,6 @@ module PlotsTests using Pkg -# This should be fine since it's run in it's own test env? -pkg"add https://github.com/JuliaPlots/PlotReferenceImages.jl.git" - include("imgcomp.jl") From d5f3a3ef69ed9db9a59e6c46c2c9099012a4d519 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 12:40:19 +0200 Subject: [PATCH 179/230] clean up & fix tests --- src/examples.jl | 5 +- test/imgcomp.jl | 20 +++----- test/runtests.jl | 122 +++-------------------------------------------- 3 files changed, 15 insertions(+), 132 deletions(-) diff --git a/src/examples.jl b/src/examples.jl index 9e382eef..6dd1b7f4 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -86,8 +86,9 @@ yaxis!("YLABEL", :log10) PlotExample("Images", "Plot an image. y-axis is set to flipped", [:(begin - import FileIO, PlotReferenceImages - img = FileIO.load(joinpath(dirname(pathof(PlotReferenceImages)), "..", "Plots","pyplot","0.7.0","ref1.png")) + import FileIO + path = download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png") + img = FileIO.load(path) plot(img) end)] ), diff --git a/test/imgcomp.jl b/test/imgcomp.jl index c8ae9966..e61a47c9 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -1,15 +1,3 @@ -using VisualRegressionTests -using Plots -using Random -using BinaryProvider -using Test - -default(size=(500,300)) - - -# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that -# is referenced in a button press callback (the button clicked callback will call notify() on that condition) - import Plots._current_plots_version # Taken from MakieGallery @@ -43,10 +31,11 @@ const ref_image_dir = download_reference() function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2) Plots._debugMode.on = debug example = Plots._examples[idx] + Plots.theme(:default) @info("Testing plot: $pkg:$idx:$(example.header)") backend(pkg) backend() - + default(size=(500,300)) # ensure consistent results Random.seed!(1234) @@ -83,7 +72,10 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is # test function func = (fn, idx) -> begin - map(eval, example.exprs) + expr = Expr(:block) + append!(expr.args, example.exprs) + eval(expr) + png(joinpath(@__DIR__, "testimgs", "test$idx.png")) png(fn) end diff --git a/test/runtests.jl b/test/runtests.jl index 167eb6a1..8e6ef9c1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,11 @@ -module PlotsTests - -using Pkg +using VisualRegressionTests +using Plots +using Random +using BinaryProvider +using Test +using FileIO include("imgcomp.jl") - - # don't actually show the plots Random.seed!(1234) default(show=false, reuse=true) @@ -21,14 +22,6 @@ img_tol = isinteractive() ? 1e-2 : 10e-2 end end -# @static if isinteractive() -# @testset "PyPlot" begin -# @test pyplot() == Plots.PyPlotBackend() -# @test backend() == Plots.PyPlotBackend() -# -# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31]) -# end -# end @testset "UnicodePlots" begin @test unicodeplots() == Plots.UnicodePlotsBackend() @@ -43,68 +36,6 @@ end @test isa(display(p), Nothing) == true end -# The plotlyjs testimages return a connection error on travis: -# connect: connection refused (ECONNREFUSED) - -# @static if isinteractive() -# @testset "PlotlyJS" begin -# @test plotlyjs() == Plots.PlotlyJSBackend() -# @test backend() == Plots.PlotlyJSBackend() -# -# image_comparison_facts(:plotlyjs, -# skip=[ -# 2, # animation (skipped for speed) -# 25, -# 27, # (polar plots) takes very long / not working -# 30, -# 31, # animation (skipped for speed) -# ], -# tol=img_tol) -# end -# end - -# InspectDR returns that error on travis: -# ERROR: LoadError: InitError: Cannot open display: -# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17 - -# @testset "InspectDR" begin -# @test inspectdr() == Plots.InspectDRBackend() -# @test backend() == Plots.InspectDRBackend() -# -# image_comparison_facts(:inspectdr, -# skip=[ -# 2, # animation -# 6, # heatmap not defined -# 10, # heatmap not defined -# 22, # contour not defined -# 23, # pie not defined -# 27, # polar plot not working -# 28, # heatmap not defined -# 31, # animation -# ], -# tol=img_tol) -# end - - -# @testset "Plotly" begin -# @test plotly() == Plots.PlotlyBackend() -# @test backend() == Plots.PlotlyBackend() -# -# # # until png generation is reliable on OSX, just test on linux -# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol) -# end - -# @testset "PlotlyJS" begin -# @test plotlyjs() == Plots.PlotlyJSBackend() -# @test backend() == Plots.PlotlyJSBackend() -# -# # as long as we can plot anything without error, it should be the same as Plotly -# image_comparison_facts(:plotlyjs, only=[1], tol=img_tol) -# end - - - - @testset "Axes" begin p = plot() axis = p.subplots[1][:xaxis] @@ -122,44 +53,3 @@ end @testset "NoFail" begin histogram([1, 0, 0, 0, 0, 0]) end - -# tests for preprocessing recipes - -# @testset "recipes" begin - - # user recipe - - # type T end - # @recipe function f(::T) - # line := (3,0.3,:red) - # marker := (20,0.5,:blue,:o) - # bg := :yellow - # rand(10) - # end - # plot(T()) - - # plot recipe - - # @recipe function f(::Type{Val{:hiplt}},plt::Plot) - # line := (3,0.3,:red) - # marker := (20,0.5,:blue,:o) - # t := :path - # bg:=:green - # () - # end - # plot(rand(10),t=:hiplt) - - # series recipe - - # @recipe function f(::Type{Val{:hi}},x,y,z) - # line := (3,0.3,:red) - # marker := (20,0.5,:blue,:o) - # t := :path - # () - # end - # plot(rand(10),t=:hiplt) - -# end - - -end # module From 379a320d2dcddbc172b44ff4d3c3eebe941119b2 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 12:45:13 +0200 Subject: [PATCH 180/230] remove debug --- test/REQUIRE | 2 -- test/imgcomp.jl | 1 - 2 files changed, 3 deletions(-) diff --git a/test/REQUIRE b/test/REQUIRE index f357d290..c469edc8 100644 --- a/test/REQUIRE +++ b/test/REQUIRE @@ -3,9 +3,7 @@ ImageMagick Images LaTeXStrings RDatasets -Random StatsPlots -Test UnicodePlots VisualRegressionTests BinaryProvider diff --git a/test/imgcomp.jl b/test/imgcomp.jl index e61a47c9..206b8d50 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -75,7 +75,6 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is expr = Expr(:block) append!(expr.args, example.exprs) eval(expr) - png(joinpath(@__DIR__, "testimgs", "test$idx.png")) png(fn) end From 8cd48bc6601e05a6567b487b7149e6d3109a2415 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 13:01:49 +0200 Subject: [PATCH 181/230] add back tomls --- .Project.toml => Project.toml | 4 ++-- REQUIRE | 16 ---------------- test/REQUIRE | 9 --------- 3 files changed, 2 insertions(+), 27 deletions(-) rename .Project.toml => Project.toml (90%) delete mode 100644 REQUIRE delete mode 100644 test/REQUIRE diff --git a/.Project.toml b/Project.toml similarity index 90% rename from .Project.toml rename to Project.toml index e59e581a..ef757d7e 100644 --- a/.Project.toml +++ b/Project.toml @@ -39,7 +39,6 @@ julia = "≥ 1.0.0" [extras] FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" @@ -50,6 +49,7 @@ StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" +BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232" [targets] -test = ["Pkg", "GR", "Test", "Random", "StatsPlots", "VisualRegressionTests", "LaTeXStrings", "Images", "ImageMagick", "RDatasets", "FileIO", "UnicodePlots"] +test = ["BinaryProvider", "Pkg", "Test", "Random", "StatsPlots", "VisualRegressionTests", "LaTeXStrings", "Images", "ImageMagick", "RDatasets", "FileIO", "UnicodePlots"] diff --git a/REQUIRE b/REQUIRE deleted file mode 100644 index bd236535..00000000 --- a/REQUIRE +++ /dev/null @@ -1,16 +0,0 @@ -julia 1.0 - -RecipesBase 0.6.0 -PlotUtils 0.4.1 -PlotThemes 0.1.3 -Reexport -GeometryTypes -FixedPointNumbers 0.3 -Measures -Showoff -StatsBase 0.14.0 -JSON -NaNMath -Requires -Contour -GR 0.39.0 diff --git a/test/REQUIRE b/test/REQUIRE deleted file mode 100644 index c469edc8..00000000 --- a/test/REQUIRE +++ /dev/null @@ -1,9 +0,0 @@ -FileIO -ImageMagick -Images -LaTeXStrings -RDatasets -StatsPlots -UnicodePlots -VisualRegressionTests -BinaryProvider From d0830b90be15d3d673f3c5bbc47ab4bdf4850b8c Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 9 May 2019 13:06:05 +0200 Subject: [PATCH 182/230] remove PlotReferenceImages --- Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Project.toml b/Project.toml index ef757d7e..d7e0a52d 100644 --- a/Project.toml +++ b/Project.toml @@ -13,7 +13,6 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e" NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -PlotReferenceImages = "c5e800db-1e6b-5f72-915a-308d267b7a19" PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" From a99783dfa02951c203b8b97c85c759af2bd92dbf Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 10 May 2019 17:45:56 +0200 Subject: [PATCH 183/230] add author and version --- Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index d7e0a52d..99907026 100644 --- a/Project.toml +++ b/Project.toml @@ -1,5 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +author = ["Tom Breloff (@tbreloff)"] +version = "0.25.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" From 405df5da8bab86dfd8e708d70f9a5509f62495b4 Mon Sep 17 00:00:00 2001 From: shipengcheng1230 Date: Sun, 12 May 2019 13:14:03 -0400 Subject: [PATCH 184/230] fix gr_display --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 473f6bd1..e227eaa4 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -860,7 +860,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) legendn += 1 if typeof(series[:label]) <: Array legendi += 1 - lab = series[:label][i] + lab = series[:label][legendi] else lab = series[:label] end From cdc5a2b361c8f2077e73fa6cf0f6942dbffdc5fe Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 13 May 2019 22:13:27 +0200 Subject: [PATCH 185/230] up version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 99907026..2581cbc9 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" author = ["Tom Breloff (@tbreloff)"] -version = "0.25.0" +version = "0.25.1" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" From bc8370eadd9514d1ed583e893859c9f0ab05c464 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 13 May 2019 22:16:18 +0200 Subject: [PATCH 186/230] update NEWS.md --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7c3d71ac..130921c8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,9 @@ --- ## (current master) +## 0.25.1 +- fix gr_display + ## 0.25.0 - Replace StaticArrays with GeometryTypes - Contour fixes for GR From 9a445d529dd1069878e8ebfe48ef1c547c4bb3e8 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 17 May 2019 10:41:01 +0200 Subject: [PATCH 187/230] Make sure show return nothing. --- src/animation.jl | 1 + src/output.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/src/animation.jl b/src/animation.jl index 4f9ff6da..f4db54be 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -103,6 +103,7 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) else error("Cannot show animation with extension $ext: $agif") end) + return nothing end diff --git a/src/output.jl b/src/output.jl index 27c7731e..95a9c158 100644 --- a/src/output.jl +++ b/src/output.jl @@ -197,6 +197,7 @@ for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml prepare_output(plt) _show(io, m, plt) end + return nothing end end From 6d6d4f14b5625c2ceb48012352af1c3ad389cf45 Mon Sep 17 00:00:00 2001 From: Will Grant Date: Fri, 24 May 2019 11:27:09 +1000 Subject: [PATCH 188/230] add recipes for time periods --- src/recipes.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/recipes.jl b/src/recipes.jl index ca2468e1..c4f052c6 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1104,10 +1104,21 @@ abline!(args...; kw...) = abline!(current(), args...; kw...) dateformatter(dt) = string(Date(Dates.UTD(dt))) datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) +periodformatter(t) = string(t) @recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) @recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter) @recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) +@recipe f(::Type{Dates.Nanosecond}, t::Dates.Nanosecond) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Microsecond}, t::Dates.Microsecond) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Millisecond}, t::Dates.Millisecond) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Second}, t::Dates.Second) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Minute}, t::Dates.Minute) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Hour}, t::Dates.Hour) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Day}, t::Dates.Day) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Week}, t::Dates.Week) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Month}, t::Dates.Month) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{Dates.Year}, t::Dates.Year) = (t -> Dates.value(t), periodformatter) # ------------------------------------------------- # Complex Numbers From 03f6c76b5361f3a9a155cb437a05b2b14525fa70 Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 30 May 2019 19:08:19 +0300 Subject: [PATCH 189/230] Only warn for series sharing a colorbar when it matters. --- src/backends/gr.jl | 74 +++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e227eaa4..a0eb1163 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -421,23 +421,20 @@ function gr_set_viewport_polar() end struct GRColorbar - gradient::Ref{Union{Series,Nothing}} - fill::Ref{Union{Series,Nothing}} - lines::Ref{Union{Series,Nothing}} - GRColorbar() = new(nothing,nothing,nothing) + gradients + fills + lines + GRColorbar() = new([],[],[]) end function gr_update_colorbar!(cbar::GRColorbar, series::Series) style = colorbar_style(series) style === nothing && return - ref = style == cbar_gradient ? cbar.gradient : - style == cbar_fill ? cbar.fill : + list = style == cbar_gradient ? cbar.gradients : + style == cbar_fill ? cbar.fills : style == cbar_lines ? cbar.lines : error("Unknown colorbar style: $style.") - if ref[] !== nothing - @warn "Overwriting colorbar entry" - end - ref[] = series + push!(list, series) end function gr_contour_levels(series::Series, clims) @@ -466,6 +463,16 @@ function gr_colorbar_colors(series::Series, clims) round.(Int,colors) end + +function _cbar_unique(values, propname) + out = last(values) + if any(x != out for x in values) + @warn "Multiple series with different $propname share a colorbar. " * + "Colorbar may not refelct all series correctly." + end + out +end + # add the colorbar function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) GR.savestate() @@ -474,16 +481,19 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) gr_set_viewport_cmap(sp) GR.setscale(0) GR.setwindow(xmin, xmax, zmin, zmax) - if (series = cbar.gradient[]) !== nothing - gr_set_gradient(series) - gr_set_transparency(get_fillalpha(series)) + if !isempty(cbar.gradients) + series = cbar.gradients + gr_set_gradient(_cbar_unique(gr_get_color.(series),"color")) + gr_set_transparency(_cbar_unique(get_fillalpha.(series), "fill alpha")) GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) end - if (series = cbar.fill[]) !== nothing - gr_set_gradient(series) + if !isempty(cbar.fills) + series = cbar.fills GR.setfillintstyle(GR.INTSTYLE_SOLID) - levels = contour_levels(series, clims) + gr_set_gradient(_cbar_unique(gr_get_color.(series), "color")) + gr_set_transparency(_cbar_unique(get_fillalpha.(series), "fill alpha")) + levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels") # GR implicitly uses the maximal z value as the highest level if levels[end] < clims[2] @warn("GR: highest contour level less than maximal z value is not supported.") @@ -491,20 +501,22 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) # promotion in case levels is an integer array levels = [levels[1:end-1]; clims[2]] end - colors = gr_colorbar_colors(series, clims) + colors = gr_colorbar_colors(last(series), clims) for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) GR.setfillcolorind(color) - gr_set_transparency(get_fillalpha(series)) GR.fillrect( xmin, xmax, from, to ) end end - if (series = cbar.lines[]) !== nothing - gr_set_gradient(series) - gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) - gr_set_transparency(get_linealpha(series)) - levels = contour_levels(series, clims) - colors = gr_colorbar_colors(series, clims) + if !isempty(cbar.lines) + series = cbar.lines + gr_set_gradient(_cbar_unique(gr_get_color.(series),"color")) + gr_set_line(_cbar_unique(get_linewidth.(series), "line width"), + _cbar_unique(get_linestyle.(series), "line style"), + _cbar_unique(get_linecolor.(series, Ref(clims)), "line color")) + gr_set_transparency(_cbar_unique(get_linealpha.(series), "line alpha")) + levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels") + colors = gr_colorbar_colors(last(series), clims) for (line, color) in zip(levels, colors) GR.setlinecolorind(color) GR.polyline([xmin,xmax], [line,line] ) @@ -593,18 +605,20 @@ function gr_set_gradient(c) grad end -function gr_set_gradient(series::Series) +gr_set_gradient(series::Series) = gr_set_gradient(gr_get_color(series)) + +function gr_get_color(series::Series) st = series[:seriestype] if st in (:surface, :heatmap) || isfilledcontour(series) - gr_set_gradient(series[:fillcolor]) + series[:fillcolor] elseif st in (:contour, :wireframe) - gr_set_gradient(series[:linecolor]) + series[:linecolor] elseif series[:marker_z] != nothing - gr_set_gradient(series[:markercolor]) + series[:markercolor] elseif series[:line_z] != nothing - gr_set_gradient(series[:linecolor]) + series[:linecolor] elseif series[:fill_z] != nothing - gr_set_gradient(series[:fillcolor]) + series[:fillcolor] end end From ddd083b8c1ef84ce22c4292259a052bbc6031999 Mon Sep 17 00:00:00 2001 From: yha Date: Sun, 2 Jun 2019 19:21:31 +0300 Subject: [PATCH 190/230] Fix for gr_get_color(series) == nothing --- src/backends/gr.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index a0eb1163..01ad6790 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -605,7 +605,10 @@ function gr_set_gradient(c) grad end -gr_set_gradient(series::Series) = gr_set_gradient(gr_get_color(series)) +function gr_set_gradient(series::Series) + color = gr_get_color(series) + color !== nothing && gr_set_gradient(color) +end function gr_get_color(series::Series) st = series[:seriestype] From 71cbaa843c55c72f484e92146888c7288b414141 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 3 Jun 2019 02:25:16 -0700 Subject: [PATCH 191/230] gr: added support for polar heatmaps --- src/backends/gr.jl | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 01ad6790..7e41bfeb 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1318,21 +1318,29 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) dmin, dmax = GR.gr3.volume(y.v, 0) elseif st == :heatmap - xmin, xmax, ymin, ymax = xy_lims zmin, zmax = clims - m, n = length(x), length(y) - xinds = sort(1:m, rev = xaxis[:flip]) - yinds = sort(1:n, rev = yaxis[:flip]) - z = reshape(reshape(z, m, n)[xinds, yinds], m*n) - GR.setspace(zmin, zmax, 0, 90) - grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad() - colors = [plot_color(grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)], series[:fillalpha]) for zi=z] - rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 + - round(UInt, blue(c) * 255) << 16 + - round(UInt, green(c) * 255) << 8 + - round(UInt, red(c) * 255) ), colors) - w, h = length(x), length(y) - GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) + if !ispolar(sp) + xmin, xmax, ymin, ymax = xy_lims + m, n = length(x), length(y) + xinds = sort(1:m, rev = xaxis[:flip]) + yinds = sort(1:n, rev = yaxis[:flip]) + z = reshape(reshape(z, m, n)[xinds, yinds], m*n) + GR.setspace(zmin, zmax, 0, 90) + grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad() + colors = [plot_color(grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)], series[:fillalpha]) for zi=z] + rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 + + round(UInt, blue(c) * 255) << 16 + + round(UInt, green(c) * 255) << 8 + + round(UInt, red(c) * 255) ), colors) + w, h = length(x), length(y) + GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) + else + h, w = length(x), length(y) + z = reshape(z, h, w) + colors = Int32[round(Int32, 1000 + _i * 255) for _i in z'] + GR.setwindow(-1, 1, -1, 1) + GR.polarcellarray(0, 0, 0, 360, 0, 1, w, h, colors) + end elseif st in (:path3d, :scatter3d) # draw path From fd611b36479fb56830892550a70c7aee8c1b4ddd Mon Sep 17 00:00:00 2001 From: yha Date: Mon, 3 Jun 2019 20:22:44 +0300 Subject: [PATCH 192/230] Fix hiding of axis on PyPlot --- src/backends/pyplot.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 9f9962e3..4e5f4d40 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1132,11 +1132,12 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # showaxis if !sp[:xaxis][:showaxis] kw = KW() + if ispolar(sp) + ax.spines["polar"].set_visible(false) + end for dir in (:top, :bottom) - if ispolar(sp) - ax."spines"."polar"."set_visible"(false) - else - getproperty(ax.spines, dir).set_visible(false) + if !ispolar(sp) + ax.spines[string(dir)].set_visible(false) end kw[dir] = kw[Symbol(:label,dir)] = false end @@ -1146,7 +1147,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) kw = KW() for dir in (:left, :right) if !ispolar(sp) - getproperty(ax.spines, dir).set_visible(false) + ax.spines[string(dir)].set_visible(false) end kw[dir] = kw[Symbol(:label,dir)] = false end From 972c97d5ec80742a81b3cfdfc7e8577eafb0f33a Mon Sep 17 00:00:00 2001 From: yha Date: Tue, 4 Jun 2019 20:41:35 +0300 Subject: [PATCH 193/230] Fix for missing as first element --- src/series.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index 9bfcafc7..5f82e4cf 100644 --- a/src/series.jl +++ b/src/series.jl @@ -194,7 +194,8 @@ _apply_type_recipe(plotattributes, v) = RecipesBase.apply_recipe(plotattributes, # and one to format tick values. function _apply_type_recipe(plotattributes, v::AbstractArray) isempty(v) && return Float64[] - args = RecipesBase.apply_recipe(plotattributes, typeof(v[1]), v[1])[1].args + x = first(skipmissing(v)) + args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function numfunc, formatter = args Formatted(map(numfunc, v), formatter) From 4c22a421a17e8ea0117b18f8c3dd067906b4dbc0 Mon Sep 17 00:00:00 2001 From: yha Date: Tue, 4 Jun 2019 21:00:52 +0300 Subject: [PATCH 194/230] No error when input is all missing --- src/series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index 5f82e4cf..cb6daaf2 100644 --- a/src/series.jl +++ b/src/series.jl @@ -193,7 +193,7 @@ _apply_type_recipe(plotattributes, v) = RecipesBase.apply_recipe(plotattributes, # This sort of recipe should return a pair of functions... one to convert to number, # and one to format tick values. function _apply_type_recipe(plotattributes, v::AbstractArray) - isempty(v) && return Float64[] + isempty(skipmissing(v)) && return Float64[] x = first(skipmissing(v)) args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function From 08a30b255d4b0720e1d2fdc796330f3ce324f6cc Mon Sep 17 00:00:00 2001 From: Marek Kukan Date: Thu, 6 Jun 2019 14:31:54 +0200 Subject: [PATCH 195/230] fix bug in plotly_convert_to_datetime --- src/backends/plotly.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index b642979f..81d0bb7f 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -436,7 +436,7 @@ plotly_native_data(axis::Axis, a::Surface) = Surface(plotly_native_data(axis, a. function plotly_convert_to_datetime(x::AbstractArray, formatter::Function) if formatter == datetimeformatter - map(xi -> replace(formatter(xi), "T", " "), x) + map(xi -> replace(formatter(xi), "T" => " "), x) elseif formatter == dateformatter map(xi -> string(formatter(xi), " 00:00:00"), x) elseif formatter == timeformatter From e9abb6d021a6dc03440f7039683a18562b8e8c48 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 11 Jun 2019 22:55:54 +0200 Subject: [PATCH 196/230] implement arrowstyle for GR --- src/backends/gr.jl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 7e41bfeb..ae105ee6 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -84,12 +84,21 @@ gr_set_transparency(c, α) = gr_set_transparency(α) gr_set_transparency(c::Colorant, ::Nothing) = gr_set_transparency(c) gr_set_transparency(c::Colorant) = GR.settransparency(alpha(c)) +const _gr_arrow_map = Dict( + :simple => 1, + :hollow => 3, + :filled => 4, + :triangle => 5, + :filledtriangle => 6, +) +gr_set_arrowstyle(s::Symbol) = GR.setarrowstyle(get(_gr_arrow_map, s, 1)) + # -------------------------------------------------------------------------------------- # draw line segments, splitting x/y into contiguous/finite segments # note: this can be used for shapes by passing func `GR.fillarea` -function gr_polyline(x, y, func = GR.polyline; arrowside=:none) +function gr_polyline(x, y, func = GR.polyline; arrowside = :none, arrowstyle = :simple) iend = 0 n = length(x) while iend < n-1 @@ -118,9 +127,11 @@ function gr_polyline(x, y, func = GR.polyline; arrowside=:none) if istart > 0 && iend > 0 func(x[istart:iend], y[istart:iend]) if arrowside in (:head,:both) + gr_set_arrowstyle(arrowstyle) GR.drawarrow(x[iend-1], y[iend-1], x[iend], y[iend]) end if arrowside in (:tail,:both) + gr_set_arrowstyle(arrowstyle) GR.drawarrow(x[istart+1], y[istart+1], x[istart], y[istart]) end else @@ -1269,7 +1280,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) gr_set_transparency(lc, get_linealpha(series, i)) arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none - gr_polyline(x[rng], y[rng]; arrowside = arrowside) + arrowstyle = isa(series[:arrow], Arrow) ? series[:arrow].style : :simple + gr_set_fillcolor(lc) + gr_polyline(x[rng], y[rng]; arrowside = arrowside, arrowstyle = arrowstyle) end end end From 8342da1ea2001db493a0aef77cd219743cab0df4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 11 Jun 2019 23:15:59 +0200 Subject: [PATCH 197/230] allow row vector of arrows --- src/args.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/args.jl b/src/args.jl index 9ff20711..6f719bae 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1030,7 +1030,7 @@ function preprocessArgs!(plotattributes::KW) arrow() elseif a in (false, nothing, :none) nothing - elseif !(typeof(a) <: Arrow) + elseif !(typeof(a) <: Arrow || typeof(a) <: AbstractArray{Arrow}) arrow(wraptuple(a)...) else a From fd2c01808a2df5e609eb9fe693ad5b29a93edfb6 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 12 Jun 2019 19:26:15 +0200 Subject: [PATCH 198/230] add :open and :closed arrow --- src/backends/gr.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index ae105ee6..91bf25b4 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -90,6 +90,8 @@ const _gr_arrow_map = Dict( :filled => 4, :triangle => 5, :filledtriangle => 6, + :closed => 6, + :open => 5, ) gr_set_arrowstyle(s::Symbol) = GR.setarrowstyle(get(_gr_arrow_map, s, 1)) From fadc0bf6c7b8cbc9238388c6ba4ea884e725e762 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 12 Jun 2019 22:49:12 +0200 Subject: [PATCH 199/230] don't let aspect_ratio impact subplot size --- src/axes.jl | 58 ++++++++++++++++++++++++++---------- src/backends.jl | 8 ++--- src/backends/gr.jl | 16 +++++----- src/backends/inspectdr.jl | 4 +-- src/backends/pgfplots.jl | 4 +-- src/backends/plotly.jl | 18 +++++------ src/backends/pyplot.jl | 18 +++++------ src/backends/unicodeplots.jl | 4 +-- src/layouts.jl | 2 +- src/recipes.jl | 18 ++--------- src/series.jl | 2 +- src/utils.jl | 2 +- 12 files changed, 85 insertions(+), 69 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index c95b5db7..3d6bfbb8 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -152,8 +152,8 @@ scalefunc(scale::Symbol) = x -> get(_scale_funcs, scale, identity)(Float64(x)) invscalefunc(scale::Symbol) = x -> get(_inv_scale_funcs, scale, identity)(Float64(x)) labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string) -function optimal_ticks_and_labels(axis::Axis, ticks = nothing) - amin,amax = axis_limits(axis) +function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing) + amin, amax = axis_limits(sp, axis[:letter]) # scale the limits scale = axis[:scale] @@ -238,7 +238,7 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing) end # return (continuous_values, discrete_values) for the ticks on this axis -function get_ticks(axis::Axis) +function get_ticks(sp::Subplot, axis::Axis) ticks = _transform_ticks(axis[:ticks]) ticks in (:none, nothing, false) && return nothing @@ -261,7 +261,7 @@ function get_ticks(axis::Axis) (collect(0:pi/4:7pi/4), string.(0:45:315)) else # compute optimal ticks and labels - optimal_ticks_and_labels(axis) + optimal_ticks_and_labels(sp, axis) end elseif typeof(ticks) <: Union{AVec, Int} if !isempty(dvals) && typeof(ticks) <: Int @@ -269,7 +269,7 @@ function get_ticks(axis::Axis) axis[:continuous_values][rng], dvals[rng] else # override ticks, but get the labels - optimal_ticks_and_labels(axis, ticks) + optimal_ticks_and_labels(sp, axis, ticks) end elseif typeof(ticks) <: NTuple{2, Any} # assuming we're passed (ticks, labels) @@ -286,12 +286,12 @@ _transform_ticks(ticks) = ticks _transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.value.(ticks) _transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2]) -function get_minor_ticks(axis,ticks) +function get_minor_ticks(sp, axis, ticks) axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing ticks = ticks[1] length(ticks) < 2 && return nothing - amin, amax = axis_limits(axis) + amin, amax = axis_limits(sp, axis[:letter]) #Add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits if length(ticks) > 2 ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1]) @@ -479,7 +479,8 @@ function round_limits(amin,amax) end # using the axis extrema and limit overrides, return the min/max value for this axis -function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis)) +function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(letter, :axis)]), consider_aspect = true) + axis = sp[Symbol(letter, :axis)] ex = axis[:extrema] amin, amax = ex.emin, ex.emax lims = axis[:lims] @@ -497,7 +498,7 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis) if !isfinite(amin) && !isfinite(amax) amin, amax = 0.0, 1.0 end - if ispolar(axis.sps[1]) + amin, amax = if ispolar(axis.sps[1]) if axis[:letter] == :x amin, amax = 0, 2pi elseif lims == :auto @@ -513,6 +514,33 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis) else amin, amax end + + if consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || is3d(:sp)) + aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1 + plot_ratio = height(plotarea(sp)) / width(plotarea(sp)) + bbox_ratio = height(sp.bbox) / width(sp.bbox) + dist = amax - amin + + if letter == :x + yamin, yamax = axis_limits(sp, :y, default_should_widen(sp[:yaxis]), false) + ydist = yamax - yamin + axis_ratio = aspect_ratio * ydist / dist + factor = axis_ratio / plot_ratio + else + xamin, xamax = axis_limits(sp, :x, default_should_widen(sp[:xaxis]), false) + xdist = xamax - xamin + axis_ratio = aspect_ratio * dist / xdist + factor = plot_ratio / axis_ratio + end + + if factor > 1 + center = (amin + amax) / 2 + amin = center + factor * (amin - center) + amax = center + factor * (amax - center) + end + end + + return amin, amax end # ------------------------------------------------------------------------- @@ -586,12 +614,12 @@ end # compute the line segments which should be drawn for this axis function axis_drawing_info(sp::Subplot) xaxis, yaxis = sp[:xaxis], sp[:yaxis] - xmin, xmax = axis_limits(xaxis) - ymin, ymax = axis_limits(yaxis) - xticks = get_ticks(xaxis) - yticks = get_ticks(yaxis) - xminorticks = get_minor_ticks(xaxis,xticks) - yminorticks = get_minor_ticks(yaxis,yticks) + xmin, xmax = axis_limits(sp, :x) + ymin, ymax = axis_limits(sp, :y) + xticks = get_ticks(sp, xaxis) + yticks = get_ticks(sp, yaxis) + xminorticks = get_minor_ticks(sp, xaxis, xticks) + yminorticks = get_minor_ticks(sp, yaxis, yticks) xaxis_segs = Segments(2) yaxis_segs = Segments(2) xtick_segs = Segments(2) diff --git a/src/backends.jl b/src/backends.jl index 8cb4c0ce..8e42442b 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -75,8 +75,8 @@ end text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(lab), sz, rot) # account for the size/length/rotation of tick labels -function tick_padding(axis::Axis) - ticks = get_ticks(axis) +function tick_padding(sp::Subplot, axis::Axis) + ticks = get_ticks(sp, axis) if ticks == nothing 0mm else @@ -106,10 +106,10 @@ end # to fit ticks, tick labels, guides, colorbars, etc. function _update_min_padding!(sp::Subplot) # TODO: something different when `is3d(sp) == true` - leftpad = tick_padding(sp[:yaxis]) + sp[:left_margin] + guide_padding(sp[:yaxis]) + leftpad = tick_padding(sp, sp[:yaxis]) + sp[:left_margin] + guide_padding(sp[:yaxis]) toppad = sp[:top_margin] + title_padding(sp) rightpad = sp[:right_margin] - bottompad = tick_padding(sp[:xaxis]) + sp[:bottom_margin] + guide_padding(sp[:xaxis]) + bottompad = tick_padding(sp, sp[:xaxis]) + sp[:bottom_margin] + guide_padding(sp[:xaxis]) # switch them? if sp[:xaxis][:mirror] diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 7e41bfeb..29f6170b 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -162,7 +162,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot) a = α .+ 90 sinf = sind.(a) cosf = cosd.(a) - rtick_values, rtick_labels = get_ticks(yaxis) + rtick_values, rtick_labels = get_ticks(sp, yaxis) if yaxis[:formatter] in (:scientific, :auto) && yaxis[:ticks] in (:auto, :native) rtick_labels = convert_sci_unicode.(rtick_labels) end @@ -218,16 +218,16 @@ end # using the axis extrema and limit overrides, return the min/max value for this axis -gr_x_axislims(sp::Subplot) = axis_limits(sp[:xaxis]) -gr_y_axislims(sp::Subplot) = axis_limits(sp[:yaxis]) -gr_z_axislims(sp::Subplot) = axis_limits(sp[:zaxis]) +gr_x_axislims(sp::Subplot) = axis_limits(sp, :x) +gr_y_axislims(sp::Subplot) = axis_limits(sp, :y) +gr_z_axislims(sp::Subplot) = axis_limits(sp, :z) gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)... -function gr_lims(axis::Axis, adjust::Bool, expand = nothing) +function gr_lims(sp::Subplot, axis::Axis, adjust::Bool, expand = nothing) if expand != nothing expand_extrema!(axis, expand) end - lims = axis_limits(axis) + lims = axis_limits(sp, axis[:letter]) if adjust GR.adjustrange(lims...) else @@ -989,7 +989,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if is3d(sp) # TODO do we really need a different clims computation here from the one # computed above using get_clims(sp)? - zmin, zmax = gr_lims(zaxis, true) + zmin, zmax = gr_lims(sp, zaxis, true) clims3d = sp[:clims] if is_2tuple(clims3d) isfinite(clims3d[1]) && (zmin = clims3d[1]) @@ -1024,7 +1024,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif ispolar(sp) r = gr_set_viewport_polar() #rmin, rmax = GR.adjustrange(ignorenan_minimum(r), ignorenan_maximum(r)) - rmin, rmax = axis_limits(sp[:yaxis]) + rmin, rmax = axis_limits(sp, :y) gr_polaraxes(rmin, rmax, sp) elseif draw_axes diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index bbc268a3..c1e5c5b8 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -294,8 +294,8 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) plot.xscale = _inspectdr_getscale(xaxis[:scale], false) strip.yscale = _inspectdr_getscale(yaxis[:scale], true) - xmin, xmax = axis_limits(xaxis) - ymin, ymax = axis_limits(yaxis) + xmin, xmax = axis_limits(sp, :x) + ymin, ymax = axis_limits(sp, :y) if ispolar(sp) #Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax) rmax = NaNMath.max(abs(ymin), abs(ymax)) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index e7c805d0..96a83dd4 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -361,13 +361,13 @@ function pgf_axis(sp::Subplot, letter) # limits # TODO: support zlims if letter != :z - lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(axis)) : axis_limits(axis) + lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, :x) kw[Symbol(letter,:min)] = lims[1] kw[Symbol(letter,:max)] = lims[2] end if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none - ticks = get_ticks(axis) + ticks = get_ticks(sp, axis) #pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1] push!(style, string(letter, "tick = {", join(tick_values,","), "}")) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 81d0bb7f..b9c6c7cf 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -114,8 +114,8 @@ function plotly_apply_aspect_ratio(sp::Subplot, plotarea, pcts) if aspect_ratio == :equal aspect_ratio = 1.0 end - xmin,xmax = axis_limits(sp[:xaxis]) - ymin,ymax = axis_limits(sp[:yaxis]) + xmin,xmax = axis_limits(sp, :x) + ymin,ymax = axis_limits(sp, :y) want_ratio = ((xmax-xmin) / (ymax-ymin)) / aspect_ratio parea_ratio = width(plotarea) / height(plotarea) if want_ratio > parea_ratio @@ -174,7 +174,7 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot) ax[:tickangle] = -axis[:rotation] ax[:type] = plotly_scale(axis[:scale]) - lims = axis_limits(axis) + lims = axis_limits(sp, letter) if axis[:ticks] != :native || axis[:lims] != :auto ax[:range] = map(scalefunc(axis[:scale]), lims) @@ -188,7 +188,7 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot) # ticks if axis[:ticks] != :native - ticks = get_ticks(axis) + ticks = get_ticks(sp, axis) ttype = ticksType(ticks) if ttype == :ticks ax[:tickmode] = "array" @@ -211,16 +211,16 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot) ax end -function plotly_polaraxis(axis::Axis) +function plotly_polaraxis(sp::Subplot, axis::Axis) ax = KW( :visible => axis[:showaxis], :showline => axis[:grid], ) if axis[:letter] == :x - ax[:range] = rad2deg.(axis_limits(axis)) + ax[:range] = rad2deg.(axis_limits(sp, :x)) else - ax[:range] = axis_limits(axis) + ax[:range] = axis_limits(sp, :y) ax[:orientation] = -90 end @@ -283,8 +283,8 @@ function plotly_layout(plt::Plot) ), ) elseif ispolar(sp) - plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis]) - plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis]) + plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis]) + plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis]) else plotattributes_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp) # don't allow yaxis to be reupdated/reanchored in a linked subplot diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 9f9962e3..c510b3cc 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -862,9 +862,9 @@ end # -------------------------------------------------------------------------- -function py_set_lims(ax, axis::Axis) +function py_set_lims(ax, sp::Subplot, axis::Axis) letter = axis[:letter] - lfrom, lto = axis_limits(axis) + lfrom, lto = axis_limits(sp, letter) getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto) end @@ -891,7 +891,7 @@ function py_set_ticks(ax, ticks, letter) end end -function py_compute_axis_minval(axis::Axis) +function py_compute_axis_minval(sp::Subplot, axis::Axis) # compute the smallest absolute value for the log scale's linear threshold minval = 1.0 sps = axis.sps @@ -905,13 +905,13 @@ function py_compute_axis_minval(axis::Axis) end # now if the axis limits go to a smaller abs value, use that instead - vmin, vmax = axis_limits(axis) + vmin, vmax = axis_limits(sp, axis[:letter]) minval = NaNMath.min(minval, abs(vmin), abs(vmax)) minval end -function py_set_scale(ax, axis::Axis) +function py_set_scale(ax, sp::Subplot, axis::Axis) scale = axis[:scale] letter = axis[:letter] scale in supported_scales() || return @warn("Unhandled scale value in pyplot: $scale") @@ -927,7 +927,7 @@ function py_set_scale(ax, axis::Axis) elseif scale == :log10 10 end - kw[Symbol(:linthresh,letter)] = NaNMath.min(1e-16, py_compute_axis_minval(axis)) + kw[Symbol(:linthresh,letter)] = NaNMath.min(1e-16, py_compute_axis_minval(sp, axis)) "symlog" end func(arg; kw...) @@ -1092,12 +1092,12 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) if axis[:guide_position] != :auto && letter != :z pyaxis."set_label_position"(axis[:guide_position]) end - py_set_scale(ax, axis) - axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing + py_set_scale(ax, sp, axis) + axis[:ticks] != :native ? py_set_lims(ax, sp, axis) : nothing if ispolar(sp) && letter == :y ax."set_rlabel_position"(90) end - ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis) + ticks = sp[:framestyle] == :none ? nothing : get_ticks(sp, axis) # don't show the 0 tick label for the origin framestyle if sp[:framestyle] == :origin && length(ticks) > 1 ticks[2][ticks[1] .== 0] .= "" diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index a2e677c5..cabb89bb 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -27,8 +27,8 @@ function rebuildUnicodePlot!(plt::Plot, width, height) for sp in plt.subplots xaxis = sp[:xaxis] yaxis = sp[:yaxis] - xlim = axis_limits(xaxis) - ylim = axis_limits(yaxis) + xlim = axis_limits(sp, :x) + ylim = axis_limits(sp, :y) # make vectors xlim = [xlim[1], xlim[2]] diff --git a/src/layouts.jl b/src/layouts.jl index 2527cfc3..83ae259d 100644 --- a/src/layouts.jl +++ b/src/layouts.jl @@ -111,7 +111,7 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol) pct += mix.len / totlen end if pct != 0 - amin, amax = axis_limits(sp[Symbol(letter,:axis)]) + amin, amax = axis_limits(sp, letter) xy += pct * (amax-amin) end xy diff --git a/src/recipes.jl b/src/recipes.jl index ca2468e1..83869efa 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -96,19 +96,6 @@ const POTENTIAL_VECTOR_ARGUMENTS = [ end @deps line path - -function hvline_limits(axis::Axis) - vmin, vmax = axis_limits(axis) - if vmin >= vmax - if isfinite(vmin) - vmax = vmin + 1 - else - vmin, vmax = 0.0, 1.1 - end - end - vmin, vmax -end - @recipe function f(::Type{Val{:hline}}, x, y, z) n = length(y) newx = repeat(Float64[-1, 1, NaN], n) @@ -253,11 +240,12 @@ end n = length(x) fr = plotattributes[:fillrange] if fr == nothing - yaxis = plotattributes[:subplot][:yaxis] + sp = plotattributes[:subplot] + yaxis = sp[:yaxis] fr = if yaxis[:scale] == :identity 0.0 else - NaNMath.min(axis_limits(yaxis)[1], ignorenan_minimum(y)) + NaNMath.min(axis_limits(sp, :y)[1], ignorenan_minimum(y)) end end newx, newy = zeros(3n), zeros(3n) diff --git a/src/series.jl b/src/series.jl index cb6daaf2..89d41152 100644 --- a/src/series.jl +++ b/src/series.jl @@ -392,7 +392,7 @@ end @recipe function f(f::FuncOrFuncs{F}) where F<:Function plt = plotattributes[:plot_object] xmin, xmax = try - axis_limits(plt[1][:xaxis]) + axis_limits(plt[1], :x) catch xinv = invscalefunc(get(plotattributes, :xscale, :identity)) xm = tryrange(f, xinv.([-5,-1,0,0.01])) diff --git a/src/utils.jl b/src/utils.jl index 6a8cb81e..7b04e22a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -508,7 +508,7 @@ function concatenate_fillrange(x,y::Tuple) end function get_sp_lims(sp::Subplot, letter::Symbol) - axis_limits(sp[Symbol(letter, :axis)]) + axis_limits(sp, letter) end """ From 589643d59141a4729c01a4c3eea85c737fbf52e1 Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 13 Jun 2019 16:44:05 +0300 Subject: [PATCH 200/230] Fix SegmentsIterator for more than one initial NaN. --- src/utils.jl | 35 +++++++++-------------------------- test/runtests.jl | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 6a8cb81e..6f548a2a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -214,36 +214,19 @@ end # helpers to figure out if there are NaN values in a list of array types anynan(i::Int, args::Tuple) = any(a -> try isnan(_cycle(a,i)) catch MethodError false end, args) -anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend) -allnan(istart::Int, iend::Int, args::Tuple) = all(i -> anynan(i, args), istart:iend) +anynan(args::Tuple) = i -> anynan(i,args) +anynan(istart::Int, iend::Int, args::Tuple) = any(anynan(args), istart:iend) +allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend) function Base.iterate(itr::SegmentsIterator, nextidx::Int = 1) - nextidx > itr.n && return nothing - if nextidx == 1 && !any(isempty,itr.args) && anynan(1, itr.args) - nextidx = 2 - end + i = findfirst(!anynan(itr.args), nextidx:itr.n) + i === nothing && return nothing + nextval = nextidx + i - 1 - i = istart = iend = nextidx + j = findfirst(anynan(itr.args), nextval:itr.n) + nextnan = j === nothing ? itr.n + 1 : nextval + j - 1 - # find the next NaN, and iend is the one before - while i <= itr.n + 1 - if i > itr.n || anynan(i, itr.args) - # done... array end or found NaN - iend = i-1 - break - end - i += 1 - end - - # find the next non-NaN, and set nextidx - while i <= itr.n - if !anynan(i, itr.args) - break - end - i += 1 - end - - istart:iend, i + nextval:nextnan-1, nextnan end # Find minimal type that can contain NaN and x diff --git a/test/runtests.jl b/test/runtests.jl index 8e6ef9c1..e2f7b9c5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,5 +51,31 @@ end end @testset "NoFail" begin - histogram([1, 0, 0, 0, 0, 0]) + plots = [histogram([1, 0, 0, 0, 0, 0]), + plot([missing]), + plot([missing; 1:4]), + plot([fill(missing,10); 1:4])] + for plt in plots + display(plt) + end +end + +@testset "Segments" begin + function segments(args...) + segs = UnitRange{Int}[] + for seg in iter_segments(args...) + push!(segs,seg) + end + segs + end + + nan10 = fill(NaN,10) + @test segments(11:20) == [1:10] + @test segments([NaN]) == [] + @test segments(nan10) == [] + @test segments([nan10; 1:5]) == [11:15] + @test segments([1:5;nan10]) == [1:5] + @test segments([nan10; 1:5; nan10; 1:5; nan10]) == [11:15, 26:30] + @test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10] + @test segments([nan10; 1:15], [1:15; nan10]) == [11:15] end From 9f9ac4ec922ddea8eddbfd5d3e69686480a9f722 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 13 Jun 2019 18:50:59 +0200 Subject: [PATCH 201/230] bbox_ratio not required --- src/axes.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index 3d6bfbb8..339ff454 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -518,7 +518,6 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l if consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || is3d(:sp)) aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1 plot_ratio = height(plotarea(sp)) / width(plotarea(sp)) - bbox_ratio = height(sp.bbox) / width(sp.bbox) dist = amax - amin if letter == :x From 63f6128c87202dee211c71b80fc2096a05c9316a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 13 Jun 2019 23:03:19 +0200 Subject: [PATCH 202/230] respect user lims --- src/axes.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index 339ff454..8ef97f7e 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -484,7 +484,8 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l ex = axis[:extrema] amin, amax = ex.emin, ex.emax lims = axis[:lims] - if (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2 + has_user_lims = (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2 + if has_user_lims if isfinite(lims[1]) amin = lims[1] end @@ -515,7 +516,7 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l amin, amax end - if consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || is3d(:sp)) + if !has_user_lims && consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || is3d(:sp)) aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1 plot_ratio = height(plotarea(sp)) / width(plotarea(sp)) dist = amax - amin From 46ed2f62638af533f17b2485e69f1985ab37a34b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 13 Jun 2019 23:12:12 +0200 Subject: [PATCH 203/230] fix pgfplots axis limits --- src/backends/pgfplots.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 96a83dd4..8f849c07 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -361,7 +361,7 @@ function pgf_axis(sp::Subplot, letter) # limits # TODO: support zlims if letter != :z - lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, :x) + lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, letter) kw[Symbol(letter,:min)] = lims[1] kw[Symbol(letter,:max)] = lims[2] end From 0f6336b3dd32a63b7f8783aa18bcba7c9b6117ab Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 15 Jun 2019 18:30:21 +0200 Subject: [PATCH 204/230] fix ENV['PLOTS_DEFAULT_BACKEND'] --- src/backends.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 8e42442b..a95b2dd2 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -143,12 +143,7 @@ function _pick_default_backend() if env_default != "" sym = Symbol(lowercase(env_default)) if sym in _backends - if sym in _initialized_backends - backend(sym) - else - @warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.") - _fallback_default_backend() - end + backend(sym) else @warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" * join(sort(_backends), "\n\t")) From b3336229ab21e863b6750df70454df8b7851102f Mon Sep 17 00:00:00 2001 From: yha Date: Mon, 17 Jun 2019 01:31:08 +0300 Subject: [PATCH 205/230] Limit number of automatic bins --- src/recipes.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 83869efa..705ac54b 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -608,7 +608,8 @@ Plots.@deps stepbins path wand_edges(x...) = (@warn("Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto) function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N - _cl(x) = ceil(Int, max(x, one(x))) + max_bins = 10_000 + _cl(x) = min(ceil(Int, max(x, one(x))), max_bins) _iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1)) _span(v) = maximum(v) - minimum(v) @@ -635,7 +636,7 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S elseif mode == :fd # Freedman–Diaconis rule _cl(_span(v) / (2 * _iqr(v) / nd)) elseif mode == :wand - wand_edges(v) # this makes this function not type stable, but the type instability does not propagate + _cl(wand_edges(v)) # this makes this function not type stable, but the type instability does not propagate else error("Unknown auto-binning mode $mode") end From 068523fac14edee36783d3d83f33393f17ce6438 Mon Sep 17 00:00:00 2001 From: Will Grant Date: Mon, 17 Jun 2019 17:44:24 +1000 Subject: [PATCH 206/230] neaten change by implementing with a for loop --- src/recipes.jl | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index c4f052c6..eaab89b3 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1106,19 +1106,7 @@ datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) periodformatter(t) = string(t) -@recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) -@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter) -@recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) -@recipe f(::Type{Dates.Nanosecond}, t::Dates.Nanosecond) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Microsecond}, t::Dates.Microsecond) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Millisecond}, t::Dates.Millisecond) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Second}, t::Dates.Second) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Minute}, t::Dates.Minute) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Hour}, t::Dates.Hour) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Day}, t::Dates.Day) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Week}, t::Dates.Week) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Month}, t::Dates.Month) = (t -> Dates.value(t), periodformatter) -@recipe f(::Type{Dates.Year}, t::Dates.Year) = (t -> Dates.value(t), periodformatter) +@recipe f(::Type{P}, t::P) where P <: Dates.Period = (t -> Dates.value(t), t -> string(P(t))) # ------------------------------------------------- # Complex Numbers From 8f4753a0bb87fd54328fa8c36772573b955491ad Mon Sep 17 00:00:00 2001 From: Jeff Fessler Date: Fri, 21 Jun 2019 09:53:22 -0400 Subject: [PATCH 207/230] Document :colorbar_entry Addresses #2068 --- src/arg_desc.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 13e42645..120d1c36 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -49,7 +49,8 @@ const _arg_desc = KW( :series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", :primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", :hover => "nothing or vector of strings. Text to display when hovering over each data point.", - +:colorbar_entry => "Bool. Include this series in the color bar? Set to `false` to exclude.", + # plot args :plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)", :background_color => "Color Type. Base color for all backgrounds.", From 7f8dc486bb185937866684fb5d64f280e20db24b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 26 Jun 2019 12:09:59 +0200 Subject: [PATCH 208/230] allow specifying the color gradient for z values in pyplot --- src/backends/pyplot.jl | 16 ++++++++++------ src/utils.jl | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 5b4939ed..e5424a01 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -467,7 +467,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) handle = ax."plot"((arg[rng] for arg in xyargs)...; label = i == 1 ? series[:label] : "", zorder = series[:series_plotindex], - color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)), + color = py_color(single_color(get_linecolor(series, clims, i)), get_linealpha(series, i)), linewidth = py_thickness_scale(plt, get_linewidth(series, i)), linestyle = py_linestyle(st, get_linestyle(series, i)), solid_capstyle = "round", @@ -1296,22 +1296,26 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) handles = [] for series in series_list(sp) if should_add_to_legend(series) + + lc = get_linecolor(series, clims) + lc = isa(lc, ColorGradient) ? lc[0.5] : lc + # add a line/marker and a label push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing pypatches."Patch"( - edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)), - facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)), + edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)), + facecolor = py_color(single_color(get_fillcolor(series, clims)), get_fillalpha(series)), 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) PyPlot.plt."Line2D"((0,1),(0,0), - color = py_color(get_linecolor(series, clims), get_linealpha(series)), + color = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)), linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)), linestyle = py_linestyle(:path, get_linestyle(series)), marker = py_marker(first(series[:markershape])), - markeredgecolor = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)), - markerfacecolor = series[:marker_z] == nothing ? py_color(get_markercolor(series, clims), get_markeralpha(series)) : py_color(series[:markercolor][0.5]) + markeredgecolor = py_color(single_color(get_markerstrokecolor(series)), get_markerstrokealpha(series)), + markerfacecolor = py_color(single_color(get_markercolor(series, clims)), get_markeralpha(series)) ) else series[:serieshandle][1] diff --git a/src/utils.jl b/src/utils.jl index 8f1873d3..f86c7768 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -625,6 +625,9 @@ for comp in (:line, :fill, :marker) end end +single_color(c, v = 0.5) = c +single_color(grad::ColorGradient, v = 0.5) = grad[v] + function get_linewidth(series, i::Int = 1) _cycle(series[:linewidth], i) end From 2f14c37c598cba677a2c67cd9f16370345b01f1b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 26 Jun 2019 13:04:14 +0200 Subject: [PATCH 209/230] remove unnecessary lines --- src/backends/pyplot.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index e5424a01..eec1e6ca 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1296,10 +1296,6 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) handles = [] for series in series_list(sp) if should_add_to_legend(series) - - lc = get_linecolor(series, clims) - lc = isa(lc, ColorGradient) ? lc[0.5] : lc - # add a line/marker and a label push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing pypatches."Patch"( From 0aac0398e8aea653d9a9cfbe3692676e37227d7a Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 27 Jun 2019 01:23:26 +0300 Subject: [PATCH 210/230] Fix handling of missing values in matrix inputs. --- src/series.jl | 15 +++++---------- test/runtests.jl | 4 +++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/series.jl b/src/series.jl index 89d41152..b3aaedcd 100644 --- a/src/series.jl +++ b/src/series.jl @@ -19,13 +19,8 @@ convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing # fixed number of blank series convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing -# numeric vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing -convertToAnyVector(v::AVec{Union{Missing, T}}, plotattributes::KW) where {T<:Number} = Any[replace(v, missing => NaN)], nothing - -# string vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing -convertToAnyVector(v::AVec{Union{Missing, T}}, plotattributes::KW) where {T<:AbstractString} = Any[replace(v, missing => "")], nothing +# numeric/string vector +convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Union{Number,String,Missing}} = Any[handlemissings(v)], nothing function convertToAnyVector(v::AMat, plotattributes::KW) v = handlemissings(v) @@ -36,9 +31,9 @@ function convertToAnyVector(v::AMat, plotattributes::KW) end, nothing end -handlemissings(v::AMat) = v -handlemissings(v::AMat{T}) where T <: Number = replace(v, missing => NaN) -handlemissings(v::AMat{T}) where T <: String = replace(v, missing => "") +handlemissings(v) = v +handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: Number = replace(v, missing => NaN) +handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: String = replace(v, missing => "") # function convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing diff --git a/test/runtests.jl b/test/runtests.jl index e2f7b9c5..d5f6864b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -54,7 +54,9 @@ end plots = [histogram([1, 0, 0, 0, 0, 0]), plot([missing]), plot([missing; 1:4]), - plot([fill(missing,10); 1:4])] + plot([fill(missing,10); 1:4]), + plot([1 1; 1 missing]), + plot(["a" "b"; missing "d"], [1 2; 3 4])] for plt in plots display(plt) end From b3e8fd9c666419a6a1176316ed74dc67362194aa Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 27 Jun 2019 11:35:39 +0200 Subject: [PATCH 211/230] up version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2581cbc9..1c0003d2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" author = ["Tom Breloff (@tbreloff)"] -version = "0.25.1" +version = "0.25.2" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" From 7a248331e783cf2662ee1d3f906468a8ca97ba82 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 30 Jun 2019 13:15:04 +0200 Subject: [PATCH 212/230] fix gr linealpha --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index df86d2e5..0fa3d210 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1280,10 +1280,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (i, rng) in enumerate(segments) lc = get_linecolor(series, clims, i) gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) - gr_set_transparency(lc, get_linealpha(series, i)) arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none arrowstyle = isa(series[:arrow], Arrow) ? series[:arrow].style : :simple gr_set_fillcolor(lc) + gr_set_transparency(lc, get_linealpha(series, i)) gr_polyline(x[rng], y[rng]; arrowside = arrowside, arrowstyle = arrowstyle) end end From db1e25252ad1a59a3d49f3e276b2f3e88a30c701 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sun, 30 Jun 2019 17:38:53 +0200 Subject: [PATCH 213/230] Fix zero and NaN weighted bins in stephist for log-yscale Bins with weight NaN and zero (which the Plots engine seems to turn into into NaN automatically for log-yscale) should not be draws in log-yscale. --- src/recipes.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/recipes.jl b/src/recipes.jl index 705ac54b..cc12b522 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -545,6 +545,8 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S if !isnan(last_w) push!(x, a) push!(y, baseline) + push!(x, NaN) + push!(y, NaN) end else if isnan(last_w) From 7214b8b1b1bd6844d1240098d1926e90ee507435 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sun, 30 Jun 2019 17:41:49 +0200 Subject: [PATCH 214/230] Improve type stability of _stepbins_path --- src/recipes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index cc12b522..daa88a89 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -538,7 +538,7 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S w, it_state_w = it_tuple_w if (log_scale_x && a ≈ 0) - a = b/_logScaleBases[xscale]^3 + a = oftype(a, b/_logScaleBases[xscale]^3) end if isnan(w) @@ -559,8 +559,8 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S push!(y, w) end - a = b - last_w = w + a = oftype(a, b) + last_w = oftype(last_w, w) it_tuple_e = iterate(edge, it_state_e) it_tuple_w = iterate(weights, it_state_w) From a7b7c5ba81697e68f654b23f37b0dcc7c70cb854 Mon Sep 17 00:00:00 2001 From: yha Date: Mon, 1 Jul 2019 01:39:05 +0300 Subject: [PATCH 215/230] Support any element type (incl. missing) and length in tuple/Point recipes --- src/series.jl | 31 ++++++------------------------- src/utils.jl | 21 ++++++++++----------- test/runtests.jl | 12 ++++++++++++ 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/series.jl b/src/series.jl index b3aaedcd..2c8684af 100644 --- a/src/series.jl +++ b/src/series.jl @@ -553,33 +553,14 @@ end # # Lists of tuples and GeometryTypes.Points # # -------------------------------------------------------------------- # -# # if we get an unhandled tuple, just splat it in -@recipe f(tup::Tuple) = tup -# -# # (x,y) tuples -@recipe f(xy::AVec{Tuple{R1,R2}}) where {R1<:Number,R2<:Number} = unzip(xy) -@recipe f(xy::Tuple{R1,R2}) where {R1<:Number,R2<:Number} = [xy[1]], [xy[2]] +@recipe f(v::AVec{<:Tuple}) = unzip(v) +@recipe f(v::AVec{<:GeometryTypes.Point}) = unzip(v) +@recipe f(tup::Tuple) = [tup] +@recipe f(p::GeometryTypes.Point) = [p] -# -# # (x,y,z) tuples -@recipe f(xyz::AVec{Tuple{R1,R2,R3}}) where {R1<:Number,R2<:Number,R3<:Number} = unzip(xyz) -@recipe f(xyz::Tuple{R1,R2,R3}) where {R1<:Number,R2<:Number,R3<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] - -# these might be points+velocity, or OHLC or something else -@recipe f(xyuv::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv) -@recipe f(xyuv::Tuple{R1,R2,R3,R4}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]] - - -# -# # 2D Points -@recipe f(xy::AVec{GeometryTypes.Point{2,T}}) where {T<:Number} = unzip(xy) -@recipe f(xy::GeometryTypes.Point{2,T}) where {T<:Number} = [xy[1]], [xy[2]] - -# -# # 3D Points -@recipe f(xyz::AVec{GeometryTypes.Point{3,T}}) where {T<:Number} = unzip(xyz) -@recipe f(xyz::GeometryTypes.Point{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]] +# Special case for 4-tuples in :ohlc series +@recipe f(xyuv::AVec{<:Tuple{R1,R2,R3,R4}}) where {R1,R2,R3,R4} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv) # # # -------------------------------------------------------------------- diff --git a/src/utils.jl b/src/utils.jl index f86c7768..ea0ccc99 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -271,18 +271,17 @@ maketuple(x::Tuple{T,S}) where {T,S} = x mapFuncOrFuncs(f::Function, u::AVec) = map(f, u) mapFuncOrFuncs(fs::AVec{F}, u::AVec) where {F<:Function} = [map(f, u) for f in fs] -unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] for t in xy] -unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz] -unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv] +for i in 2:4 + @eval begin + unzip(v::Union{AVec{<:Tuple{Vararg{T,$i} where T}}, + AVec{<:GeometryTypes.Point{$i}}}) = $(Expr(:tuple, (:([t[$j] for t in v]) for j=1:i)...)) + end +end -unzip(xy::AVec{GeometryTypes.Point{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy] -unzip(xy::GeometryTypes.Point{2,T}) where {T} = T[xy[1]], T[xy[2]] - -unzip(xyz::AVec{GeometryTypes.Point{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz] -unzip(xyz::GeometryTypes.Point{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]] - -unzip(xyuv::AVec{GeometryTypes.Point{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv] -unzip(xyuv::GeometryTypes.Point{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]] +unzip(v::Union{AVec{<:GeometryTypes.Point{N}}, + AVec{<:Tuple{Vararg{T,N} where T}}}) where N = error("$N-dimensional unzip not implemented.") +unzip(v::Union{AVec{<:GeometryTypes.Point}, + AVec{<:Tuple}}) = error("Can't unzip points of different dimensions.") # given 2-element lims and a vector of data x, widen lims to account for the extrema of x function _expand_limits(lims, x) diff --git a/test/runtests.jl b/test/runtests.jl index d5f6864b..0b73b148 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,6 +4,7 @@ using Random using BinaryProvider using Test using FileIO +using GeometryTypes include("imgcomp.jl") # don't actually show the plots @@ -81,3 +82,14 @@ end @test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10] @test segments([nan10; 1:15], [1:15; nan10]) == [11:15] end + +@testset "Utils" begin + zipped = ([(1,2)], [("a","b")], [(1,"a"),(2,"b")], + [(1,2),(3,4)], [(1,2,3),(3,4,5)], [(1,2,3,4),(3,4,5,6)], + [(1,2.0),(missing,missing)], [(1,missing),(missing,"a")], + [(missing,missing)], [(missing,missing,missing),("a","b","c")]) + for z in zipped + @test isequal(collect(zip(Plots.unzip(z)...)), z) + @test isequal(collect(zip(Plots.unzip(Point.(z))...)), z) + end +end From bb3c54cb278c15bdcb5eeab861692459a6968317 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jul 2019 10:39:31 +0200 Subject: [PATCH 216/230] allow missing in line_z, fill_z and marker_z --- src/utils.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index ea0ccc99..666c878d 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -527,9 +527,9 @@ function get_clims(sp::Subplot) z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface) for series in series_list(sp) 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) <: Real) + if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real}) zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...) - elseif (vals != nothing) && (eltype(vals) <: Real) + elseif (vals != nothing) && (eltype(vals) <: Union{Missing, Real}) zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...) end end @@ -654,7 +654,7 @@ 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, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray{<:Real} 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, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z)) end # --------------------------------------------------------------- From 8dfca617692a6024cf1ddabdd76f231274606e9e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jul 2019 11:31:00 +0200 Subject: [PATCH 217/230] add areaplot recipe --- src/recipes.jl | 19 ++++++ src/shorthands.jl | 150 +++++++++++++++++++++++++--------------------- 2 files changed, 100 insertions(+), 69 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index daa88a89..0f833d51 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1183,3 +1183,22 @@ end @series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) end end + + +@userplot AreaPlot + +@recipe function f(a::AreaPlot) + data = cumsum(a.args[end], dims=2) + x = length(a.args) == 1 ? (1:size(data, 1)) : a.args[1] + seriestype := :line + @series begin + fillrange := 0 + x, data[:,1] + end + for i in 2:size(data, 2) + @series begin + fillrange := data[:,i-1] + x, data[:,i] + end + end +end diff --git a/src/shorthands.jl b/src/shorthands.jl index 6f379a73..79e63919 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -2,10 +2,10 @@ scatter(x,y) scatter!(x,y) -Make a scatter plot of y vs x. +Make a scatter plot of y vs x. # Examples -```julia-repl +```julia-repl julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue]) julia> scatter([(1,4),(2,5),(3,6)]) ``` @@ -16,9 +16,9 @@ julia> scatter([(1,4),(2,5),(3,6)]) bar(x,y) bar!(x,y) -Make a bar plot of y vs x. +Make a bar plot of y vs x. -# Arguments +# Arguments - $(_document_argument("bar_position")) - $(_document_argument("bar_width")) @@ -26,7 +26,7 @@ Make a bar plot of y vs x. - $(_document_argument("orientation")) # Examples -```julia-repl +```julia-repl julia> bar([1,2,3],[4,5,6],fillcolor=[:red,:green,:blue],fillalpha=[0.2,0.4,0.6]) julia> bar([(1,4),(2,5),(3,6)]) ``` @@ -41,7 +41,7 @@ julia> bar([(1,4),(2,5),(3,6)]) Plot a histogram. -# Arguments +# Arguments - `x`: AbstractVector of values to be binned - $(_document_argument("bins")) @@ -53,7 +53,7 @@ Plot a histogram. - $(_document_argument("orientation")) # Example -```julia-repl +```julia-repl julia> histogram([1,2,1,1,4,3,8],bins=0:8) ``` """ @@ -63,7 +63,7 @@ julia> histogram([1,2,1,1,4,3,8],bins=0:8) barhist(x) barhist!(x) -Make a histogram bar plot. See `histogram`. +Make a histogram bar plot. See `histogram`. """ @shorthands barhist @@ -72,7 +72,7 @@ Make a histogram bar plot. See `histogram`. stephist(x) Make a histogram step plot (bin counts are represented using horizontal lines -instead of bars). See `histogram`. +instead of bars). See `histogram`. """ @shorthands stephist @@ -80,8 +80,8 @@ instead of bars). See `histogram`. scatterhist(x) scatterhist!(x) -Make a histogram scatter plot (bin counts are represented using points -instead of bars). See `histogram`. +Make a histogram scatter plot (bin counts are represented using points +instead of bars). See `histogram`. """ @shorthands scatterhist @@ -91,14 +91,14 @@ instead of bars). See `histogram`. Plot a two-dimensional histogram. -# Arguments +# Arguments -- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) -- `weights`: Vector of weights for the values in `x`. Each entry of x contributes - its weight to the height of its bin. +- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`) +- `weights`: Vector of weights for the values in `x`. Each entry of x contributes + its weight to the height of its bin. # Example -```julia-repl +```julia-repl julia> histogram2d(randn(10_000),randn(10_000)) ``` """ @@ -108,14 +108,14 @@ julia> histogram2d(randn(10_000),randn(10_000)) density(x) density!(x) -Make a line plot of a kernel density estimate of x. +Make a line plot of a kernel density estimate of x. # Arguments -- `x`: AbstractVector of samples for probability density estimation +- `x`: AbstractVector of samples for probability density estimation # Example -```julia-repl +```julia-repl julia> using StatsPlots julia> density(randn(100_000)) ``` @@ -126,10 +126,10 @@ julia> density(randn(100_000)) heatmap(x,y,z) heatmap!(x,y,z) -Plot a heatmap of the rectangular array `z`. +Plot a heatmap of the rectangular array `z`. # Example -```julia-repl +```julia-repl julia> heatmap(randn(10,10)) ``` """ @@ -140,7 +140,7 @@ julia> heatmap(randn(10,10)) hexbin(x,y) hexbin!(x,y) -Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])` +Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])` with hexagonal bins) # Example @@ -154,11 +154,11 @@ julia> hexbin(randn(10_000), randn(10_000)) sticks(x,y) sticks!(x,y) -Draw a stick plot of y vs x. +Draw a stick plot of y vs x. # Example ```julia-repl -julia> sticks(1:10) +julia> sticks(1:10) ``` """ @shorthands sticks @@ -167,11 +167,11 @@ julia> sticks(1:10) hline(y) hline!(y) -Draw horizontal lines at positions specified by the values in +Draw horizontal lines at positions specified by the values in the AbstractVector `y` # Example -```julia-repl +```julia-repl julia> hline([-1,0,2]) ``` """ @@ -181,11 +181,11 @@ julia> hline([-1,0,2]) vline(x) vline!(x) -Draw vertical lines at positions specified by the values in +Draw vertical lines at positions specified by the values in the AbstractVector `x` # Example -```julia-repl +```julia-repl julia> vline([-1,0,2]) ``` """ @@ -194,13 +194,13 @@ julia> vline([-1,0,2]) """ hspan(y) -Draw a rectangle between the horizontal line at position `y[1]` -and the horizontal line at position `y[2]`. If `length(y) ≥ 4`, -then further rectangles are drawn between `y[3]` and `y[4]`, -`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the -last entry of `y` is ignored. +Draw a rectangle between the horizontal line at position `y[1]` +and the horizontal line at position `y[2]`. If `length(y) ≥ 4`, +then further rectangles are drawn between `y[3]` and `y[4]`, +`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the +last entry of `y` is ignored. # Example -```julia-repl +```julia-repl julia> hspan(1:6) ``` """ @@ -209,13 +209,13 @@ julia> hspan(1:6) """ vspan(x) -Draw a rectangle between the vertical line at position `x[1]` -and the vertical line at position `x[2]`. If `length(x) ≥ 4`, -then further rectangles are drawn between `x[3]` and `x[4]`, -`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the -last entry of `x` is ignored. +Draw a rectangle between the vertical line at position `x[1]` +and the vertical line at position `x[2]`. If `length(x) ≥ 4`, +then further rectangles are drawn between `x[3]` and `x[4]`, +`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the +last entry of `x` is ignored. # Example -```julia-repl +```julia-repl julia> vspan(1:6) ``` """ @@ -225,9 +225,9 @@ julia> vspan(1:6) ohlc(x,y::Vector{OHLC}) ohlc!(x,y::Vector{OHLC}) -Make open-high-low-close plot. Each entry of y is represented by a vertical -segment extending from the low value to the high value, with short horizontal -segments on the left and right indicating the open and close values, respectively. +Make open-high-low-close plot. Each entry of y is represented by a vertical +segment extending from the low value to the high value, with short horizontal +segments on the left and right indicating the open and close values, respectively. # Example ```julia-repl @@ -240,16 +240,16 @@ julia> ohlc(y) """ - contour(x,y,z) - contour!(x,y,z) + contour(x,y,z) + contour!(x,y,z) -Draw contour lines of the `Surface` z. +Draw contour lines of the `Surface` z. # Arguments - `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`) - `fill`: Bool. Fill area between contours or draw contours only (false by default) -# Example +# Example ```julia-repl julia> x = y = range(-20, 20, length = 100) julia> contour(x, y, (x, y) -> x^2 + y^2) @@ -267,10 +267,10 @@ julia> contour(x, y, (x, y) -> x^2 + y^2) surface(x,y,z) surface!(x,y,z) -Draw a 3D surface plot. +Draw a 3D surface plot. # Example -```julia-repl +```julia-repl julia> x = y = range(-3, 3, length = 100) julia> surface(x, y, (x, y) -> sinc(norm([x, y]))) ``` @@ -281,10 +281,10 @@ julia> surface(x, y, (x, y) -> sinc(norm([x, y]))) wireframe(x,y,z) wireframe!(x,y,z) -Draw a 3D wireframe plot. +Draw a 3D wireframe plot. # Example -```julia-repl +```julia-repl julia> wireframe(1:10,1:10,randn(10,10)) ``` """ @@ -295,10 +295,10 @@ julia> wireframe(1:10,1:10,randn(10,10)) path3d!(x,y,z) Plot a 3D path from `(x[1],y[1],z[1])` to `(x[2],y[2],z[2])`, -..., to `(x[end],y[end],z[end])`. +..., to `(x[end],y[end],z[end])`. # Example -```julia-repl +```julia-repl julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) ``` """ @@ -308,10 +308,10 @@ julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) scatter3d(x,y,z) scatter3d!(x,y,z) -Make a 3D scatter plot. +Make a 3D scatter plot. # Example -```julia-repl +```julia-repl julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) ``` """ @@ -321,17 +321,17 @@ julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27]) boxplot(x, y) boxplot!(x, y) -Make a box and whisker plot. +Make a box and whisker plot. # Keyword arguments - `notch`: Bool. Notch the box plot? (false) - `range`: Real. Values more than range*IQR below the first quartile - or above the third quartile are shown as outliers (1.5) -- `outliers`: Bool. Show outliers? (true) -- `whisker_width`: Real or Symbol. Length of whiskers (:match) + or above the third quartile are shown as outliers (1.5) +- `outliers`: Bool. Show outliers? (true) +- `whisker_width`: Real or Symbol. Length of whiskers (:match) # Example -```julia-repl +```julia-repl julia> using StatsPlots julia> boxplot(repeat([1,2,3],outer=100),randn(300)) ``` @@ -342,10 +342,10 @@ julia> boxplot(repeat([1,2,3],outer=100),randn(300)) violin(x,y,z) violin!(x,y,z) -Make a violin plot. +Make a violin plot. # Example -```julia-repl +```julia-repl julia> violin(repeat([1,2,3],outer=100),randn(300)) ``` """ @@ -355,11 +355,11 @@ julia> violin(repeat([1,2,3],outer=100),randn(300)) quiver(x,y,quiver=(u,v)) quiver!(x,y,quiver=(u,v)) -Make a quiver (vector field) plot. The `i`th vector extends -from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`. +Make a quiver (vector field) plot. The `i`th vector extends +from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`. # Example -```julia-repl +```julia-repl julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3])) ``` """ @@ -369,16 +369,28 @@ julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3])) curves(x,y) curves!(x,y) -Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])` +Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])` with control points `(x[2],y[2]), ..., (x[end-1],y[end]-1)` # Example -```julia-repl +```julia-repl julia> curves([1,2,3,4],[1,1,2,4]) ``` """ @shorthands curves +""" + areaplot([x,] y) + areaplot!([x,] y) + +Draw a stacked area plot of the matrix y. +# Examples +```julia-repl +julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4]) +``` +""" +@shorthands areaplot + "Plot a pie diagram" pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) @@ -424,9 +436,9 @@ ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = """ annotate!(anns...) -Add annotations to an existing plot. +Add annotations to an existing plot. -# Arguments +# Arguments - `anns`: An `AbstractVector` of tuples of the form (x,y,text). The text object can be an String or PlotText From ddaa69bce2ffbc704fe9c35c6c6380793e7cf32b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jul 2019 12:48:47 +0200 Subject: [PATCH 218/230] move areaplot doc from shorthands to recipes --- src/recipes.jl | 9 +++++++++ src/shorthands.jl | 12 ------------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 0f833d51..0bab86b0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1184,7 +1184,16 @@ end end end +""" + areaplot([x,] y) + areaplot!([x,] y) +Draw a stacked area plot of the matrix y. +# Examples +```julia-repl +julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4]) +``` +""" @userplot AreaPlot @recipe function f(a::AreaPlot) diff --git a/src/shorthands.jl b/src/shorthands.jl index 79e63919..776626a9 100644 --- a/src/shorthands.jl +++ b/src/shorthands.jl @@ -379,18 +379,6 @@ julia> curves([1,2,3,4],[1,1,2,4]) """ @shorthands curves -""" - areaplot([x,] y) - areaplot!([x,] y) - -Draw a stacked area plot of the matrix y. -# Examples -```julia-repl -julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4]) -``` -""" -@shorthands areaplot - "Plot a pie diagram" pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) From f0dac1630ffd583bc42e70a8780cada1edd25e25 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jul 2019 12:53:01 +0200 Subject: [PATCH 219/230] fewer lines --- src/recipes.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 0bab86b0..230aedac 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1200,13 +1200,9 @@ julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], f data = cumsum(a.args[end], dims=2) x = length(a.args) == 1 ? (1:size(data, 1)) : a.args[1] seriestype := :line - @series begin - fillrange := 0 - x, data[:,1] - end - for i in 2:size(data, 2) + for i in 1:size(data, 2) @series begin - fillrange := data[:,i-1] + fillrange := i > 1 ? data[:,i-1] : 0 x, data[:,i] end end From adbe515af791a781b97188a19c642869a505c6e1 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jul 2019 12:55:02 +0200 Subject: [PATCH 220/230] up version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1c0003d2..0d611db2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" author = ["Tom Breloff (@tbreloff)"] -version = "0.25.2" +version = "0.25.3" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" From c6893f6cb5b4f657cc8703cf11929347f46e5aa0 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 6 Jul 2019 14:44:48 +0200 Subject: [PATCH 221/230] convertToAnyVector method for AbstractString --- src/series.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/series.jl b/src/series.jl index b3aaedcd..39c1658d 100644 --- a/src/series.jl +++ b/src/series.jl @@ -20,7 +20,7 @@ convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing # numeric/string vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Union{Number,String,Missing}} = Any[handlemissings(v)], nothing +convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Union{Number,AbstractString,Missing}} = Any[handlemissings(v)], nothing function convertToAnyVector(v::AMat, plotattributes::KW) v = handlemissings(v) @@ -33,7 +33,7 @@ end handlemissings(v) = v handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: Number = replace(v, missing => NaN) -handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: String = replace(v, missing => "") +handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: AbstractString = replace(v, missing => "") # function convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing From a1182e0ebe5d3bdd1672dda9bad47897b3331536 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sat, 13 Jul 2019 11:02:01 +0530 Subject: [PATCH 222/230] JuliaPlot -> JuliaPlots in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 955a5f4b..f2225901 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ #### Created by Tom Breloff (@tbreloff) -#### Maintained by the [JuliaPlot members](https://github.com/orgs/JuliaPlots/people) +#### Maintained by the [JuliaPlots members](https://github.com/orgs/JuliaPlots/people) Plots is a plotting API and toolset. My goals with the package are: From 8c2a66b00cf4e5e4bf49cf07ab82f9a43fd7c16c Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sat, 13 Jul 2019 17:58:28 +0530 Subject: [PATCH 223/230] Use FFMPEG.jl for video encoding (#2099) * add FFMPEG as a project dependency * run(`ffmpeg ...`) -> ffmpeg_exe(`...`) Add FFMPEG.jl to Project.toml too. --- Project.toml | 1 + src/Plots.jl | 2 ++ src/animation.jl | 8 ++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index 0d611db2..ce061ba5 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.25.3" Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb" diff --git a/src/Plots.jl b/src/Plots.jl index 0849c20b..4fd536b5 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -8,6 +8,8 @@ import GeometryTypes using Dates, Printf, Statistics, Base64, LinearAlgebra, Random import SparseArrays: findnz +using FFMPEG + @reexport using RecipesBase import RecipesBase: plot, plot!, animate using Base.Meta diff --git a/src/animation.jl b/src/animation.jl index f4db54be..b6d45f36 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -76,15 +76,15 @@ function buildanimation(animdir::AbstractString, fn::AbstractString, if variable_palette # generate a colorpalette for each frame for highest quality, but larger filesize palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1" - run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`) + ffmpeg_exe(`-v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`) else # generate a colorpalette first so ffmpeg does not have to guess it - run(`ffmpeg -v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`) + ffmpeg_exe(`-v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`) # then apply the palette to get better results - run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`) + ffmpeg_exe(` -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`) end else - run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`) + ffmpeg_exe(`-v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`) end show_msg && @info("Saved animation to ", fn) From b6a7c1036c4d28387da45861ad5172aa60d7e5b6 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 16 Jul 2019 13:52:52 +0200 Subject: [PATCH 224/230] update NEWS.md --- NEWS.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/NEWS.md b/NEWS.md index 130921c8..08a760c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,29 @@ --- ## (current master) +## 0.26.0 +- use FFMPEG.jl +- add missing method for convertToAnyVector + +## 0.25.3 +- add areaplot +- allow missing in z_color arguments +- more general tuple recipe +- stephist logscale improvements + +## 0.25.2 +- improvements to handle missings +- pyplot: allow setting the color gradient for z values +- document :colorbar_entry +- limit number of automatic bins +- fix ENV['PLOTS_DEFAULT_BACKEND'] +- don't let aspect_ratio impact subplot size +- implement arrowstyle for GR +- fix bug in plotly_convert_to_datetime +- improve missing support +- gr: polar heatmaps +- make sure show returns nothing + ## 0.25.1 - fix gr_display From daf9556bedd14c33079ab7b55a549cd7a04eac38 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 16 Jul 2019 13:53:20 +0200 Subject: [PATCH 225/230] up version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0d611db2..b2a0ce78 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" author = ["Tom Breloff (@tbreloff)"] -version = "0.25.3" +version = "0.26.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" From 56734774288f637d4095dca1af933fb529327ecd Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 25 Jul 2019 16:05:08 +0300 Subject: [PATCH 226/230] Restore Date, DateTime and Time recipes --- src/recipes.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index faca1f72..9be74970 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1095,8 +1095,10 @@ abline!(args...; kw...) = abline!(current(), args...; kw...) dateformatter(dt) = string(Date(Dates.UTD(dt))) datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) -periodformatter(t) = string(t) +@recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) +@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter) +@recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) @recipe f(::Type{P}, t::P) where P <: Dates.Period = (t -> Dates.value(t), t -> string(P(t))) # ------------------------------------------------- From 4ac5484b4f92e04d284d4bd84d79b9d803c19fe8 Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 25 Jul 2019 18:08:37 +0300 Subject: [PATCH 227/230] convertToAnyVector cleanup. Adds missing support in heatmap/volume. --- src/series.jl | 87 +++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 59 deletions(-) diff --git a/src/series.jl b/src/series.jl index d6cd9952..6cbaee82 100644 --- a/src/series.jl +++ b/src/series.jl @@ -7,67 +7,35 @@ # note: returns meta information... mainly for use with automatic labeling from DataFrames for now const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} +const DataPoint = Union{Number, AbstractString, Missing} +const SeriesData = Union{AVec{<:DataPoint}, Function, Surface, Volume} all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) -# unknown -convertToAnyVector(x, plotattributes::KW) = error("No user recipe defined for $(typeof(x))") - -# missing -convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing - -# fixed number of blank series -convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing - -# numeric/string vector -convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Union{Number,AbstractString,Missing}} = Any[handlemissings(v)], nothing - -function convertToAnyVector(v::AMat, plotattributes::KW) - v = handlemissings(v) - if all3D(plotattributes) - Any[Surface(v)] - else - Any[v[:,i] for i in 1:size(v,2)] - end, nothing -end +prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") +prepareSeriesData(::Nothing) = nothing +prepareSeriesData(s::SeriesData) = handlemissings(s) handlemissings(v) = v handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: Number = replace(v, missing => NaN) handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: AbstractString = replace(v, missing => "") +handlemissings(s::Surface) = Surface(handlemissings(s.surf)) +handlemissings(v::Volume) = Volume(handlemissings(v.v), v.x_extents, v.y_extents, v.z_extents) -# function -convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing +# default: assume x represents a single series +convertToAnyVector(x) = Any[prepareSeriesData(x)] -# surface -convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing +# fixed number of blank series +convertToAnyVector(n::Integer) = Any[zeros(0) for i in 1:n] -# volume -convertToAnyVector(v::Volume, plotattributes::KW) = Any[v], nothing - -# # vector of OHLC -# convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing - -# # dates -convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing +# vector of data points is a single series +convertToAnyVector(v::AVec{<:DataPoint}) = Any[prepareSeriesData(v)] # list of things (maybe other vectors, functions, or something else) -function convertToAnyVector(v::AVec, plotattributes::KW) - if all(x -> typeof(x) <: Number, v) - # all real numbers wrap the whole vector as one item - Any[convert(Vector{Float64}, v)], nothing - else - # something else... treat each element as an item - vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing - # Any[vi for vi in v], nothing - end -end +convertToAnyVector(v::AVec) = vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) -convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing - - -function convertToAnyVector(args...) - error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))") -end +# Matrix is split into rows +convertToAnyVector(v::AMat{<:DataPoint}) = Any[prepareSeriesData(v[:,i]) for i in 1:size(v,2)] # -------------------------------------------------------------------- @@ -130,23 +98,24 @@ struct SliceIt end z = z.data end - xs, _ = convertToAnyVector(x, plotattributes) - ys, _ = convertToAnyVector(y, plotattributes) - zs, _ = convertToAnyVector(z, plotattributes) + xs = convertToAnyVector(x) + ys = convertToAnyVector(y) + zs = convertToAnyVector(z) + fr = pop!(plotattributes, :fillrange, nothing) - fillranges, _ = if typeof(fr) <: Number - ([fr],nothing) + fillranges = if typeof(fr) <: Number + [fr] else - convertToAnyVector(fr, plotattributes) + convertToAnyVector(fr) end mf = length(fillranges) rib = pop!(plotattributes, :ribbon, nothing) - ribbons, _ = if typeof(rib) <: Number - ([fr],nothing) + ribbons = if typeof(rib) <: Number + [rib] else - convertToAnyVector(rib, plotattributes) + convertToAnyVector(rib) end mr = length(ribbons) @@ -289,7 +258,7 @@ end @recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing) # return a surface if this is a 3d plot, otherwise let it be sliced up -@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat} +@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing} if all3D(plotattributes) n,m = size(mat) wrap_surfaces(plotattributes) @@ -312,7 +281,7 @@ end end # assume this is a Volume, so construct one -@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Number +@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Union{Number,Missing} seriestype := :volume SliceIt, nothing, Volume(vol, args...), nothing end From 12e34bb24f48048dcc26c9a056752b16f2c8fe75 Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 25 Jul 2019 18:29:49 +0300 Subject: [PATCH 228/230] Fix comment, move all3D method --- src/series.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/series.jl b/src/series.jl index 6cbaee82..ed7a719e 100644 --- a/src/series.jl +++ b/src/series.jl @@ -10,8 +10,6 @@ const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} const DataPoint = Union{Number, AbstractString, Missing} const SeriesData = Union{AVec{<:DataPoint}, Function, Surface, Volume} -all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) - prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") prepareSeriesData(::Nothing) = nothing prepareSeriesData(s::SeriesData) = handlemissings(s) @@ -34,7 +32,7 @@ convertToAnyVector(v::AVec{<:DataPoint}) = Any[prepareSeriesData(v)] # list of things (maybe other vectors, functions, or something else) convertToAnyVector(v::AVec) = vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) -# Matrix is split into rows +# Matrix is split into columns convertToAnyVector(v::AMat{<:DataPoint}) = Any[prepareSeriesData(v[:,i]) for i in 1:size(v,2)] # -------------------------------------------------------------------- @@ -257,6 +255,8 @@ end @recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing) +all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) + # return a surface if this is a 3d plot, otherwise let it be sliced up @recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing} if all3D(plotattributes) From 74c69f575fcd23ae6b02dbdd3d4ed8b1855ebc5b Mon Sep 17 00:00:00 2001 From: yha Date: Thu, 25 Jul 2019 18:51:04 +0300 Subject: [PATCH 229/230] Fix general vec method --- src/series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index ed7a719e..97492ce9 100644 --- a/src/series.jl +++ b/src/series.jl @@ -30,7 +30,7 @@ convertToAnyVector(n::Integer) = Any[zeros(0) for i in 1:n] convertToAnyVector(v::AVec{<:DataPoint}) = Any[prepareSeriesData(v)] # list of things (maybe other vectors, functions, or something else) -convertToAnyVector(v::AVec) = vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) +convertToAnyVector(v::AVec) = vcat((convertToAnyVector(vi) for vi in v)...) # Matrix is split into columns convertToAnyVector(v::AMat{<:DataPoint}) = Any[prepareSeriesData(v[:,i]) for i in 1:size(v,2)] From d6b3b68cd961e2e0545495bf302567bfe051f9df Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 2 Aug 2019 14:54:32 +0200 Subject: [PATCH 230/230] don't split color_palette into groups --- src/series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index 97492ce9..023c7c4b 100644 --- a/src/series.jl +++ b/src/series.jl @@ -550,7 +550,7 @@ end # end splittable_kw(key, val, lengthGroup) = false -splittable_kw(key, val::AbstractArray, lengthGroup) = (key != :group) && size(val,1) == lengthGroup +splittable_kw(key, val::AbstractArray, lengthGroup) = !(key in (:group, :color_palette)) && size(val,1) == lengthGroup splittable_kw(key, val::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup)) splittable_kw(key, val::SeriesAnnotations, lengthGroup) = splittable_kw(key, val.strs, lengthGroup)