diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml
new file mode 100644
index 00000000..68dbe39c
--- /dev/null
+++ b/.github/workflows/CompatHelper.yml
@@ -0,0 +1,24 @@
+name: CompatHelper
+
+on:
+ schedule:
+ - cron: '00 * * * *'
+
+jobs:
+ CompatHelper:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ julia-version: [1.2.0]
+ julia-arch: [x86]
+ os: [ubuntu-latest]
+ steps:
+ - uses: julia-actions/setup-julia@latest
+ with:
+ version: ${{ matrix.julia-version }}
+ - name: Pkg.add("CompatHelper")
+ run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
+ - name: CompatHelper.main()
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: julia -e 'using CompatHelper; CompatHelper.main()'
diff --git a/.travis.yml b/.travis.yml
index fc303b0f..1bd6d03c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,12 +4,21 @@ os:
- linux
# - osx
julia:
- - 1.1
+ - 1
+ - 1.2
- nightly
-
+
matrix:
allow_failures:
- - julia: nightly
+ - julia: nightly
+
+addons:
+ apt:
+ packages:
+ - at-spi2-core
+ - libgtk-3-dev
+ - xauth
+ - xvfb
sudo: required
before_install:
@@ -18,3 +27,8 @@ before_install:
notifications:
email: true
+
+script:
+ - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
+ - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi
+ - $TESTCMD -e 'using Pkg; Pkg.build(); Pkg.test(coverage=true)'
diff --git a/NEWS.md b/NEWS.md
index 08a760c3..33ae2e4c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,14 +3,38 @@
#### notes on release changes, ongoing development, and future planned work
-- Minor version 0.17 is the last one to support Julia 0.6!!
-- Minor version 0.11 is the last one to support Julia 0.5!!
- - Critical bugfixes only
- - `backports` branch is for Julia 0.5
-
----
## (current master)
+## 0.28.3
+- support generalized array interface
+- save to pdf, svg and eps in plotlyjs
+- fix for clims in line_z
+- optimize heatmap logic in gr
+
+## 0.26.3
+- fix `vline` with dates
+- fix PyPlot logscale bug
+- avoid annotation clipping for PyPlot
+- allow plotting of Any vectors and 3D plotting again in convertToAnyVector
+- specify legend title font in GR and PyPlot
+- delete `pushtomaster.sh`
+- use `=== nothing`
+
+## 0.26.2
+- improve empty animation build error
+- fix GR axis flip for heatmaps and images
+- fix ribbons specified as tuples
+- add Char recipe
+- fix Plotly plots with single-element series
+- rewrite PlotlyJS backend
+
+## 0.26.1
+- handle `Char`s as input data
+- fix html saving for Plotly
+- expand ~ in paths on UNIX systems
+- convertToAnyVector clean-up
+- fix color_palette grouping issue
+
## 0.26.0
- use FFMPEG.jl
- add missing method for convertToAnyVector
diff --git a/Project.toml b/Project.toml
index d61e259e..bc1fc4e5 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.26.0"
+version = "0.28.4"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@@ -31,27 +31,39 @@ 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"
+Contour = "0.5"
+FFMPEG = "0.2"
+FixedPointNumbers = "0.6, 0.7"
+GR = "0.44"
+GeometryTypes = "0.7"
+JSON = "0.21"
+Measures = "0.3"
+NaNMath = "0.3"
+PGFPlotsX = "1.2.0"
+PlotThemes = "1"
+PlotUtils = "0.6.1"
+RecipesBase = "0.6, 0.7"
+Reexport = "0.2"
+Requires = "0.5, 1.0"
+Showoff = "0.3.1"
+StatsBase = "0.32"
+julia = "1"
[extras]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
+GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
+Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
-Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
+LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
+PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925"
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"
-BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
[targets]
-test = ["BinaryProvider", "Pkg", "Test", "Random", "StatsPlots", "VisualRegressionTests", "LaTeXStrings", "Images", "ImageMagick", "RDatasets", "FileIO", "UnicodePlots"]
+test = ["FileIO", "GeometryTypes", "Gtk", "ImageMagick", "Images", "LaTeXStrings", "LibGit2", "PGFPlotsX", "Random", "RDatasets", "StatsPlots", "Test", "UnicodePlots", "VisualRegressionTests"]
diff --git a/appveyor.yml b/appveyor.yml
index 3490f07b..b0bbcfc0 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,6 +2,7 @@ environment:
matrix:
# - julia_version: 0.7
- julia_version: 1
+ - julia_version: 1.2
- julia_version: nightly
platform:
diff --git a/deps/generateprecompiles.jl b/deps/generateprecompiles.jl
new file mode 100644
index 00000000..5bf3d6be
--- /dev/null
+++ b/deps/generateprecompiles.jl
@@ -0,0 +1,51 @@
+# To figure out what should be precompiled, run this script, then move
+# precompile_Plots.jl in precompiles_path (see below) to src/precompile.jl
+
+# This script works by using SnoopCompile to log compilations that take place
+# while running the examples on the GR backend. So SnoopCompile must be
+# installed, and StatsPlots, RDatasets, and FileIO are also required for
+# certain examples.
+
+# If precompilation fails with an UndefVarError for a module, probably what is
+# happening is that the module appears in the precompile statements, but is
+# only visible to one of Plots' dependencies, and not Plots itself. Adding the
+# module to the blacklist below will remove these precompile statements.
+
+# Anonymous functions may appear in precompile statements as functions with
+# hashes in their name. Those of the form "#something##kw" have to do with
+# compiling functions with keyword arguments, and are named reproducibly, so
+# can be kept. Others generally will not work. Currently, SnoopCompile includes
+# some anonymous functions that not reproducible, but SnoopCompile PR #30
+# (which looks about to be merged) will ensure that anonymous functions are
+# actually defined before attempting to precompile them. Alternatively, we can
+# keep only the keyword argument related anonymous functions by changing the
+# regex that SnoopCompile uses to detect anonymous functions to
+# r"#{1,2}[^\"#]+#{1,2}\d+" (see anonrex in SnoopCompile.jl). To exclude all
+# precompile statements involving anonymous functions, "#" can also be added to
+# the blacklist below.
+
+using SnoopCompile
+
+log_path = joinpath(tempdir(), "compiles.log")
+precompiles_path = joinpath(tempdir(), "precompile")
+
+# run examples with GR backend, logging what needs to be compiled
+SnoopCompile.@snoopc log_path begin
+ using Plots
+ Plots.test_examples(:gr, disp=true)
+end
+
+# precompile calls containing the following strings are dropped
+blacklist = [
+ # functions defined in examples
+ "PlotExampleModule",
+ # the following are not visible to Plots, only its dependencies
+ "CategoricalArrays",
+ "FixedPointNumbers",
+ "SparseArrays",
+ r"#{1,2}[^\"#]+#{1,2}\d+",
+]
+
+data = SnoopCompile.read(log_path)
+pc = SnoopCompile.parcel(reverse!(data[2]), blacklist=blacklist)
+SnoopCompile.write(precompiles_path, pc)
diff --git a/pushtomaster.sh b/pushtomaster.sh
deleted file mode 100755
index 01d219c0..00000000
--- a/pushtomaster.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-git checkout master
-git merge --ff-only dev
-git push origin master
-git checkout dev
diff --git a/src/Plots.jl b/src/Plots.jl
index 4fd536b5..6b64f9c0 100644
--- a/src/Plots.jl
+++ b/src/Plots.jl
@@ -1,6 +1,6 @@
module Plots
-_current_plots_version = v"0.25.0"
+const _current_plots_version = VersionNumber(split(first(filter(line -> occursin("version", line), readlines(normpath(@__DIR__, "..", "Project.toml")))), "\"")[2])
using Reexport
@@ -222,4 +222,7 @@ end
const CURRENT_BACKEND = CurrentBackend(:none)
+include("precompile.jl")
+_precompile_()
+
end # module
diff --git a/src/animation.jl b/src/animation.jl
index b6d45f36..7e5f9a8e 100644
--- a/src/animation.jl
+++ b/src/animation.jl
@@ -60,31 +60,39 @@ end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
-gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
-mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
-mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
+gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
+mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
+mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim, fn, false; kw...)
+ffmpeg_framerate(fps) = "$fps"
+ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)"
-function buildanimation(animdir::AbstractString, fn::AbstractString,
+function buildanimation(anim::Animation, fn::AbstractString,
is_animated_gif::Bool=true;
- fps::Integer = 20, loop::Integer = 0,
+ fps::Real = 20, loop::Integer = 0,
variable_palette::Bool=false,
show_msg::Bool=true)
- fn = abspath(fn)
+ if length(anim.frames) == 0
+ throw(ArgumentError("Cannot build empty animations"))
+ end
+
+ fn = abspath(expanduser(fn))
+ animdir = anim.dir
+ framerate = ffmpeg_framerate(fps)
if is_animated_gif
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"
- ffmpeg_exe(`-v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
+ ffmpeg_exe(`-v 0 -framerate $framerate -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
else
# generate a colorpalette first so ffmpeg does not have to guess it
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
- ffmpeg_exe(` -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 $framerate -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
end
else
- ffmpeg_exe(`-v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
+ ffmpeg_exe(`-v 0 -framerate $framerate -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
end
show_msg && @info("Saved animation to ", fn)
@@ -96,13 +104,18 @@ end
# 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"
- "
"
+ if ext == "gif"
+ html = "
"
elseif ext in ("mov", "mp4")
- ""
+ mimetype = ext == "mov" ? "video/quicktime" : "video/mp4"
+ html = ""
else
error("Cannot show animation with extension $ext: $agif")
- end)
+ end
+
+ write(io, html)
return nothing
end
diff --git a/src/arg_desc.jl b/src/arg_desc.jl
index 120d1c36..7b7e5283 100644
--- a/src/arg_desc.jl
+++ b/src/arg_desc.jl
@@ -42,6 +42,7 @@ const _arg_desc = KW(
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
: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.",
+:show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default).",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
: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`.",
@@ -50,7 +51,7 @@ const _arg_desc = KW(
: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.",
@@ -95,9 +96,16 @@ const _arg_desc = KW(
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
+:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
+:legendtitlefontsize => "Integer. Font pointsize the legend title.",
+:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
+:legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
+:legendtitlefontrotation => "Real. Font rotation of the legend title",
+:legendtitlefontcolor => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.",
+:legendtitlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
: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 `aspect_ratio` x-units.",
diff --git a/src/args.jl b/src/args.jl
index 6f719bae..75577482 100644
--- a/src/args.jl
+++ b/src/args.jl
@@ -272,6 +272,7 @@ const _series_defaults = KW(
:arrow => nothing, # allows for adding arrows to line/path... call `arrow(args...)`
:normalize => false, # do we want a normalized histogram?
:weights => nothing, # optional weights for histograms (1D and 2D)
+ :show_empty_bins => false, # should empty bins in 2D histogram be colored as zero (otherwise they are transparent)
:contours => false, # add contours to 3d surface and wireframe plots
:contour_labels => false,
:match_dimensions => false, # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196
@@ -336,6 +337,12 @@ const _subplot_defaults = KW(
:legendfontvalign => :vcenter,
:legendfontrotation => 0.0,
:legendfontcolor => :match,
+ :legendtitlefontfamily => :match,
+ :legendtitlefontsize => 11,
+ :legendtitlefonthalign => :hcenter,
+ :legendtitlefontvalign => :vcenter,
+ :legendtitlefontrotation => 0.0,
+ :legendtitlefontcolor => :match,
:annotations => [], # annotation tuples... list of (x,y,annotation)
:projection => :none, # can also be :polar or :3d
:aspect_ratio => :none, # choose from :none or :equal
@@ -450,6 +457,7 @@ const _initial_axis_defaults = deepcopy(_axis_defaults)
# to be able to reset font sizes to initial values
const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize],
+ :legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize])
@@ -574,6 +582,7 @@ add_aliases(:xerror, :xerr, :xerrorbar)
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized)
+add_aliases(:show_empty_bins, :showemptybins, :showempty, :show_empty)
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
add_aliases(:match_dimensions, :transpose, :transpose_z)
add_aliases(:subplot, :sp, :subplt, :splt)
@@ -685,15 +694,15 @@ function processLineArg(plotattributes::KW, arg)
plotattributes[:linestyle] = arg
elseif typeof(arg) <: Stroke
- arg.width == nothing || (plotattributes[:linewidth] = arg.width)
- arg.color == nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[:linealpha] = arg.alpha)
- arg.style == nothing || (plotattributes[:linestyle] = arg.style)
+ arg.width === nothing || (plotattributes[:linewidth] = arg.width)
+ arg.color === nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[:linealpha] = arg.alpha)
+ arg.style === nothing || (plotattributes[:linestyle] = arg.style)
elseif typeof(arg) <: Brush
- arg.size == nothing || (plotattributes[:fillrange] = arg.size)
- arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
+ arg.size === nothing || (plotattributes[:fillrange] = arg.size)
+ arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows)
plotattributes[:arrow] = arg
@@ -724,15 +733,15 @@ function processMarkerArg(plotattributes::KW, arg)
plotattributes[:markerstrokestyle] = arg
elseif typeof(arg) <: Stroke
- arg.width == nothing || (plotattributes[:markerstrokewidth] = arg.width)
- arg.color == nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
- arg.style == nothing || (plotattributes[:markerstrokestyle] = arg.style)
+ arg.width === nothing || (plotattributes[:markerstrokewidth] = arg.width)
+ arg.color === nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
+ arg.style === nothing || (plotattributes[:markerstrokestyle] = arg.style)
elseif typeof(arg) <: Brush
- arg.size == nothing || (plotattributes[:markersize] = arg.size)
- arg.color == nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[:markeralpha] = arg.alpha)
+ arg.size === nothing || (plotattributes[:markersize] = arg.size)
+ arg.color === nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[:markeralpha] = arg.alpha)
# linealpha
elseif allAlphas(arg)
@@ -757,9 +766,9 @@ end
function processFillArg(plotattributes::KW, arg)
# fr = get(plotattributes, :fillrange, 0)
if typeof(arg) <: Brush
- arg.size == nothing || (plotattributes[:fillrange] = arg.size)
- arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
+ arg.size === nothing || (plotattributes[:fillrange] = arg.size)
+ arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Bool
plotattributes[:fillrange] = arg ? 0 : nothing
@@ -793,10 +802,10 @@ function processGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :gridstyle)] = arg
elseif typeof(arg) <: Stroke
- arg.width == nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
- arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
- arg.style == nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
+ arg.width === nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
+ arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
+ arg.style === nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
# linealpha
elseif allAlphas(arg)
@@ -822,10 +831,10 @@ function processMinorGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :minorgrid)] = true
elseif typeof(arg) <: Stroke
- arg.width == nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
- arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
- arg.alpha == nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
- arg.style == nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
+ arg.width === nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
+ arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
+ arg.alpha === nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
+ arg.style === nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
plotattributes[Symbol(letter, :minorgrid)] = true
# linealpha
@@ -930,6 +939,15 @@ function preprocessArgs!(plotattributes::KW)
end
end
+ # vline accesses the y argument but actually maps it to the x axis.
+ # Hence, we have to swap formatters
+ if get(plotattributes, :seriestype, :path) == :vline
+ xformatter = get(plotattributes, :xformatter, :auto)
+ yformatter = get(plotattributes, :yformatter, :auto)
+ plotattributes[:xformatter] = yformatter
+ plotattributes[:yformatter] = xformatter
+ end
+
# handle grid args common to all axes
args = pop!(plotattributes, :grid, ())
for arg in wraptuple(args)
@@ -961,7 +979,7 @@ function preprocessArgs!(plotattributes::KW)
end
end
# fonts
- for fontname in (:titlefont, :legendfont)
+ for fontname in (:titlefont, :legendfont, :legendtitlefont)
args = pop!(plotattributes, fontname, ())
for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg)
@@ -1080,7 +1098,7 @@ function extractGroupArgs(v::AVec, args...; legendEntry = string)
if n > 100
@warn("You created n=$n groups... Is that intended?")
end
- groupIds = Vector{Int}[filter(i -> v[i] == glab, 1:length(v)) for glab in groupLabels]
+ groupIds = Vector{Int}[filter(i -> v[i] == glab, eachindex(v)) for glab in groupLabels]
GroupBy(map(legendEntry, groupLabels), groupIds)
end
@@ -1088,7 +1106,7 @@ legendEntryFromTuple(ns::Tuple) = join(ns, ' ')
# this is when given a tuple of vectors of values to group by
function extractGroupArgs(vs::Tuple, args...)
- isempty(vs) && return GroupBy([""], [1:size(args[1],1)])
+ isempty(vs) && return GroupBy([""], [axes(args[1],1)])
v = map(tuple, vs...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end
@@ -1098,7 +1116,7 @@ legendEntryFromTuple(ns::NamedTuple) =
join(["$k = $v" for (k, v) in pairs(ns)], ", ")
function extractGroupArgs(vs::NamedTuple, args...)
- isempty(vs) && return GroupBy([""], [1:size(args[1],1)])
+ isempty(vs) && return GroupBy([""], [axes(args[1],1)])
v = map(NamedTuple{keys(vs)}∘tuple, values(vs)...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end
@@ -1121,7 +1139,7 @@ end
function _filter_input_data!(plotattributes::KW)
idxfilter = pop!(plotattributes, :idxfilter, nothing)
- if idxfilter != nothing
+ if idxfilter !== nothing
filter_data!(plotattributes, idxfilter)
end
end
@@ -1207,7 +1225,8 @@ convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
# anything else is returned as-is
function slice_arg(v::AMat, idx::Int)
c = mod1(idx, size(v,2))
- size(v,1) == 1 ? v[1,c] : v[:,c]
+ m,n = axes(v)
+ size(v,1) == 1 ? v[first(m),n[c]] : v[:,n[c]]
end
slice_arg(wrapper::InputWrapper, idx) = wrapper.obj
slice_arg(v, idx) = v
@@ -1237,7 +1256,7 @@ end
# v = plotattributes[k]
# plotattributes[k] = if v == :match
# match_color
-# elseif v == nothing
+# elseif v === nothing
# plot_color(RGBA(0,0,0,0))
# else
# v
@@ -1246,7 +1265,7 @@ end
function color_or_nothing!(plotattributes::KW, k::Symbol)
v = plotattributes[k]
- plotattributes[k] = if v == nothing || v == false
+ plotattributes[k] = if v === nothing || v == false
RGBA{Float64}(0,0,0,0)
elseif v != :match
plot_color(v)
@@ -1271,8 +1290,10 @@ const _match_map = KW(
:bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot,
:legendfontfamily => :fontfamily_subplot,
+ :legendtitlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot,
:legendfontcolor => :foreground_color_subplot,
+ :legendtitlefontcolor => :foreground_color_subplot,
:tickfontcolor => :foreground_color_text,
:guidefontcolor => :foreground_color_guide,
)
@@ -1563,11 +1584,11 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
# update alphas
for asym in (:linealpha, :markeralpha, :fillalpha)
- if plotattributes[asym] == nothing
+ if plotattributes[asym] === nothing
plotattributes[asym] = plotattributes[:seriesalpha]
end
end
- if plotattributes[:markerstrokealpha] == nothing
+ if plotattributes[:markerstrokealpha] === nothing
plotattributes[:markerstrokealpha] = plotattributes[:markeralpha]
end
@@ -1602,13 +1623,13 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
end
# if marker_z, fill_z or line_z are set, ensure we have a gradient
- if plotattributes[:marker_z] != nothing
+ if plotattributes[:marker_z] !== nothing
ensure_gradient!(plotattributes, :markercolor, :markeralpha)
end
- if plotattributes[:line_z] != nothing
+ if plotattributes[:line_z] !== nothing
ensure_gradient!(plotattributes, :linecolor, :linealpha)
end
- if plotattributes[:fill_z] != nothing
+ if plotattributes[:fill_z] !== nothing
ensure_gradient!(plotattributes, :fillcolor, :fillalpha)
end
diff --git a/src/axes.jl b/src/axes.jl
index 8ef97f7e..baebcaac 100644
--- a/src/axes.jl
+++ b/src/axes.jl
@@ -67,7 +67,7 @@ function process_axis_arg!(plotattributes::KW, arg, letter = "")
elseif T <: AVec
plotattributes[Symbol(letter,:ticks)] = arg
- elseif arg == nothing
+ elseif arg === nothing
plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs
@@ -166,7 +166,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
# or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
- if ticks == nothing && scale == :identity
+ if ticks === nothing && scale == :identity
if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes
@@ -184,7 +184,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
end
# get a list of well-laid-out ticks
- if ticks == nothing
+ if ticks === nothing
scaled_ticks = optimize_ticks(
sf(amin),
sf(amax);
@@ -218,6 +218,8 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :plain))
elseif formatter == :scientific
Showoff.showoff(unscaled_ticks, :scientific)
+ elseif formatter == :latex
+ map(x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"), Showoff.showoff(unscaled_ticks, :auto))
else
# there was an override for the formatter... use that on the unscaled ticks
map(formatter, unscaled_ticks)
@@ -295,7 +297,7 @@ function get_minor_ticks(sp, axis, ticks)
#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])
- elseif axis[:scale] == :none
+ elseif axis[:scale] in (:none, :identity)
ratio = 1
else
return nothing
@@ -309,7 +311,9 @@ function get_minor_ticks(sp, axis, ticks)
minorticks = typeof(ticks[1])[]
for (i,hi) in enumerate(ticks[2:end])
lo = ticks[i]
- append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
+ if isfinite(lo) && hi > lo
+ append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
+ end
end
minorticks[amin .<= minorticks .<= amax]
end
@@ -382,7 +386,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
end
expand_extrema!(axis, data)
- elseif data != nothing
+ elseif data !== nothing
# TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value)
@@ -399,10 +403,10 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
# expand for fillrange
fr = plotattributes[:fillrange]
- if fr == nothing && plotattributes[:seriestype] == :bar
+ if fr === nothing && plotattributes[:seriestype] == :bar
fr = 0.0
end
- if fr != nothing && !all3D(plotattributes)
+ if fr !== nothing && !all3D(plotattributes)
axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple
for fri in fr
@@ -419,7 +423,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[dsym]
bw = plotattributes[:bar_width]
- if bw == nothing
+ if bw === nothing
bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end
axis = sp.attr[Symbol(dsym, :axis)]
@@ -573,10 +577,10 @@ end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AVec)
- n = length(v)
- cvec = zeros(n)
- discrete_indices = zeros(Int, n)
- for i=1:n
+ n = eachindex(v)
+ cvec = zeros(axes(v))
+ discrete_indices = similar(Array{Int}, axes(v))
+ for i in n
cvec[i], discrete_indices[i] = discrete_value!(axis, v[i])
end
cvec, discrete_indices
@@ -584,10 +588,10 @@ end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AMat)
- n,m = size(v)
- cmat = zeros(n,m)
- discrete_indices = zeros(Int, n, m)
- for i=1:n, j=1:m
+ n,m = axes(v)
+ cmat = zeros(axes(v))
+ discrete_indices = similar(Array{Int}, axes(v))
+ for i in n, j in m
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j])
end
cmat, discrete_indices
@@ -633,13 +637,13 @@ function axis_drawing_info(sp::Subplot)
if sp[:framestyle] != :none
# xaxis
+ y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
+ end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
- y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
- 0.0, 0.0
- else
- xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
- 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 (:none, nothing, false)) && length(xticks) > 1
@@ -652,55 +656,48 @@ function axis_drawing_info(sp::Subplot)
if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
- ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
- t1 = invf(f(ymin) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
- t2 = invf(f(ymax) - 0.015 * (f(ymax) - f(ymin)) * ticks_in)
- t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
+ t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
for xtick in xticks[1]
if xaxis[:showaxis]
- tick_start, tick_stop = if sp[:framestyle] == :origin
- (0, t3)
- else
- xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
- end
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end
- # sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
- end
- 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
- t1 = invf(f(ymin) + 0.01 * (f(ymax) - f(ymin)) * ticks_in)
- t2 = invf(f(ymax) - 0.01 * (f(ymax) - f(ymin)) * ticks_in)
- t3 = invf(f(0) + 0.01 * (f(ymax) - f(ymin)) * ticks_in)
- for xminortick in xminorticks
- if xaxis[:showaxis]
- tick_start, tick_stop = if sp[:framestyle] == :origin
- (0, t3)
- else
- xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
- end
- push!(xtick_segs, (xminortick, tick_start), (xminortick, tick_stop)) # bottom tick
+ if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
+ for xtick in xminorticks
+ if xaxis[:showaxis]
+ push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
+ end
+ xaxis[:minorgrid] && push!(xminorgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
- # sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
- xaxis[:minorgrid] && push!(xminorgrid_segs, (xminortick, ymin), (xminortick, ymax)) # vertical grid
end
end
# yaxis
+ x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
+ end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
- x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
- 0.0, 0.0
- else
- xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
- 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 (:none, nothing,false)) && length(yticks) > 1
@@ -713,46 +710,297 @@ function axis_drawing_info(sp::Subplot)
if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
- ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
- t1 = invf(f(xmin) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
- t2 = invf(f(xmax) - 0.015 * (f(xmax) - f(xmin)) * ticks_in)
- t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.012 * (f(xmax) - f(xmin)))
+ (-t, t)
+ else
+ ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
+ t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
+ (x1, t)
+ end
for ytick in yticks[1]
if yaxis[:showaxis]
- tick_start, tick_stop = if sp[:framestyle] == :origin
- (0, t3)
- else
- xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
- end
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
- # sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
- end
- 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
- t1 = invf(f(xmin) + 0.01 * (f(xmax) - f(xmin)) * ticks_in)
- t2 = invf(f(xmax) - 0.01 * (f(xmax) - f(xmin)) * ticks_in)
- t3 = invf(f(0) + 0.01 * (f(xmax) - f(xmin)) * ticks_in)
- for ytick in yminorticks
- if yaxis[:showaxis]
- tick_start, tick_stop = if sp[:framestyle] == :origin
- (0, t3)
- else
- xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
- end
- push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
+ if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.006 * (f(xmax) - f(xmin)))
+ (-t, t)
+ else
+ t = invf(f(x1) + 0.006 * (f(x2) - f(x1)) * ticks_in)
+ (x1, t)
+ end
+ for ytick in yminorticks
+ if yaxis[:showaxis]
+ push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
+ end
+ yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
- # sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
- yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
end
xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xminorgrid_segs, yminorgrid_segs, xborder_segs, yborder_segs
end
+
+
+function axis_drawing_info_3d(sp::Subplot)
+ xaxis, yaxis, zaxis = sp[:xaxis], sp[:yaxis], sp[:zaxis]
+ xmin, xmax = axis_limits(sp, :x)
+ ymin, ymax = axis_limits(sp, :y)
+ zmin, zmax = axis_limits(sp, :z)
+ xticks = get_ticks(sp, xaxis)
+ yticks = get_ticks(sp, yaxis)
+ zticks = get_ticks(sp, zaxis)
+ xminorticks = get_minor_ticks(sp, xaxis, xticks)
+ yminorticks = get_minor_ticks(sp, yaxis, yticks)
+ zminorticks = get_minor_ticks(sp, zaxis, zticks)
+ xaxis_segs = Segments(3)
+ yaxis_segs = Segments(3)
+ zaxis_segs = Segments(3)
+ xtick_segs = Segments(3)
+ ytick_segs = Segments(3)
+ ztick_segs = Segments(3)
+ xgrid_segs = Segments(3)
+ ygrid_segs = Segments(3)
+ zgrid_segs = Segments(3)
+ xminorgrid_segs = Segments(3)
+ yminorgrid_segs = Segments(3)
+ zminorgrid_segs = Segments(3)
+ xborder_segs = Segments(3)
+ yborder_segs = Segments(3)
+ zborder_segs = Segments(3)
+
+ if sp[:framestyle] != :none
+
+ # xaxis
+ y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
+ end
+ z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(xaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
+ end
+ if xaxis[:showaxis]
+ if sp[:framestyle] != :grid
+ push!(xaxis_segs, (xmin, y1, z1), (xmax, y1, z1))
+ # don't show the 0 tick label for the origin framestyle
+ 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, z2), (xmax, y2, z2)) # top spine
+ end
+ if !(xaxis[:ticks] in (:none, nothing, false))
+ f = scalefunc(yaxis[:scale])
+ invf = invscalefunc(yaxis[:scale])
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
+ t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
+
+ for xtick in xticks[1]
+ if xaxis[:showaxis]
+ push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
+ end
+ if xaxis[:grid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(xgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
+ push!(xgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
+ else
+ push!(xgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
+ push!(xgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
+ end
+ end
+ end
+
+ if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
+ for xtick in xminorticks
+ if xaxis[:showaxis]
+ push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
+ end
+ if xaxis[:minorgrid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(xminorgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
+ push!(xminorgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
+ else
+ push!(xminorgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
+ push!(xminorgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
+ end
+ end
+ end
+ end
+ end
+
+
+ # yaxis
+ x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(yaxis[:mirror], xaxis[:flip]) ? (xmin, xmax) : (xmax, xmin)
+ end
+ z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(yaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
+ end
+ if yaxis[:showaxis]
+ if sp[:framestyle] != :grid
+ push!(yaxis_segs, (x1, ymin, z1), (x1, ymax, z1))
+ # don't show the 0 tick label for the origin framestyle
+ 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, z2), (x2, ymax, z2)) # right spine
+ end
+ if !(yaxis[:ticks] in (:none, nothing, false))
+ f = scalefunc(xaxis[:scale])
+ invf = invscalefunc(xaxis[:scale])
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.012 * (f(xmax) - f(xmin)))
+ (-t, t)
+ else
+ ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
+ t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
+ (x1, t)
+ end
+
+ for ytick in yticks[1]
+ if yaxis[:showaxis]
+ push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
+ end
+ if yaxis[:grid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(ygrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
+ push!(ygrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
+ else
+ push!(ygrid_segs, (x1, ytick, z1), (x2, ytick, z1))
+ push!(ygrid_segs, (x2, ytick, z1), (x2, ytick, z2))
+ end
+ end
+ end
+
+ if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.006 * (f(xmax) - f(xmin)))
+ (-t, t)
+ else
+ t = invf(f(x1) + 0.006 * (f(x2) - f(x1)) * ticks_in)
+ (x1, t)
+ end
+ for ytick in yminorticks
+ if yaxis[:showaxis]
+ push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
+ end
+ if yaxis[:minorgrid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(yminorgrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
+ push!(yminorgrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
+ else
+ push!(yminorgrid_segs, (x1, ytick, z1), (x2, ytick, z1))
+ push!(yminorgrid_segs, (x2, ytick, z1), (x2, ytick, z2))
+ end
+ end
+ end
+ end
+ end
+
+
+ # zaxis
+ x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(zaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
+ end
+ y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
+ 0.0, 0.0
+ else
+ xor(zaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
+ end
+ if zaxis[:showaxis]
+ if sp[:framestyle] != :grid
+ push!(zaxis_segs, (x1, y1, zmin), (x1, y1, zmax))
+ # don't show the 0 tick label for the origin framestyle
+ if sp[:framestyle] == :origin && !(zticks in (:none, nothing,false)) && length(zticks) > 1
+ showticks = zticks[1] .!= 0
+ zticks = (zticks[1][showticks], zticks[2][showticks])
+ end
+ end
+ sp[:framestyle] in (:semi, :box) && push!(zborder_segs, (x2, y2, zmin), (x2, y2, zmax))
+ end
+ if !(zaxis[:ticks] in (:none, nothing, false))
+ f = scalefunc(xaxis[:scale])
+ invf = invscalefunc(xaxis[:scale])
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ ticks_in = zaxis[:tick_direction] == :out ? -1 : 1
+ t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
+
+ for ztick in zticks[1]
+ if zaxis[:showaxis]
+ push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
+ end
+ if zaxis[:grid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(zgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
+ push!(ygrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
+ else
+ push!(ygrid_segs, (x1, y1, ztick), (x1, y2, ztick))
+ push!(ygrid_segs, (x1, y2, ztick), (x2, y2, ztick))
+ end
+ end
+ end
+
+ if !(zaxis[:minorticks] in (:none, nothing, false)) || zaxis[:minorgrid]
+ tick_start, tick_stop = if sp[:framestyle] == :origin
+ t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
+ (-t, t)
+ else
+ t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
+ (y1, t)
+ end
+ for ztick in zminorticks
+ if zaxis[:showaxis]
+ push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
+ end
+ if zaxis[:minorgrid]
+ if sp[:framestyle] in (:origin, :zerolines)
+ push!(zminorgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
+ push!(zminorgrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
+ else
+ push!(zminorgrid_segs, (x1, y1, ztick), (x1, y2, ztick))
+ push!(zminorgrid_segs, (x1, y2, ztick), (x2, y2, ztick))
+ end
+ end
+ end
+ end
+ end
+ end
+
+ xticks, yticks, zticks, xaxis_segs, yaxis_segs, zaxis_segs, xtick_segs, ytick_segs, ztick_segs, xgrid_segs, ygrid_segs, zgrid_segs, xminorgrid_segs, yminorgrid_segs, zminorgrid_segs, xborder_segs, yborder_segs, zborder_segs
+end
diff --git a/src/backends.jl b/src/backends.jl
index a95b2dd2..143a929e 100644
--- a/src/backends.jl
+++ b/src/backends.jl
@@ -37,7 +37,6 @@ macro init_backend(s)
_backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str)
_backend_packages[Symbol($str)] = Symbol($package_str)
- # include("backends/" * $str * ".jl")
end)
end
@@ -77,7 +76,7 @@ text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(l
# account for the size/length/rotation of tick labels
function tick_padding(sp::Subplot, axis::Axis)
ticks = get_ticks(sp, axis)
- if ticks == nothing
+ if ticks === nothing
0mm
else
vals, labs = ticks
@@ -229,7 +228,7 @@ const _base_supported_args = [
:subplot_index,
:discrete_values,
:projection,
-
+ :show_empty_bins
]
function merge_with_base_supported(v::AVec)
@@ -252,6 +251,7 @@ end
@init_backend PlotlyJS
@init_backend GR
@init_backend PGFPlots
+@init_backend PGFPlotsX
@init_backend InspectDR
@init_backend HDF5
@@ -296,9 +296,6 @@ end
_initialize_backend(pkg::GRBackend) = nothing
-_initialize_backend(pkg::PlotlyBackend) = nothing
-
-
# ------------------------------------------------------------------------------
# gr
@@ -357,6 +354,16 @@ is_marker_supported(::GRBackend, shape::Shape) = true
# ------------------------------------------------------------------------------
# plotly
+function _initialize_backend(pkg::PlotlyBackend)
+ try
+ @eval Main begin
+ import ORCA
+ end
+ catch
+ @info "For saving to png with the Plotly backend ORCA has to be installed."
+ end
+end
+
const _plotly_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
@@ -661,3 +668,57 @@ const _inspectdr_marker = Symbol[
]
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
+# ------------------------------------------------------------------------------
+# pgfplotsx
+
+const _pgfplotsx_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, :colorbar_entry,
+ :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 _pgfplotsx_seriestype =
+ [:path, :scatter, :straightline,
+ :path3d, :scatter3d, :surface, :wireframe,
+ :heatmap, :contour, :contour3d,
+ :shape,
+ :steppre, :stepmid, :steppost, :ysticks, :xsticks]
+const _pgfplotsx_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
+const _pgfplotsx_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :ltriangle, :rtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline, Shape]
+const _pgfplotsx_scale = [:identity, :ln, :log2, :log10]
+is_marker_supported(::PGFPlotsXBackend, shape::Shape) = true
diff --git a/src/backends/gr.jl b/src/backends/gr.jl
index 0fa3d210..7db386aa 100644
--- a/src/backends/gr.jl
+++ b/src/backends/gr.jl
@@ -69,6 +69,19 @@ const gr_font_family = Dict(
# --------------------------------------------------------------------------------------
+gr_color(c) = gr_color(c, color_type(c))
+
+gr_color(c, ::Type{<:AbstractRGB}) = 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)) )
+function gr_color(c, ::Type{<:AbstractGray})
+ g = round(UInt, clamp(gray(c) * 255, 0, 255))
+ α = round(UInt, clamp(alpha(c) * 255, 0, 255))
+ rgba = UInt32( α<<24 + g<<16 + g<<8 + g )
+end
+gr_color(c, ::Type) = gr_color(RGBA(c), RGB)
+
function gr_getcolorind(c)
gr_set_transparency(float(alpha(c)))
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
@@ -142,12 +155,54 @@ function gr_polyline(x, y, func = GR.polyline; arrowside = :none, arrowstyle = :
end
end
+function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowstyle = :simple)
+ iend = 0
+ n = length(x)
+ while iend < n-1
+ # set istart to the first index that is finite
+ istart = -1
+ for j = iend+1:n
+ if isfinite(x[j]) && isfinite(y[j]) && isfinite(z[j])
+ istart = j
+ break
+ end
+ end
+
+ if istart > 0
+ # iend is the last finite index
+ iend = -1
+ for j = istart+1:n
+ if isfinite(x[j]) && isfinite(y[j]) && isfinite(z[j])
+ iend = j
+ else
+ break
+ end
+ end
+ end
+
+ # if we found a start and end, draw the line segment, otherwise we're done
+ if istart > 0 && iend > 0
+ func(x[istart:iend], y[istart:iend], z[istart:iend])
+ if arrowside in (:head,:both)
+ gr_set_arrowstyle(arrowstyle)
+ GR.drawarrow(x[iend-1], y[iend-1], z[iend-1], x[iend], y[iend], z[iend])
+ end
+ if arrowside in (:tail,:both)
+ gr_set_arrowstyle(arrowstyle)
+ GR.drawarrow(x[istart+1], y[istart+1], z[istart+1], x[istart], y[istart], z[istart])
+ end
+ else
+ break
+ end
+ end
+end
+
gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.inqmathtex(x, y, s[2:end-1])
- elseif findfirst(isequal('\\'), s) != nothing || occursin("10^{", s)
+ elseif findfirst(isequal('\\'), s) !== nothing || occursin("10^{", s)
GR.inqtextext(x, y, s)
else
GR.inqtext(x, y, s)
@@ -159,7 +214,7 @@ gr_text(x, y, s::Symbol) = gr_text(x, y, string(s))
function gr_text(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.mathtex(x, y, s[2:end-1])
- elseif findfirst(isequal('\\'), s) != nothing || occursin("10^{", s)
+ elseif findfirst(isequal('\\'), s) !== nothing || occursin("10^{", s)
GR.textext(x, y, s)
else
GR.text(x, y, s)
@@ -184,7 +239,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
- for i in 1:length(α)
+ for i in eachindex(α)
GR.polyline([sinf[i], 0], [cosf[i], 0])
end
end
@@ -193,7 +248,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
- for i in 1:length(rtick_values)
+ for i in eachindex(rtick_values)
r = (rtick_values[i] - rmin) / (rmax - rmin)
if r <= 1.0 && r >= 0.0
GR.drawarc(-r, r, -r, r, 0, 359)
@@ -210,7 +265,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw angular ticks
if xaxis[:showaxis]
GR.drawarc(-1, 1, -1, 1, 0, 359)
- for i in 1:length(α)
+ for i in eachindex(α)
x, y = GR.wctondc(1.1 * sinf[i], 1.1 * cosf[i])
GR.textext(x, y, string((360-α[i])%360, "^o"))
end
@@ -218,7 +273,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw radial ticks
if yaxis[:showaxis]
- for i in 1:length(rtick_values)
+ for i in eachindex(rtick_values)
r = (rtick_values[i] - rmin) / (rmax - rmin)
if r <= 1.0 && r >= 0.0
x, y = GR.wctondc(0.05, r)
@@ -236,18 +291,6 @@ 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(sp::Subplot, axis::Axis, adjust::Bool, expand = nothing)
- if expand != nothing
- expand_extrema!(axis, expand)
- end
- lims = axis_limits(sp, axis[:letter])
- if adjust
- GR.adjustrange(lims...)
- else
- lims
- end
-end
-
function gr_fill_viewport(vp::AVec{Float64}, c)
GR.savestate()
@@ -260,19 +303,6 @@ function gr_fill_viewport(vp::AVec{Float64}, c)
GR.restorestate()
end
-
-normalize_zvals(args...) = nothing
-function normalize_zvals(zv::AVec, clims::NTuple{2, <:Real})
- vmin, vmax = ignorenan_extrema(zv)
- isfinite(clims[1]) && (vmin = clims[1])
- isfinite(clims[2]) && (vmax = clims[2])
- if vmin == vmax
- zeros(length(zv))
- else
- clamp.((zv .- vmin) ./ (vmax .- vmin), 0, 1)
- end
-end
-
# ---------------------------------------------------------
# draw ONE Shape
@@ -305,7 +335,7 @@ function gr_draw_markers(series::Series, x, y, clims, msize = series[:markersize
shapes = series[:markershape]
if shapes != :none
- for i=1:length(x)
+ for i=eachindex(x)
msi = _cycle(msize, i)
shape = _cycle(shapes, i)
cfunc = isa(shape, Shape) ? gr_set_fillcolor : gr_set_markercolor
@@ -370,6 +400,12 @@ function gr_nans_to_infs!(z)
end
end
+function gr_w3tondc(x, y, z)
+ xw, yw, zw = GR.wc3towc(x, y, z)
+ x, y = GR.wctondc(xw, yw)
+ return x, y
+end
+
# --------------------------------------------------------------------------------------
# viewport plot area
@@ -388,16 +424,8 @@ function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, vi
viewport[2] = viewport_canvas[2] * (right(bb) / w)
viewport[3] = viewport_canvas[4] * (1.0 - bottom(bb) / h)
viewport[4] = viewport_canvas[4] * (1.0 - top(bb) / h)
- if is3d(sp)
- vp = viewport[:]
- extent = min(vp[2] - vp[1], vp[4] - vp[3])
- viewport[1] = 0.5 * (vp[1] + vp[2] - extent)
- viewport[2] = 0.5 * (vp[1] + vp[2] + extent)
- viewport[3] = 0.5 * (vp[3] + vp[4] - extent)
- viewport[4] = 0.5 * (vp[3] + vp[4] + extent)
- end
if hascolorbar(sp)
- viewport[2] -= gr_colorbar_ratio
+ viewport[2] -= gr_colorbar_ratio * (1 + is3d(sp) / 2)
end
viewport
end
@@ -481,7 +509,7 @@ 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."
+ "Colorbar may not reflect all series correctly."
end
out
end
@@ -567,13 +595,13 @@ function gr_legend_pos(sp::Subplot, w, h)
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 + ymirror * gr_yaxis_width(sp)
+ xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_axis_width(sp, sp[:yaxis])
else
xpos = viewport_plotarea[2] - 0.05 - w
end
elseif occursin("left", str)
if occursin("outer", str)
- xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_yaxis_width(sp)
+ xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_axis_width(sp, sp[:yaxis])
else
xpos = viewport_plotarea[1] + 0.11
end
@@ -582,13 +610,13 @@ function gr_legend_pos(sp::Subplot, w, h)
end
if occursin("top", str)
if s == :outertop
- ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_xaxis_height(sp)
+ ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_axis_height(sp, sp[:xaxis])
else
ypos = viewport_plotarea[4] - 0.06
end
elseif occursin("bottom", str)
if s == :outerbottom
- ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_xaxis_height(sp)
+ ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_axis_height(sp, sp[:xaxis])
else
ypos = viewport_plotarea[3] + h + 0.06
end
@@ -629,11 +657,11 @@ function gr_get_color(series::Series)
series[:fillcolor]
elseif st in (:contour, :wireframe)
series[:linecolor]
- elseif series[:marker_z] != nothing
+ elseif series[:marker_z] !== nothing
series[:markercolor]
- elseif series[:line_z] != nothing
+ elseif series[:line_z] !== nothing
series[:linecolor]
- elseif series[:fill_z] != nothing
+ elseif series[:fill_z] !== nothing
series[:fillcolor]
end
end
@@ -747,26 +775,24 @@ 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]))
+function gr_axis_height(sp, axis)
+ ticks = get_ticks(sp, axis)
+ gr_set_font(tickfont(axis))
+ h = (ticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(ticks, axis[:rotation])))
+ if axis[:guide] != ""
+ gr_set_font(guidefont(axis))
+ h += last(gr_text_size(axis[: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]))
+function gr_axis_width(sp, axis)
+ ticks = get_ticks(sp, axis)
+ gr_set_font(tickfont(axis))
+ w = (ticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(ticks, axis[:rotation])))
+ if axis[:guide] != ""
+ gr_set_font(guidefont(axis))
+ w += last(gr_text_size(axis[:guide]))
end
return w
end
@@ -790,48 +816,132 @@ function _update_min_padding!(sp::Subplot{GRBackend})
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 = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
- h = 1mm + gr_plot_size[2] * l * px
- if mirror
- toppad += h
- else
- bottompad += h
+
+ if is3d(sp)
+ xaxis, yaxis, zaxis = sp[:xaxis], sp[:yaxis], sp[:zaxis]
+ xticks, yticks, zticks = get_ticks(sp, xaxis), get_ticks(sp, yaxis), get_ticks(sp, zaxis)
+ # Add margin for x and y ticks
+ h = 0mm
+ if !(xticks in (nothing, false, :none))
+ gr_set_font(
+ tickfont(xaxis),
+ halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
+ valign = (xaxis[:mirror] ? :bottom : :top),
+ rotation = xaxis[:rotation]
+ )
+ l = 0.01 + last(gr_get_ticks_size(xticks, xaxis[:rotation]))
+ h = max(h, 1mm + gr_plot_size[2] * l * px)
end
- end
- if !(yticks in (nothing, false, :none))
- flip, mirror = gr_set_yticks_font(sp)
- l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
- w = 1mm + gr_plot_size[1] * l * px
- if mirror
- rightpad += w
- else
- leftpad += w
+ if !(yticks in (nothing, false, :none))
+ gr_set_font(
+ tickfont(yaxis),
+ halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
+ valign = (yaxis[:mirror] ? :bottom : :top),
+ rotation = yaxis[:rotation]
+ )
+ l = 0.01 + last(gr_get_ticks_size(yticks, yaxis[:rotation]))
+ h = max(h, 1mm + gr_plot_size[2] * l * px)
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 += h
- else
- bottompad += h
+ if h > 0mm
+ if xaxis[:mirror] || yaxis[:mirror]
+ toppad += h
+ end
+ if !xaxis[:mirror] || !yaxis[:mirror]
+ bottompad += h
+ end
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 += w
- else
- leftpad += w
+
+ if !(zticks in (nothing, false, :none))
+ gr_set_font(
+ tickfont(zaxis),
+ halign = (zaxis[:mirror] ? :left : :right),
+ valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
+ rotation = zaxis[:rotation]
+ )
+ l = 0.01 + first(gr_get_ticks_size(zticks, zaxis[:rotation]))
+ w = 1mm + gr_plot_size[1] * l * px
+ if zaxis[:mirror]
+ rightpad += w
+ else
+ leftpad += w
+ end
+ end
+
+ # Add margin for x or y label
+ h = 0mm
+ if xaxis[:guide] != ""
+ gr_set_font(guidefont(sp[:xaxis]))
+ l = last(gr_text_size(sp[:xaxis][:guide]))
+ h = max(h, 1mm + gr_plot_size[2] * l * px)
+ end
+ if yaxis[:guide] != ""
+ gr_set_font(guidefont(sp[:yaxis]))
+ l = last(gr_text_size(sp[:yaxis][:guide]))
+ h = max(h, 1mm + gr_plot_size[2] * l * px)
+ end
+ if h > 0mm
+ if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
+ toppad += h
+ else
+ bottompad += h
+ end
+ end
+ # Add margin for z label
+ if zaxis[:guide] != ""
+ gr_set_font(guidefont(sp[:zaxis]))
+ l = last(gr_text_size(sp[:zaxis][:guide]))
+ w = 1mm + gr_plot_size[2] * l * px
+ if zaxis[:guide_position] == :right || (zaxis[:guide_position] == :auto && zaxis[:mirror] == true)
+ rightpad += w
+ else
+ leftpad += w
+ end
+ end
+ else
+ # Add margin for x and y ticks
+ xticks, yticks = get_ticks(sp, sp[:xaxis]), get_ticks(sp, sp[:yaxis])
+ if !(xticks in (nothing, false, :none))
+ flip, mirror = gr_set_xticks_font(sp)
+ l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
+ h = 1mm + gr_plot_size[2] * l * px
+ if mirror
+ toppad += h
+ else
+ bottompad += h
+ end
+ end
+ if !(yticks in (nothing, false, :none))
+ flip, mirror = gr_set_yticks_font(sp)
+ l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
+ w = 1mm + gr_plot_size[1] * l * px
+ if mirror
+ rightpad += w
+ else
+ 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 += h
+ else
+ 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 += w
+ else
+ leftpad += w
+ end
end
end
if sp[:colorbar_title] != ""
@@ -840,6 +950,11 @@ function _update_min_padding!(sp::Subplot{GRBackend})
sp.minpad = Tuple(dpi * [leftpad, toppad, rightpad, bottompad])
end
+function is_equally_spaced(v)
+ d = collect(v[2:end] .- v[1:end-1])
+ all(d .≈ d[1])
+end
+
function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
_update_min_padding!(sp)
@@ -874,26 +989,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# 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
+ if sp[:legendtitle] !== nothing
+ gr_set_font(legendtitlefont(sp))
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
legendw = tbx[3] - tbx[1]
legendn += 1
end
+ gr_set_font(legendfont(sp))
for series in series_list(sp)
should_add_to_legend(series) || continue
legendn += 1
- if typeof(series[:label]) <: Array
- legendi += 1
- lab = series[:label][legendi]
- else
- lab = series[:label]
- end
+ lab = series[:label]
tbx, tby = gr_inqtext(0, 0, string(lab))
legendw = max(legendw, tbx[3] - tbx[1])
end
@@ -908,7 +1018,7 @@ 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.11
+ viewport_plotarea[2] -= legendw + 0.12
elseif occursin("left", leg_str)
viewport_plotarea[1] += legendw + 0.11
elseif occursin("top", leg_str)
@@ -920,13 +1030,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# fill in the plot area background
bg = plot_color(sp[:background_color_inside])
- gr_fill_viewport(viewport_plotarea, bg)
+ is3d(sp) || gr_fill_viewport(viewport_plotarea, bg)
# reduced from before... set some flags based on the series in this subplot
# TODO: can these be generic flags?
outside_ticks = false
- # calculate the colorbar limits once for a subplot
- clims = get_clims(sp)
cbar = GRColorbar()
draw_axes = sp[:framestyle] != :none
@@ -940,11 +1048,8 @@ 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 length(v) > 1 && diff(collect(extrema(diff(v))))[1] > 1e-6*std(v)
- @warn("GR: heatmap only supported with equally spaced data.")
- end
end
- x, y = heatmap_edges(series[:x], sp[:xaxis][:scale]), heatmap_edges(series[:y], sp[:yaxis][:scale])
+ x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
xy_lims = x[1], x[end], y[1], y[end]
expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y)
@@ -1000,39 +1105,228 @@ 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(sp, zaxis, true)
- clims3d = sp[:clims]
- if is_2tuple(clims3d)
- isfinite(clims3d[1]) && (zmin = clims3d[1])
- isfinite(clims3d[2]) && (zmax = clims3d[2])
- end
+ zmin, zmax = axis_limits(sp, :z)
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...)
- xtick = GR.tick(xmin, xmax) / 2
- ytick = GR.tick(ymin, ymax) / 2
- ztick = GR.tick(zmin, zmax) / 2
- ticksize = 0.01 * (viewport_plotarea[2] - viewport_plotarea[1])
+ xticks, yticks, zticks, xaxis_segs, yaxis_segs, zaxis_segs, xtick_segs, ytick_segs, ztick_segs, xgrid_segs, ygrid_segs, zgrid_segs, xminorgrid_segs, yminorgrid_segs, zminorgrid_segs, xborder_segs, yborder_segs, zborder_segs = axis_drawing_info_3d(sp)
+
+ # fill the plot area
+ gr_set_fill(sp[:background_color_inside])
+ plot_area_x = [xmin, xmin, xmin, xmax, xmax, xmax, xmin]
+ plot_area_y = [ymin, ymin, ymax, ymax, ymax, ymin, ymin]
+ plot_area_z = [zmin, zmax, zmax, zmax, zmin, zmin, zmin]
+ x_bg, y_bg = unzip(GR.wc3towc.(plot_area_x, plot_area_y, plot_area_z))
+ GR.fillarea(x_bg, y_bg)
+
+ # draw the grid lines
if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
- GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0)
+ gr_polyline3d(coords(xgrid_segs)...)
end
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
- GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0)
+ gr_polyline3d(coords(ygrid_segs)...)
end
if zaxis[:grid]
gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid])
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha])
- GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2)
+ gr_polyline3d(coords(zgrid_segs)...)
end
- gr_set_line(1, :solid, xaxis[:foreground_color_axis])
- 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)
+
+ if xaxis[:minorgrid]
+ gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid])
+ gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha])
+ gr_polyline3d(coords(xminorgrid_segs)...)
+ end
+ if yaxis[:minorgrid]
+ gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid])
+ gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha])
+ gr_polyline3d(coords(yminorgrid_segs)...)
+ end
+ if zaxis[:minorgrid]
+ gr_set_line(zaxis[:minorgridlinewidth], zaxis[:minorgridstyle], zaxis[:foreground_color_minor_grid])
+ gr_set_transparency(zaxis[:foreground_color_minor_grid], zaxis[:minorgridalpha])
+ gr_polyline3d(coords(zminorgrid_segs)...)
+ end
+ gr_set_transparency(1.0)
+
+ # axis lines
+ if xaxis[:showaxis]
+ gr_set_line(1, :solid, xaxis[:foreground_color_border])
+ GR.setclip(0)
+ gr_polyline3d(coords(xaxis_segs)...)
+ end
+ if yaxis[:showaxis]
+ gr_set_line(1, :solid, yaxis[:foreground_color_border])
+ GR.setclip(0)
+ gr_polyline3d(coords(yaxis_segs)...)
+ end
+ if zaxis[:showaxis]
+ gr_set_line(1, :solid, zaxis[:foreground_color_border])
+ GR.setclip(0)
+ gr_polyline3d(coords(zaxis_segs)...)
+ end
+ GR.setclip(1)
+
+ # axis ticks
+ if xaxis[:showaxis]
+ if sp[:framestyle] in (:zerolines, :grid)
+ gr_set_line(1, :solid, xaxis[:foreground_color_grid])
+ 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
+ GR.setclip(0)
+ gr_polyline3d(coords(xtick_segs)...)
+ end
+ if yaxis[:showaxis]
+ if sp[:framestyle] in (:zerolines, :grid)
+ gr_set_line(1, :solid, yaxis[:foreground_color_grid])
+ 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
+ GR.setclip(0)
+ gr_polyline3d(coords(ytick_segs)...)
+ end
+ if zaxis[:showaxis]
+ if sp[:framestyle] in (:zerolines, :grid)
+ gr_set_line(1, :solid, zaxis[:foreground_color_grid])
+ gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:tick_direction] == :out ? zaxis[:gridalpha] : 0)
+ else
+ gr_set_line(1, :solid, zaxis[:foreground_color_axis])
+ end
+ GR.setclip(0)
+ gr_polyline3d(coords(ztick_segs)...)
+ end
+ GR.setclip(1)
+
+ # tick marks
+ if !(xticks in (:none, nothing, false)) && xaxis[:showaxis]
+ # x labels
+ gr_set_font(
+ tickfont(xaxis),
+ halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
+ valign = (xaxis[:mirror] ? :bottom : :top),
+ rotation = xaxis[:rotation]
+ )
+ yt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(xaxis[:mirror], yaxis[:flip])
+ ymax
+ else
+ ymin
+ end
+ zt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(xaxis[:mirror], zaxis[:flip])
+ zmax
+ else
+ zmin
+ end
+ for (cv, dv) in zip(xticks...)
+ xi, yi = gr_w3tondc(cv, yt, zt)
+ if xaxis[:ticks] in (:auto, :native)
+ if xaxis[:formatter] in (:scientific, :auto)
+ # ensure correct dispatch in gr_text for automatic log ticks
+ if xaxis[:scale] in _logScales
+ dv = string(dv, "\\ ")
+ end
+ dv = convert_sci_unicode(dv)
+ end
+ end
+ xi += (yaxis[:mirror] ? 1 : -1) * 1e-2 * (xaxis[:tick_direction] == :out ? 1.5 : 1.0)
+ yi += (xaxis[:mirror] ? 1 : -1) * 5e-3 * (xaxis[:tick_direction] == :out ? 1.5 : 1.0)
+ gr_text(xi, yi, string(dv))
+ end
+ end
+
+ if !(yticks in (:none, nothing, false)) && yaxis[:showaxis]
+ # y labels
+ gr_set_font(
+ tickfont(yaxis),
+ halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
+ valign = (yaxis[:mirror] ? :bottom : :top),
+ rotation = yaxis[:rotation]
+ )
+ xt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(yaxis[:mirror], xaxis[:flip])
+ xmin
+ else
+ xmax
+ end
+ zt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(yaxis[:mirror], zaxis[:flip])
+ zmax
+ else
+ zmin
+ end
+ for (cv, dv) in zip(yticks...)
+ xi, yi = gr_w3tondc(xt, cv, zt)
+ if yaxis[:ticks] in (:auto, :native)
+ if xaxis[:formatter] in (:scientific, :auto)
+ # ensure correct dispatch in gr_text for automatic log ticks
+ if yaxis[:scale] in _logScales
+ dv = string(dv, "\\ ")
+ end
+ dv = convert_sci_unicode(dv)
+ end
+ end
+ gr_text(xi + (yaxis[:mirror] ? -1 : 1) * 1e-2 * (yaxis[:tick_direction] == :out ? 1.5 : 1.0), yi + (yaxis[:mirror] ? 1 : -1) * 5e-3 * (yaxis[:tick_direction] == :out ? 1.5 : 1.0), string(dv))
+ end
+ end
+
+ if !(zticks in (:none, nothing, false)) && zaxis[:showaxis]
+ # z labels
+ gr_set_font(
+ tickfont(zaxis),
+ halign = (zaxis[:mirror] ? :left : :right),
+ valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
+ rotation = zaxis[:rotation]
+ )
+ xt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(zaxis[:mirror], xaxis[:flip])
+ xmax
+ else
+ xmin
+ end
+ yt = if sp[:framestyle] == :origin
+ 0
+ elseif xor(zaxis[:mirror], yaxis[:flip])
+ ymax
+ else
+ ymin
+ end
+ for (cv, dv) in zip(zticks...)
+ xi, yi = gr_w3tondc(xt, yt, cv)
+ if zaxis[:ticks] in (:auto, :native)
+ if zaxis[:formatter] in (:scientific, :auto)
+ # ensure correct dispatch in gr_text for automatic log ticks
+ if zaxis[:scale] in _logScales
+ dv = string(dv, "\\ ")
+ end
+ dv = convert_sci_unicode(dv)
+ end
+ end
+ gr_text(xi + (zaxis[:mirror] ? 1 : -1) * 1e-2 * (zaxis[:tick_direction] == :out ? 1.5 : 1.0), yi, string(dv))
+ end
+ end
+ #
+ # # border
+ # 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(xaxis[:foreground_color_border], intensity)
+ # gr_polyline3d(coords(xborder_segs)...)
+ # gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
+ # gr_set_transparency(yaxis[:foreground_color_border], intensity)
+ # gr_polyline3d(coords(yborder_segs)...)
+ # end
elseif ispolar(sp)
r = gr_set_viewport_polar()
@@ -1121,9 +1415,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# @show cv dv ymin xi yi flip mirror (flip $ mirror)
if xaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks
- if xaxis[:scale] in _logScales
- dv = string(dv, "\\ ")
- elseif xaxis[:formatter] in (:scientific, :auto)
+ if xaxis[:formatter] in (:scientific, :auto)
+ if xaxis[:scale] in _logScales
+ dv = string(dv, "\\ ")
+ end
dv = convert_sci_unicode(dv)
end
end
@@ -1140,9 +1435,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# @show cv dv xmin xi yi
if yaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks
- if yaxis[:scale] in _logScales
- dv = string(dv, "\\ ")
- elseif yaxis[:formatter] in (:scientific, :auto)
+ if yaxis[:formatter] in (:scientific, :auto)
+ if yaxis[:scale] in _logScales
+ dv = string(dv, "\\ ")
+ end
dv = convert_sci_unicode(dv)
end
end
@@ -1182,12 +1478,54 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_text(xpos, viewport_subplot[4], sp[:title])
end
if is3d(sp)
- 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),
+ halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
+ valign = (xaxis[:mirror] ? :bottom : :top),
+ rotation = xaxis[:rotation]
+ )
+ yg = xor(xaxis[:mirror], yaxis[:flip]) ? ymax : ymin
+ zg = xor(xaxis[:mirror], zaxis[:flip]) ? zmax : zmin
+ xg = (xmin + xmax) / 2
+ xndc, yndc = gr_w3tondc(xg, yg, zg)
+ h = gr_axis_height(sp, xaxis)
+ gr_text(xndc - h, yndc - h, xaxis[:guide])
+ end
+
+ if yaxis[:guide] != ""
+ gr_set_font(
+ guidefont(yaxis),
+ halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
+ valign = (yaxis[:mirror] ? :bottom : :top),
+ rotation = yaxis[:rotation]
+ )
+ xg = xor(yaxis[:mirror], xaxis[:flip]) ? xmin : xmax
+ yg = (ymin + ymax) / 2
+ zg = xor(yaxis[:mirror], zaxis[:flip]) ? zmax : zmin
+ xndc, yndc = gr_w3tondc(xg, yg, zg)
+ h = gr_axis_height(sp, yaxis)
+ gr_text(xndc + h, yndc - h, yaxis[:guide])
+ end
+
+ if zaxis[:guide] != ""
+ gr_set_font(
+ guidefont(zaxis),
+ halign = (:left, :hcenter, :right)[sign(zaxis[:rotation]) + 2],
+ valign = (zaxis[:mirror] ? :bottom : :top),
+ rotation = zaxis[:rotation]
+ )
+ xg = xor(zaxis[:mirror], xaxis[:flip]) ? xmax : xmin
+ yg = xor(zaxis[:mirror], yaxis[:flip]) ? ymax : ymin
+ zg = (zmin + zmax) / 2
+ xndc, yndc = gr_w3tondc(xg, yg, zg)
+ w = gr_axis_width(sp, zaxis)
+ GR.setcharup(-1, 0)
+ gr_text(xndc - w, yndc, zaxis[:guide])
+ end
+ else
+ if xaxis[:guide] != ""
+ h = 0.01 + gr_axis_height(sp, xaxis)
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)
@@ -1199,7 +1537,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if yaxis[:guide] != ""
- w = 0.02 + gr_yaxis_width(sp)
+ w = 0.02 + gr_axis_width(sp, yaxis)
gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
@@ -1239,6 +1577,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
x, y, z = series[:x], series[:y], series[:z]
frng = series[:fillrange]
+ clims = get_clims(sp, series)
+
# add custom frame shapes to markershape?
series_annotations_shapes!(series)
# -------------------------------------------------------
@@ -1247,7 +1587,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if typeof(z) <: Surface
z = vec(transpose_z(series, z.surf, false))
elseif ispolar(sp)
- if frng != nothing
+ if frng !== nothing
_, frng = convert_to_polar(x, frng, (rmin, rmax))
end
x, y = convert_to_polar(x, y, (rmin, rmax))
@@ -1258,11 +1598,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if st in (:path, :scatter, :straightline)
- if x != nothing && length(x) > 1
+ if x !== nothing && length(x) > 1
lz = series[:line_z]
segments = iter_segments(series)
# do area fill
- if frng != nothing
+ if frng !== nothing
GR.setfillintstyle(GR.INTSTYLE_SOLID)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i, rng) in enumerate(segments)
@@ -1301,7 +1641,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
plot_color(series[:linecolor]) in (black,[black])
end
h = gr_contour_levels(series, clims)
- if series[:fillrange] != nothing
+ if series[:fillrange] !== nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines")
end
@@ -1335,26 +1675,45 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :heatmap
zmin, zmax = clims
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)
+ x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
+ w, h = length(x) - 1, length(y) - 1
+ z_normalized = map(x -> GR.jlgr.normalize_color(x, zmin, zmax), z)
+ if is_uniformly_spaced(x) && is_uniformly_spaced(y)
+ # For uniformly spaced data use GR.drawimage, which can be
+ # much faster than GR.nonuniformcellarray, especially for
+ # pdf output, and also supports alpha values.
+ # Note that drawimage draws uniformly spaced data correctly
+ # even on log scales, where it is visually non-uniform.
+ colors = plot_color.(series[:fillcolor][z_normalized], series[:fillalpha])
+ colors[isnan.(z_normalized)] .= RGBA(0,0,0,0)
+ rgba = gr_color.(colors)
+ GR.drawimage(first(x), last(x), last(y), first(y), w, h, rgba)
+ else
+ (something(series[:fillalpha],1) < 1 || any(_gr_gradient_alpha .< 1)) && @warn(
+ "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored.")
+ z_normalized = map(x -> isnan(x) ? 256/255 : x, z_normalized) # results in color index = 1256 -> transparent
+ colors = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
+ GR.nonuniformcellarray(x, y, w, h, colors)
+ end
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)
+ phimin, phimax = 0.0, 360.0 # nonuniform polar array is not yet supported in GR.jl
+ nx, ny = length(series[:x]), length(series[:y])
+ z_normalized = map(x -> GR.jlgr.normalize_color(x, zmin, zmax), z)
+ colors = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
+ xmin, xmax, ymin, ymax = xy_lims
+ rmax = data_lims[4]
+ GR.setwindow(-rmax, rmax, -rmax, rmax)
+ if ymin > 0
+ @warn "'ymin[1] > 0' (rmin) is not yet supported."
+ end
+ if series[:y][end] != ny
+ @warn "Right now only the maximum value of y (r) is taken into account."
+ end
+ # GR.polarcellarray(0, 0, phimin, phimax, ymin, ymax, nx, ny, colors)
+ GR.polarcellarray(0, 0, phimin, phimax, 0, ymax, nx, ny, colors)
+ # Right now only the maximum value of y (r) is taken into account.
+ # This is certainly not perfect but nonuniform polar array is not yet supported in GR.jl
end
elseif st in (:path3d, :scatter3d)
@@ -1454,19 +1813,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :image
z = transpose_z(series, series[:z].surf, true)'
w, h = size(z)
- xinds = sort(1:w, rev = xaxis[:flip])
- yinds = sort(1:h, rev = yaxis[:flip])
- z = z[xinds, yinds]
xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
- if eltype(z) <: Colors.AbstractGray
- 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, 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
+ rgba = gr_color.(z)
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
end
@@ -1481,7 +1829,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
# draw the colorbar
- hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims)
+ hascolorbar(sp) && gr_draw_colorbar(cbar, sp, get_clims(sp))
# add the legend
if sp[:legend] != :none
@@ -1490,7 +1838,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setscale(0)
gr_set_font(legendfont(sp))
w = legendw
- i = legendi
n = legendn
if w > 0
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
@@ -1502,20 +1849,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_set_line(1, :solid, sp[:foreground_color_legend])
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
i = 0
- if sp[:legendtitle] != nothing
+ if sp[:legendtitle] !== nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
- gr_set_textcolor(sp[:legendfontcolor])
- gr_set_transparency(sp[:legendfontcolor])
+ gr_set_font(legendtitlefont(sp))
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy
+ gr_set_font(legendfont(sp))
end
for series in series_list(sp)
+ clims = get_clims(sp, series)
should_add_to_legend(series) || continue
st = series[:seriestype]
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
+ if (st == :shape || series[:fillrange] !== nothing) && series[:ribbon] === nothing
fc = get_fillcolor(series, clims)
gr_set_fill(fc) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01
@@ -1532,7 +1880,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if st in (:path, :straightline)
gr_set_transparency(lc, get_linealpha(series))
- if series[:fillrange] == nothing || series[:ribbon] != nothing
+ if series[:fillrange] === nothing || series[:ribbon] !== nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
else
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos+0.4dy, ypos+0.4dy])
@@ -1543,14 +1891,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_draw_markers(series, xpos - .035, ypos, clims, 6)
end
- if typeof(series[:label]) <: Array
- i += 1
- lab = series[:label][i]
- else
- lab = series[:label]
- end
+ lab = series[:label]
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
- gr_set_textcolor(sp[:legendfontcolor])
+ gr_set_textcolor(plot_color(sp[:legendfontcolor]))
gr_text(xpos, ypos, string(lab))
ypos -= dy
end
@@ -1573,7 +1916,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...)
x, y = if is3d(sp)
- # GR.wc3towc(x, y, z)
+ gr_w3tondc(x, y, z)
else
GR.wctondc(x, y)
end
diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl
index c1e5c5b8..e9ad4cc4 100644
--- a/src/backends/inspectdr.jl
+++ b/src/backends/inspectdr.jl
@@ -121,9 +121,9 @@ function _create_backend_figure(plt::Plot{InspectDRBackend})
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
- if plt[:overwrite_figure] && mplot != nothing
+ if plt[:overwrite_figure] && mplot !== nothing
mplot.subplots = [] #Reset
- if gplot != nothing #Ensure still references current plot
+ if gplot !== nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
diff --git a/src/backends/orca.jl b/src/backends/orca.jl
new file mode 100644
index 00000000..9bc4471c
--- /dev/null
+++ b/src/backends/orca.jl
@@ -0,0 +1,24 @@
+function plotlybase_syncplot(plt::Plot)
+ plt.o = ORCA.PlotlyBase.Plot()
+ traces = ORCA.PlotlyBase.GenericTrace[]
+ for series_dict in plotly_series(plt)
+ plotly_type = pop!(series_dict, :type)
+ push!(traces, ORCA.PlotlyBase.GenericTrace(plotly_type; series_dict...))
+ end
+ ORCA.PlotlyBase.addtraces!(plt.o, traces...)
+ layout = plotly_layout(plt)
+ w, h = plt[:size]
+ ORCA.PlotlyBase.relayout!(plt.o, layout, width = w, height = h)
+ return plt.o
+end
+
+const _orca_mimeformats = Dict(
+ "application/pdf" => "pdf",
+ "image/png" => "png",
+ "image/svg+xml" => "svg",
+ "image/eps" => "eps",
+)
+
+for (mime, fmt) in _orca_mimeformats
+ @eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyBackend}) = ORCA.PlotlyBase.savefig(io, plotlybase_syncplot(plt), format = $fmt)
+end
diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl
index 8f849c07..378473c5 100644
--- a/src/backends/pgfplots.jl
+++ b/src/backends/pgfplots.jl
@@ -96,7 +96,7 @@ pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(plotattributes, i)
- if fa != nothing
+ if fa !== nothing
a = fa
end
"fill = $cstr, fill opacity=$a"
@@ -128,16 +128,18 @@ function pgf_marker(plotattributes, i = 1)
shape = _cycle(plotattributes[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i)))
cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i)))
- """
- mark = $(get(_pgfplots_markers, shape, "*")),
- mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),
- mark options = {
- color = $cstr_stroke, draw opacity = $a_stroke,
- fill = $cstr, fill opacity = $a,
- line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
- rotate = $(shape == :dtriangle ? 180 : 0),
- $(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
- }"""
+ return string(
+ "mark = $(get(_pgfplots_markers, shape, "*")),\n",
+ "mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),\n",
+ plotattributes[:seriestype] == :scatter ? "only marks,\n" : "",
+ "mark options = {
+ color = $cstr_stroke, draw opacity = $a_stroke,
+ fill = $cstr, fill opacity = $a,
+ line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
+ rotate = $(shape == :dtriangle ? 180 : 0),
+ $(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
+ }"
+ )
end
function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1)
@@ -178,11 +180,11 @@ function pgf_series(sp::Subplot, series::Series)
end
# PGFPlots can't handle non-Vector?
- args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
- collect(a)
- else
- a
- end, args)
+ # args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
+ # collect(a)
+ # else
+ # a
+ # end, args)
if st in (:contour, :histogram2d)
style = []
@@ -216,12 +218,12 @@ function pgf_series(sp::Subplot, series::Series)
# add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
- if plotattributes[:fillrange] != nothing
+ if plotattributes[:fillrange] !== nothing
push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
else
kw[:legendentry] = plotattributes[:label]
- if st == :shape # || plotattributes[:fillrange] != nothing
+ if st == :shape # || plotattributes[:fillrange] !== nothing
push!(style, "area legend")
end
end
@@ -238,7 +240,7 @@ function pgf_series(sp::Subplot, series::Series)
kw[:style] = join(style, ',')
# add fillrange
- if series[:fillrange] != nothing && st != :shape
+ if series[:fillrange] !== nothing && st != :shape
push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
end
@@ -476,8 +478,18 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos]
end
- cstr, a = pgf_color(plot_color(sp[:background_color_legend]))
- push!(style, string("legend style = {", pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], 1.0, "solid"), ",", "fill = $cstr,", "font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)), "}"))
+ cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend]))
+ fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
+
+ push!(style, string(
+ "legend style = {",
+ pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], fg_alpha, "solid", ), ",",
+ "fill = $cstr,",
+ "fill opacity = $bg_alpha,",
+ "text opacity = $(alpha(plot_color(sp[:legendfontcolor]))),",
+ "font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)),
+ "}",
+ ))
if any(s[:seriestype] == :contour for s in series_list(sp))
kw[:view] = "{0}{90}"
diff --git a/src/backends/pgfplotsx.jl b/src/backends/pgfplotsx.jl
new file mode 100644
index 00000000..367f181a
--- /dev/null
+++ b/src/backends/pgfplotsx.jl
@@ -0,0 +1,862 @@
+using Contour: Contour
+using UUIDs
+Base.@kwdef mutable struct PGFPlotsXPlot
+ is_created::Bool = false
+ was_shown::Bool = false
+ the_plot::PGFPlotsX.TikzDocument = PGFPlotsX.TikzDocument()
+ function PGFPlotsXPlot(is_created, was_shown, the_plot)
+ pgfx_plot = new(is_created, was_shown, the_plot)
+ # tikz libraries
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{arrows.meta}")
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{backgrounds}")
+ # pgfplots libraries
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{patchplots}")
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{fillbetween}")
+ # compatibility fixes
+ # add background layer to standard layers
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
+ raw"""
+ \pgfplotsset{
+ /pgfplots/layers/axis on top/.define layer set={
+ background, axis background,pre main,main,axis grid,axis ticks,axis lines,axis tick labels,
+ axis descriptions,axis foreground
+ }{/pgfplots/layers/standard},
+ }
+ """
+ )
+ pgfx_plot
+ end
+end
+
+## end user utility functions
+function pgfx_axes(pgfx_plot::PGFPlotsXPlot)
+ gp = pgfx_plot.the_plot.elements[1].elements[1]
+ return gp isa PGFPlotsX.GroupPlot ? gp.contents : gp
+end
+
+function pgfx_preamble(pgfx_plot::Plot{PGFPlotsXBackend})
+ old_flag = pgfx_plot.attr[:tex_output_standalone]
+ pgfx_plot.attr[:tex_output_standalone] = true
+ fulltext = String(repr("application/x-tex", pgfx_plot))
+ preamble = fulltext[1:first(findfirst("\\begin{document}", fulltext)) - 1]
+ pgfx_plot.attr[:tex_output_standalone] = old_flag
+ preamble
+end
+##
+
+function surface_to_vecs(x::AVec, y::AVec, s::Union{AMat, Surface})
+ a = Array(s)
+ xn = Vector{eltype(x)}(undef, length(a))
+ yn = Vector{eltype(y)}(undef, length(a))
+ zn = Vector{eltype(s)}(undef, length(a))
+ for (n, (i, j)) in enumerate(Tuple.(CartesianIndices(a)))
+ xn[n] = x[j]
+ yn[n] = y[i]
+ zn[n] = a[i,j]
+ end
+ return xn, yn, zn
+end
+
+function Base.push!(pgfx_plot::PGFPlotsXPlot, item)
+ push!(pgfx_plot.the_plot, item)
+end
+
+function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
+ if !pgfx_plot.is_created
+ the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options())
+ rows, cols = size(plt.layout.grid)
+ bgc = plt.attr[:background_color_outside] == :match ? plt.attr[:background_color] : plt.attr[:background_color_outside]
+ if bgc isa Colors.Colorant
+ cstr = plot_color(bgc)
+ a = alpha(cstr)
+ push!(the_plot.options,
+ "/tikz/background rectangle/.style" => PGFPlotsX.Options(
+ "fill" => cstr,
+ "draw opacity" => a,
+ ),
+ "show background rectangle" => nothing,
+ )
+ end
+
+ # the combination of groupplot and polaraxis is broken in pgfplots
+ if !any( sp -> ispolar(sp), plt.subplots )
+ pl_height, pl_width = plt.attr[:size]
+ push!( the_plot, PGFPlotsX.GroupPlot(
+ PGFPlotsX.Options(
+ "group style" => PGFPlotsX.Options(
+ "group size" => string(cols)*" by "*string(rows),
+ "horizontal sep" => string(maximum(sp -> sp.minpad[1], plt.subplots)),
+ "vertical sep" => string(maximum(sp -> sp.minpad[2], plt.subplots)),
+ ),
+ "height" => pl_height > 0 ? string(pl_height * px) : "{}",
+ "width" => pl_width > 0 ? string(pl_width * px) : "{}",
+ )
+ )
+ )
+ end
+ for sp in plt.subplots
+ bb = bbox(sp)
+ sp_width = width(bb)
+ sp_height = height(bb)
+ cstr = plot_color(sp[:background_color_legend])
+ a = alpha(cstr)
+ fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
+ title_cstr = plot_color(sp[:titlefontcolor])
+ title_a = alpha(title_cstr)
+ axis_opt = PGFPlotsX.Options(
+ "title" => sp[:title],
+ "title style" => PGFPlotsX.Options(
+ "font" => pgfx_font(sp[:titlefontsize], pgfx_thickness_scaling(sp)),
+ "color" => title_cstr,
+ "draw opacity" => title_a,
+ "rotate" => sp[:titlefontrotation]
+ ),
+ "legend style" => PGFPlotsX.Options(
+ pgfx_linestyle(pgfx_thickness_scaling(sp), sp[:foreground_color_legend], fg_alpha, "solid") => nothing,
+ "fill" => cstr,
+ "fill opacity" => a,
+ "text opacity" => alpha(plot_color(sp[:legendfontcolor])),
+ "font" => pgfx_font(sp[:legendfontsize], pgfx_thickness_scaling(sp))
+ ),
+ "axis background/.style" => PGFPlotsX.Options(
+ "fill" => sp[:background_color_inside]
+ ),
+ "axis on top" => nothing,
+ )
+ sp_width > 0*mm ? push!(axis_opt, "width" => string(sp_width)) : nothing
+ sp_height > 0*mm ? push!(axis_opt, "height" => string(sp_height)) : nothing
+ # legend position
+ if sp[:legend] isa Tuple
+ x, y = sp[:legend]
+ push!(axis_opt["legend style"], "at={($x, $y)}" )
+ else
+ push!(axis_opt, "legend pos" => get(_pgfplotsx_legend_pos, sp[:legend], "outer north east"),
+ )
+ end
+ for letter in (:x, :y, :z)
+ if letter != :z || is3d(sp)
+ pgfx_axis!(axis_opt, sp, letter)
+ end
+ end
+ # Search series for any gradient. In case one series uses a gradient set
+ # the colorbar and colomap.
+ # The reasoning behind doing this on the axis level is that pgfplots
+ # colorbar seems to only works on axis level and needs the proper colormap for
+ # correctly displaying it.
+ # It's also possible to assign the colormap to the series itself but
+ # then the colormap needs to be added twice, once for the axis and once for the
+ # series.
+ # As it is likely that all series within the same axis use the same
+ # colormap this should not cause any problem.
+ for series in series_list(sp)
+ for col in (:markercolor, :fillcolor, :linecolor)
+ if typeof(series.plotattributes[col]) == ColorGradient
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot, """\\pgfplotsset{
+ colormap={plots$(sp.attr[:subplot_index])}{$(pgfx_colormap(series.plotattributes[col]))},
+ }""")
+ push!(axis_opt,
+ "colorbar" => nothing,
+ "colormap name" => "plots$(sp.attr[:subplot_index])",
+ )
+ # goto is needed to break out of col and series for
+ @goto colorbar_end
+ end
+ end
+ end
+ @label colorbar_end
+
+ push!(axis_opt, "colorbar style" => PGFPlotsX.Options(
+ "title" => sp[:colorbar_title],
+ "point meta max" => get_clims(sp)[2],
+ "point meta min" => get_clims(sp)[1]
+ )
+ )
+ if is3d(sp)
+ azim, elev = sp[:camera]
+ push!( axis_opt, "view" => (azim, elev) )
+ end
+ axisf = if sp[:projection] == :polar
+ # push!(axis_opt, "xmin" => 90)
+ # push!(axis_opt, "xmax" => 450)
+ PGFPlotsX.PolarAxis
+ else
+ PGFPlotsX.Axis
+ end
+ axis = axisf(
+ axis_opt
+ )
+ for (series_index, series) in enumerate(series_list(sp))
+ opt = series.plotattributes
+ st = series[:seriestype]
+ series_opt = PGFPlotsX.Options(
+ "color" => single_color(opt[:linecolor]),
+ )
+ if is3d(series) || st == :heatmap
+ series_func = PGFPlotsX.Plot3
+ else
+ series_func = PGFPlotsX.Plot
+ end
+ if series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
+ push!(series_opt, "area legend" => nothing)
+ end
+ if st == :heatmap
+ push!(axis.options,
+ "view" => "{0}{90}",
+ )
+ end
+ # treat segments
+ segments = if st in (:wireframe, :heatmap, :contour, :surface, :contour3d)
+ iter_segments(surface_to_vecs(series[:x], series[:y], series[:z])...)
+ else
+ iter_segments(series)
+ end
+ for (i, rng) in enumerate(segments)
+ segment_opt = PGFPlotsX.Options()
+ segment_opt = merge( segment_opt, pgfx_linestyle(opt, i) )
+ if opt[:markershape] != :none
+ marker = opt[:markershape]
+ if marker isa Shape
+ x = marker.x
+ y = marker.y
+ scale_factor = 0.025
+ mark_size = opt[:markersize] * scale_factor
+ path = join(["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], " -- ")
+ c = get_markercolor(series, i)
+ a = get_markeralpha(series, i)
+ PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
+ """
+ \\pgfdeclareplotmark{PlotsShape$(series_index)}{
+ \\filldraw
+ $path;
+ }
+ """
+ )
+ end
+ segment_opt = merge( segment_opt, pgfx_marker(opt, i) )
+ end
+ if st == :shape ||
+ isfilledcontour(series)
+ segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
+ end
+ # add fillrange
+ if series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
+ pgfx_fillrange_series!( axis, series, series_func, i, _cycle(series[:fillrange], rng), rng)
+ if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
+ pgfx_filllegend!(series_opt, opt)
+ end
+ end
+ # series
+ #
+ coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng )
+ segment_plot = series_func(
+ merge(series_opt, segment_opt),
+ coordinates,
+ )
+ push!(axis, segment_plot)
+ # add ribbons?
+ ribbon = series[:ribbon]
+ if ribbon !== nothing
+ pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
+ end
+ # add to legend?
+ if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
+ leg_opt = PGFPlotsX.Options()
+ if ribbon !== nothing
+ pgfx_filllegend!(axis.contents[end-3].options, opt)
+ end
+ legend = PGFPlotsX.LegendEntry(leg_opt, opt[:label], false)
+ push!( axis, legend )
+ end
+ # add series annotations
+ anns = series[:series_annotations]
+ for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
+ pgfx_add_annotation!(axis, xi, yi, PlotText(str, fnt), pgfx_thickness_scaling(series))
+ end
+ end
+ # add subplot annotations
+ anns = sp.attr[:annotations]
+ for (xi,yi,txt) in anns
+ pgfx_add_annotation!(axis, xi, yi, txt, pgfx_thickness_scaling(sp))
+ end
+ end
+ if ispolar(sp)
+ axes = the_plot
+ else
+ axes = the_plot.elements[1]
+ end
+ push!( axes, axis )
+ if length(plt.o.the_plot.elements) > 0
+ plt.o.the_plot.elements[1] = the_plot
+ else
+ push!(plt.o, the_plot)
+ end
+ end
+ pgfx_plot.is_created = true
+ end
+ return pgfx_plot
+end
+## seriestype specifics
+@inline function pgfx_series_coordinates!(sp, series, segment_opt, opt, rng)
+ st = series[:seriestype]
+ # function args
+ args = if st in (:contour, :contour3d)
+ opt[:x], opt[:y], Array(opt[:z])'
+ elseif st in (:heatmap, :surface, :wireframe)
+ surface_to_vecs(opt[:x], opt[:y], opt[:z])
+ elseif is3d(st)
+ opt[:x], opt[:y], opt[:z]
+ elseif st == :straightline
+ straightline_data(series)
+ elseif st == :shape
+ shape_data(series)
+ elseif ispolar(sp)
+ theta, r = opt[:x], opt[:y]
+ rad2deg.(theta), r
+ else
+ opt[:x], opt[:y]
+ end
+ seg_args = if st in (:contour, :contour3d)
+ args
+ else
+ (arg[rng] for arg in args)
+ end
+ if opt[:quiver] !== nothing
+ push!(segment_opt, "quiver" => PGFPlotsX.Options(
+ "u" => "\\thisrow{u}",
+ "v" => "\\thisrow{v}",
+ pgfx_arrow(opt[:arrow]) => nothing
+ ),
+ )
+ x, y = collect(seg_args)
+ return PGFPlotsX.Table([:x => x, :y => y, :u => opt[:quiver][1], :v => opt[:quiver][2]])
+ else
+ if isfilledcontour(series)
+ st = :filledcontour
+ end
+ pgfx_series_coordinates!(Val(st), segment_opt, opt, seg_args)
+ end
+end
+function pgfx_series_coordinates!(st_val::Union{Val{:path}, Val{:path3d}, Val{:straightline}}, segment_opt, opt, args)
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Union{Val{:scatter}, Val{:scatter3d}}, segment_opt, opt, args)
+ push!( segment_opt, "only marks" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:heatmap}, segment_opt, opt, args)
+ push!(segment_opt,
+ "matrix plot*" => nothing,
+ "mesh/rows" => length(opt[:x]),
+ "mesh/cols" => length(opt[:y]),
+ )
+ return PGFPlotsX.Table(args...)
+end
+
+function pgfx_series_coordinates!(st_val::Val{:steppre}, segment_opt, opt, args)
+ push!( segment_opt, "const plot mark right" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:stepmid}, segment_opt, opt, args)
+ push!( segment_opt, "const plot mark mid" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:steppost}, segment_opt, opt, args)
+ push!( segment_opt, "const plot" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Union{Val{:ysticks},Val{:sticks}}, segment_opt, opt, args)
+ push!( segment_opt, "ycomb" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:xsticks}, segment_opt, opt, args)
+ push!( segment_opt, "xcomb" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:surface}, segment_opt, opt, args)
+ push!( segment_opt, "surf" => nothing,
+ "mesh/rows" => length(opt[:x]),
+ "mesh/cols" => length(opt[:y]),
+ )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:volume}, segment_opt, opt, args)
+ push!( segment_opt, "patch" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:wireframe}, segment_opt, opt, args)
+ push!( segment_opt, "mesh" => nothing,
+ "mesh/rows" => length(opt[:x])
+ )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Val{:shape}, segment_opt, opt, args)
+ push!( segment_opt, "area legend" => nothing )
+ return PGFPlotsX.Coordinates(args...)
+end
+function pgfx_series_coordinates!(st_val::Union{Val{:contour}, Val{:contour3d}}, segment_opt, opt, args)
+ push!(segment_opt,
+ "contour prepared" => PGFPlotsX.Options(
+ "labels" => opt[:contour_labels],
+ ),
+ )
+ return PGFPlotsX.Table(Contour.contours(args..., opt[:levels]))
+end
+function pgfx_series_coordinates!(st_val::Val{:filledcontour}, segment_opt, opt, args)
+ xs, ys, zs = collect(args)
+ push!(segment_opt,
+ "contour filled" => PGFPlotsX.Options(
+ "labels" => opt[:contour_labels],
+ ),
+ "point meta" => "explicit",
+ "shader" => "flat"
+ )
+ if opt[:levels] isa Number
+ push!(segment_opt["contour filled"],
+ "number" => opt[:levels],
+ )
+ elseif opt[:levels] isa AVec
+ push!(segment_opt["contour filled"],
+ "levels" => opt[:levels],
+ )
+ end
+
+ cs = join([
+ join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") for (i, y) in enumerate(ys)], "\n\n"
+ )
+ """
+ coordinates {
+ $cs
+ };
+ """
+end
+##
+const _pgfplotsx_linestyles = KW(
+ :solid => "solid",
+ :dash => "dashed",
+ :dot => "dotted",
+ :dashdot => "dashdotted",
+ :dashdotdot => "dashdotdotted",
+)
+
+const _pgfplotsx_markers = KW(
+ :none => "none",
+ :cross => "+",
+ :xcross => "x",
+ :+ => "+",
+ :x => "x",
+ :utriangle => "triangle*",
+ :dtriangle => "triangle*",
+ :rtriangle => "triangle*",
+ :ltriangle => "triangle*",
+ :circle => "*",
+ :rect => "square*",
+ :star5 => "star",
+ :star6 => "asterisk",
+ :diamond => "diamond*",
+ :pentagon => "pentagon*",
+ :hline => "-",
+ :vline => "|"
+)
+
+const _pgfplotsx_legend_pos = KW(
+ :bottomleft => "south west",
+ :bottomright => "south east",
+ :topright => "north east",
+ :topleft => "north west",
+ :outertopright => "outer north east",
+)
+
+const _pgfx_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none]
+const _pgfx_framestyle_defaults = Dict(:semi => :box)
+
+# we use the anchors to define orientations for example to align left
+# one needs to use the right edge as anchor
+const _pgfx_annotation_halign = KW(
+ :center => "",
+ :left => "right",
+ :right => "left"
+)
+## --------------------------------------------------------------------------------------
+# Generates a colormap for pgfplots based on a ColorGradient
+pgfx_arrow(::Nothing) = "every arrow/.append style={-}"
+function pgfx_arrow( arr::Arrow )
+ components = String[]
+ head = String[]
+ push!(head, "{stealth[length = $(arr.headlength)pt, width = $(arr.headwidth)pt")
+ if arr.style == :open
+ push!(head, ", open")
+ end
+ push!(head, "]}")
+ head = join(head, "")
+ if arr.side == :both || arr.side == :tail
+ push!( components, head )
+ end
+ push!(components, "-")
+ if arr.side == :both || arr.side == :head
+ push!( components, head )
+ end
+ components = join( components, "" )
+ return "every arrow/.append style={$(components)}"
+end
+
+function pgfx_filllegend!( series_opt, opt )
+ io = IOBuffer()
+ PGFPlotsX.print_tex(io, pgfx_fillstyle(opt))
+ style = strip(String(take!(io)),['[',']', ' '])
+ push!( series_opt, "legend image code/.code" => """{
+ \\draw[$style] (0cm,-0.1cm) rectangle (0.6cm,0.1cm);
+ }""" )
+end
+
+function pgfx_colormap(grad::ColorGradient)
+ join(map(grad.colors) do c
+ @sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c), blue(c))
+ end,"\n")
+end
+function pgfx_colormap(grad::Vector{<:Colorant})
+ join(map(grad) do c
+ @sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c), blue(c))
+ end,"\n")
+end
+
+function pgfx_framestyle(style::Symbol)
+ if style in _pgfx_framestyles
+ return style
+ else
+ default_style = get(_pgfx_framestyle_defaults, style, :axes)
+ @warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.")
+ default_style
+ end
+end
+
+pgfx_thickness_scaling(plt::Plot) = plt[:thickness_scaling]
+pgfx_thickness_scaling(sp::Subplot) = pgfx_thickness_scaling(sp.plt)
+pgfx_thickness_scaling(series) = pgfx_thickness_scaling(series[:subplot])
+
+function pgfx_fillstyle(plotattributes, i = 1)
+ cstr = get_fillcolor(plotattributes, i)
+ a = get_fillalpha(plotattributes, i)
+ if a === nothing
+ a = alpha(single_color(cstr))
+ end
+ PGFPlotsX.Options("fill" => cstr, "fill opacity" => a)
+end
+
+function pgfx_linestyle(linewidth::Real, color, α = 1, linestyle = "solid")
+ cstr = plot_color(color, α)
+ a = alpha(cstr)
+ return PGFPlotsX.Options(
+ "color" => cstr,
+ "draw opacity" => a,
+ "line width" => linewidth,
+ get(_pgfplotsx_linestyles, linestyle, "solid") => nothing
+ )
+end
+
+function pgfx_linestyle(plotattributes, i = 1)
+ lw = pgfx_thickness_scaling(plotattributes) * get_linewidth(plotattributes, i)
+ lc = single_color(get_linecolor(plotattributes, i))
+ la = get_linealpha(plotattributes, i)
+ ls = get_linestyle(plotattributes, i)
+ return pgfx_linestyle(lw, lc, la, ls)
+end
+
+function pgfx_font(fontsize, thickness_scaling = 1, font = "\\selectfont")
+ fs = fontsize * thickness_scaling
+ return string("{\\fontsize{", fs, " pt}{", 1.3fs, " pt}", font, "}")
+end
+
+function pgfx_marker(plotattributes, i = 1)
+ shape = _cycle(plotattributes[:markershape], i)
+ cstr = plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i))
+ a = alpha(cstr)
+ cstr_stroke = plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i))
+ a_stroke = alpha(cstr_stroke)
+ mark_size = pgfx_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)
+ return PGFPlotsX.Options(
+ "mark" => shape isa Shape ? "PlotsShape$i" : get(_pgfplotsx_markers, shape, "*"),
+ "mark size" => "$mark_size pt",
+ "mark options" => PGFPlotsX.Options(
+ "color" => cstr_stroke,
+ "draw opacity" => a_stroke,
+ "fill" => cstr,
+ "fill opacity" => a,
+ "line width" => pgfx_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i),
+ "rotate" => if shape == :dtriangle
+ 180
+ elseif shape == :rtriangle
+ 270
+ elseif shape == :ltriangle
+ 90
+ else
+ 0
+ end,
+ get(_pgfplotsx_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid") => nothing
+ )
+ )
+end
+
+function pgfx_add_annotation!(o, x, y, val, thickness_scaling = 1)
+ # Construct the style string.
+ cstr = val.font.color
+ a = alpha(cstr)
+ push!(o, ["\\node",
+ PGFPlotsX.Options(
+ get(_pgfx_annotation_halign, val.font.halign, "") => nothing,
+ "color" => cstr,
+ "draw opacity" => convert(Float16, a),
+ "rotate" => val.font.rotation,
+ "font" => pgfx_font(val.font.pointsize, thickness_scaling)
+ ),
+ " at (axis cs:$x, $y) {$(val.str)};"
+ ])
+end
+
+function pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
+ ribbon_y = series[:ribbon]
+ opt = series.plotattributes
+ if ribbon_y isa AVec
+ ribbon_n = length(opt[:y]) ÷ length(ribbon_y)
+ ribbon_yp = ribbon_ym = repeat(ribbon_y, outer = ribbon_n)
+ elseif ribbon_y isa Tuple
+ ribbon_ym, ribbon_yp = ribbon_y
+ ribbon_nm = length(opt[:y]) ÷ length(ribbon_ym)
+ ribbon_ym = repeat(ribbon_ym, outer = ribbon_nm)
+ ribbon_np = length(opt[:y]) ÷ length(ribbon_yp)
+ ribbon_yp = repeat(ribbon_yp, outer = ribbon_np)
+ else
+ ribbon_yp = ribbon_ym = ribbon_y
+ end
+ # upper ribbon
+ rib_uuid = uuid4()
+ ribbon_name_plus = "plots_rib_p$rib_uuid"
+ ribbon_opt_plus = merge(segment_plot.options, PGFPlotsX.Options(
+ "name path" => ribbon_name_plus,
+ "color" => opt[:fillcolor],
+ "draw opacity" => opt[:fillalpha],
+ "forget plot" => nothing
+ ))
+ coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .+ ribbon_yp)
+ ribbon_plot_plus = series_func(
+ ribbon_opt_plus,
+ coordinates_plus
+ )
+ push!(axis, ribbon_plot_plus)
+ # lower ribbon
+ ribbon_name_minus = "plots_rib_m$rib_uuid"
+ ribbon_opt_minus = merge(segment_plot.options, PGFPlotsX.Options(
+ "name path" => ribbon_name_minus,
+ "color" => opt[:fillcolor],
+ "draw opacity" => opt[:fillalpha],
+ "forget plot" => nothing
+ ))
+ coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .- ribbon_ym)
+ ribbon_plot_plus = series_func(
+ ribbon_opt_minus,
+ coordinates_plus
+ )
+ push!(axis, ribbon_plot_plus)
+ # fill
+ push!(axis, series_func(
+ merge(pgfx_fillstyle(opt, series_index), PGFPlotsX.Options("forget plot" => nothing)),
+ "fill between [of=$(ribbon_name_plus) and $(ribbon_name_minus)]"
+ ))
+ return axis
+end
+
+function pgfx_fillrange_series!(axis, series, series_func, i, fillrange, rng)
+ fillrange_opt = PGFPlotsX.Options(
+ "line width" => "0",
+ "draw opacity" => "0",
+ )
+ fillrange_opt = merge( fillrange_opt, pgfx_fillstyle(series, i) )
+ fillrange_opt = merge( fillrange_opt, pgfx_marker(series, i) )
+ push!( fillrange_opt, "forget plot" => nothing )
+ opt = series.plotattributes
+ args = is3d(series) ? (opt[:x][rng], opt[:y][rng], opt[:z][rng]) : (opt[:x][rng], opt[:y][rng])
+ push!(axis, PGFPlotsX.PlotInc(fillrange_opt, pgfx_fillrange_args(fillrange, args...)))
+ return axis
+end
+
+function pgfx_fillrange_args(fillrange, x, y)
+ n = length(x)
+ x_fill = [x; x[n:-1:1]; x[1]]
+ y_fill = [y; _cycle(fillrange, n:-1:1); y[1]]
+ return PGFPlotsX.Coordinates(x_fill, y_fill)
+end
+
+function pgfx_fillrange_args(fillrange, x, y, z)
+ n = length(x)
+ x_fill = [x; x[n:-1:1]; x[1]]
+ y_fill = [y; y[n:-1:1]; x[1]]
+ z_fill = [z; _cycle(fillrange, n:-1:1); z[1]]
+ return PGFPlotsX.Coordiantes(x_fill, y_fill, z_fill)
+end
+# --------------------------------------------------------------------------------------
+function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
+ axis = sp[Symbol(letter,:axis)]
+
+ # turn off scaled ticks
+ push!(opt, "scaled $(letter) ticks" => "false",
+ string(letter,:label) => axis[:guide],
+ )
+
+ # set to supported framestyle
+ framestyle = pgfx_framestyle(sp[:framestyle] == false ? :none : sp[:framestyle])
+
+ # axis label position
+ labelpos = ""
+ if letter == :x && axis[:guide_position] == :top
+ labelpos = "at={(0.5,1)},above,"
+ elseif letter == :y && axis[:guide_position] == :right
+ labelpos = "at={(1,0.5)},below,"
+ end
+
+ # Add label font
+ cstr = plot_color(axis[:guidefontcolor])
+ α = alpha(cstr)
+ push!(opt, string(letter, "label style") => PGFPlotsX.Options(
+ labelpos => nothing,
+ "font" => pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)),
+ "color" => cstr,
+ "draw opacity" => α,
+ "rotate" => axis[:guidefontrotation],
+ )
+ )
+
+ # flip/reverse?
+ axis[:flip] && push!(opt, "$letter dir" => "reverse")
+
+ # scale
+ scale = axis[:scale]
+ if scale in (:log2, :ln, :log10)
+ push!(opt, string(letter,:mode) => "log")
+ scale == :ln || push!(opt, "log basis $letter" => "$(scale == :log2 ? 2 : 10)")
+ end
+
+ # ticks on or off
+ if axis[:ticks] in (nothing, false, :none) || framestyle == :none
+ push!(opt, "$(letter)majorticks" => "false")
+ end
+
+ # grid on or off
+ if axis[:grid] && framestyle != :none
+ push!(opt, "$(letter)majorgrids" => "true")
+ else
+ push!(opt, "$(letter)majorgrids" => "false")
+ end
+
+ # limits
+ lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, letter)
+ push!( opt,
+ string(letter,:min) => lims[1],
+ string(letter,:max) => lims[2]
+ )
+
+ if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none
+ 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!(opt, string(letter, "tick") => string("{", join(tick_values,","), "}"))
+ if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
+ # wrap the power part of label with }
+ tick_labels = Vector{String}(undef, length(ticks[2]))
+ for (i, label) in enumerate(ticks[2])
+ base, power = split(label, "^")
+ power = string("{", power, "}")
+ tick_labels[i] = string(base, "^", power)
+ end
+ push!(opt, string(letter, "ticklabels") => string("{\$", join(tick_labels,"\$,\$"), "\$}"))
+ elseif axis[:showaxis]
+ tick_labels = ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
+ if axis[:formatter] in (:scientific, :auto)
+ tick_labels = string.("\$", convert_sci_unicode.(tick_labels), "\$")
+ tick_labels = replace.(tick_labels, Ref("×" => "\\times"))
+ end
+ push!(opt, string(letter, "ticklabels") => string("{", join(tick_labels,","), "}"))
+ else
+ push!(opt, string(letter, "ticklabels") => "{}")
+ end
+ push!(opt, string(letter, "tick align") => (axis[:tick_direction] == :out ? "outside" : "inside"))
+ cstr = plot_color(axis[:tickfontcolor])
+ α = alpha(cstr)
+ push!(opt, string(letter, "ticklabel style") => PGFPlotsX.Options(
+ "font" => pgfx_font(axis[:tickfontsize], pgfx_thickness_scaling(sp)),
+ "color" => cstr,
+ "draw opacity" => α,
+ "rotate" => axis[:tickfontrotation]
+ )
+ )
+ push!(opt, string(letter, " grid style") => pgfx_linestyle(pgfx_thickness_scaling(sp) * axis[:gridlinewidth], axis[:foreground_color_grid], axis[:gridalpha], axis[:gridstyle])
+ )
+ end
+
+ # framestyle
+ if framestyle in (:axes, :origin)
+ axispos = framestyle == :axes ? "left" : "middle"
+ if axis[:draw_arrow]
+ push!(opt, string("axis ", letter, " line") => axispos)
+ else
+ # the * after line disables the arrow at the axis
+ push!(opt, string("axis ", letter, " line*") => axispos)
+ end
+ end
+
+ if framestyle == :zerolines
+ push!(opt, string("extra ", letter, " ticks") => "0")
+ push!(opt, string("extra ", letter, " tick labels") => "")
+ push!(opt, string("extra ", letter, " tick style") => PGFPlotsX.Options(
+ "grid" => "major",
+ "major grid style" => pgfx_linestyle(pgfx_thickness_scaling(sp), axis[:foreground_color_border], 1.0)
+ )
+ )
+ end
+
+ if !axis[:showaxis]
+ push!(opt, "separate axis lines")
+ end
+ if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
+ push!(opt, string(letter, " axis line style") => "{draw opacity = 0}")
+ else
+ push!(opt, string(letter, " axis line style") => pgfx_linestyle(pgfx_thickness_scaling(sp), axis[:foreground_color_border], 1.0)
+ )
+ end
+end
+# --------------------------------------------------------------------------------------
+# display calls this and then _display, its called 3 times for plot(1:5)
+# Set the (left, top, right, bottom) minimum padding around the plot area
+# to fit ticks, tick labels, guides, colorbars, etc.
+function _update_min_padding!(sp::Subplot{PGFPlotsXBackend})
+ # TODO: make padding more intelligent
+ # order: right, top, left, bottom
+ sp.minpad = (22mm + sp[:right_margin],
+ 12mm + sp[:top_margin],
+ 2mm + sp[:left_margin],
+ 10mm + sp[:bottom_margin])
+end
+
+function _create_backend_figure(plt::Plot{PGFPlotsXBackend})
+ plt.o = PGFPlotsXPlot()
+end
+
+function _series_added(plt::Plot{PGFPlotsXBackend}, series::Series)
+ plt.o.is_created = false
+end
+
+function _update_plot_object(plt::Plot{PGFPlotsXBackend})
+ plt.o(plt)
+end
+
+for mime in ("application/pdf", "image/png", "image/svg+xml")
+ @eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{PGFPlotsXBackend})
+ show(io, mime, plt.o.the_plot)
+ end
+end
+
+function _show(io::IO, mime::MIME{Symbol("application/x-tex")}, plt::Plot{PGFPlotsXBackend})
+ PGFPlotsX.print_tex(io, plt.o.the_plot, include_preamble = plt.attr[:tex_output_standalone])
+end
+
+function _display(plt::Plot{PGFPlotsXBackend})
+ display(PGFPlotsX.PGFPlotsXDisplay(), plt.o.the_plot)
+end
diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl
index 977d338f..e63cddba 100644
--- a/src/backends/plotly.jl
+++ b/src/backends/plotly.jl
@@ -26,7 +26,6 @@ const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js"
# end
using UUIDs
-push!(_initialized_backends, :plotly)
# ----------------------------------------------------------------
const _plotly_legend_pos = KW(
@@ -346,12 +345,12 @@ function plotly_layout(plt::Plot)
end
function plotly_layout_json(plt::Plot)
- JSON.json(plotly_layout(plt))
+ JSON.json(plotly_layout(plt), 4)
end
function plotly_colorscale(grad::ColorGradient, α)
- [[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)]
+ [[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in eachindex(grad.colors)]
end
plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α)
@@ -392,7 +391,7 @@ end
# we split by NaNs and then construct/destruct the shapes to get the closed coords
function plotly_close_shapes(x, y)
xs, ys = nansplit(x), nansplit(y)
- for i=1:length(xs)
+ for i=eachindex(xs)
shape = Shape(xs[i], ys[i])
xs[i], ys[i] = coords(shape)
end
@@ -402,7 +401,7 @@ end
function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)]
- data = if axis[:ticks] == :native && data != nothing
+ data = if axis[:ticks] == :native && data !== nothing
plotly_native_data(axis, data)
else
data
@@ -414,7 +413,8 @@ function plotly_data(series::Series, letter::Symbol, data)
plotly_data(data)
end
end
-plotly_data(v) = v != nothing ? collect(v) : v
+plotly_data(v) = v !== nothing ? collect(v) : v
+plotly_data(v::AbstractArray) = v
plotly_data(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
@@ -453,7 +453,7 @@ function plotly_series(plt::Plot, series::Series)
st = series[:seriestype]
sp = series[:subplot]
- clims = get_clims(sp)
+ clims = get_clims(sp, series)
if st == :shape
return plotly_series_shapes(plt, series, clims)
@@ -468,7 +468,7 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showlegend] = should_add_to_legend(series)
if st == :straightline
- x, y = straightline_data(series)
+ x, y = straightline_data(series, 100)
z = series[:z]
else
x, y, z = series[:x], series[:y], series[:z]
@@ -528,7 +528,7 @@ function plotly_series(plt::Plot, series::Series)
else
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = series[:fillalpha]
- if series[:fill_z] != nothing
+ if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
plotattributes_out[:showscale] = hascolorbar(sp)
@@ -583,7 +583,7 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
)
x, y = (plotly_data(series, letter, data)
- for (letter, data) in zip((:x, :y), shape_data(series))
+ for (letter, data) in zip((:x, :y), shape_data(series, 100))
)
for (i,rng) in enumerate(segments)
@@ -610,11 +610,11 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[i] = plotattributes_out
end
- if series[:fill_z] != nothing
+ if series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
- elseif series[:line_z] != nothing
+ elseif series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
- elseif series[:marker_z] != nothing
+ elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
plotattributes_outs
@@ -630,11 +630,9 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series)
- plotattributes_outs = Vector{KW}(undef, (hasfillrange ? 2 : 1 ) * length(segments))
+ plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
for (i,rng) in enumerate(segments)
- !isscatter && length(rng) < 2 && continue
-
plotattributes_out = deepcopy(plotattributes_base)
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotattributes_out[:legendgroup] = series[:label]
@@ -734,11 +732,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
end
end
- if series[:line_z] != nothing
+ if series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
- elseif series[:fill_z] != nothing
+ elseif series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
- elseif series[:marker_z] != nothing
+ elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
@@ -783,7 +781,7 @@ function plotly_hover!(plotattributes_out::KW, hover)
# hover text
if hover in (:none, false)
plotattributes_out[:hoverinfo] = "none"
- elseif hover != nothing
+ elseif hover !== nothing
plotattributes_out[:hoverinfo] = "text"
plotattributes_out[:text] = hover
end
@@ -799,13 +797,16 @@ function plotly_series(plt::Plot)
end
# get json string for a list of dictionaries, each representing the series params
-plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt))
+plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt), 4)
# ----------------------------------------------------------------
+html_head(plt::Plot{PlotlyBackend}) = plotly_html_head(plt)
+html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
+
const ijulia_initialized = Ref(false)
-function html_head(plt::Plot{PlotlyBackend})
+function plotly_html_head(plt::Plot)
local_file = ("file://" * plotly_local_file_path)
plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path
if isijulia() && !ijulia_initialized[]
@@ -821,12 +822,10 @@ function html_head(plt::Plot{PlotlyBackend})
""")
ijulia_initialized[] = true
end
- # IJulia just needs one initialization
- isijulia() && return ""
return ""
end
-function html_body(plt::Plot{PlotlyBackend}, style = nothing)
+function plotly_html_body(plt, style = nothing)
if style == nothing
style = "width:100%;height:100%;"
end
@@ -839,7 +838,7 @@ function html_body(plt::Plot{PlotlyBackend}, style = nothing)
"""
end
-function js_body(plt::Plot{PlotlyBackend}, divid)
+function js_body(plt::Plot, divid)
"""
gd = (function() {
var WIDTH_IN_PERCENT_OF_PARENT = 100;
@@ -866,7 +865,7 @@ end
# ----------------------------------------------------------------
-function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
+function plotly_show_js(io::IO, plot::Plot)
data = []
for series in plot.series_list
append!(data, plotly_series(plot, series))
@@ -875,7 +874,19 @@ function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{Plotly
JSON.print(io, Dict(:data => data, :layout => layout))
end
+# ----------------------------------------------------------------
+
+function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
+ plotly_show_js(io, plot)
+end
+
+
+function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
+ write(io, standalone_html(plt))
+end
+
function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt)
end
+
diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl
index 83952c71..5893ece3 100644
--- a/src/backends/plotlyjs.jl
+++ b/src/backends/plotlyjs.jl
@@ -1,78 +1,44 @@
# https://github.com/sglyon/PlotlyJS.jl
-# --------------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
-
-function _create_backend_figure(plt::Plot{PlotlyJSBackend})
- if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
- PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options)
- else
- PlotlyJS.plot()
+function plotlyjs_syncplot(plt::Plot{PlotlyJSBackend})
+ plt[:overwrite_figure] && closeall()
+ plt.o = PlotlyJS.plot()
+ traces = PlotlyJS.GenericTrace[]
+ for series_dict in plotly_series(plt)
+ plotly_type = pop!(series_dict, :type)
+ push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...))
end
+ PlotlyJS.addtraces!(plt.o, traces...)
+ layout = plotly_layout(plt)
+ w, h = plt[:size]
+ PlotlyJS.relayout!(plt.o, layout, width = w, height = h)
+ return plt.o
end
+# ------------------------------------------------------------------------------
-function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
- syncplot = plt.o
- pdicts = plotly_series(plt, series)
- for pdict in pdicts
- typ = pop!(pdict, :type)
- gt = PlotlyJS.GenericTrace(typ; pdict...)
- PlotlyJS.addtraces!(syncplot, gt)
- end
+const _plotlyjs_mimeformats = Dict(
+ "application/pdf" => "pdf",
+ "image/png" => "png",
+ "image/svg+xml" => "svg",
+ "image/eps" => "eps",
+)
+
+for (mime, fmt) in _plotlyjs_mimeformats
+ @eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
end
-function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
- xsym, ysym = (ispolar(series) ? (:t,:r) : (:x,:y))
- kw = KW(xsym => (series.plotattributes[:x],), ysym => (series.plotattributes[:y],))
- z = series[:z]
- if z != nothing
- kw[:z] = (isa(z,Surface) ? transpose_z(series, series[:z].surf, false) : z,)
- end
- PlotlyJS.restyle!(
- plt.o,
- findfirst(isequal(series), plt.series_list),
- kw
- )
-end
+# Use the Plotly implementation for json and html:
+_show(io::IO, mime::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) = plotly_show_js(io, plt)
+html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt)
+html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt)
-# ----------------------------------------------------------------
+_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, standalone_html(plt))
-function _update_plot_object(plt::Plot{PlotlyJSBackend})
- pdict = plotly_layout(plt)
- syncplot = plt.o
- w,h = plt[:size]
- PlotlyJS.relayout!(syncplot, pdict, width = w, height = h)
-end
-
-
-# ----------------------------------------------------------------
-
-_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 _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)
- filename
-end
-
-function _display(plt::Plot{PlotlyJSBackend})
- if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
- display(plt.o)
- else
- standalone_html_window(plt)
- end
-end
+_display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt))
@require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin
function WebIO.render(plt::Plot{PlotlyJSBackend})
diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl
index eec1e6ca..19137b13 100644
--- a/src/backends/pyplot.jl
+++ b/src/backends/pyplot.jl
@@ -187,7 +187,7 @@ end
# end
function get_locator_and_formatter(vals::AVec)
- pyticker."FixedLocator"(1:length(vals)), pyticker."FixedFormatter"(vals)
+ pyticker."FixedLocator"(eachindex(vals)), pyticker."FixedFormatter"(vals)
end
function add_pyfixedformatter(cbar, vals::AVec)
@@ -216,7 +216,7 @@ end
# ---------------------------------------------------------------------------
function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
- if series[:x] != nothing
+ 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
@@ -399,7 +399,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# handle zcolor and get c/cmap
needs_colorbar = hascolorbar(sp)
- vmin, vmax = clims = get_clims(sp)
+ vmin, vmax = clims = get_clims(sp, series)
# Dict to store extra kwargs
if st == :wireframe
@@ -434,7 +434,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if maximum(series[:linewidth]) > 0
segments = iter_segments(series)
# TODO: check LineCollection alternative for speed
- # if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] != nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
+ # if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] !== nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
# # multicolored line segments
# n = length(segments)
# # segments = Array(Any,n)
@@ -478,7 +478,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# end
a = series[:arrow]
- if a != nothing && !is3d(st) # TODO: handle 3d later
+ if a !== nothing && !is3d(st) # TODO: handle 3d later
if typeof(a) != Arrow
@warn("Unexpected type for arrow: $(typeof(a))")
else
@@ -508,7 +508,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:markershape] != :none && st in (:path, :scatter, :path3d,
:scatter3d, :steppre, :steppost,
:bar)
- markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] != nothing
+ markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] !== nothing
# py_color(plot_color.(get_markercolor.(series, clims, eachindex(x)), get_markeralpha.(series, eachindex(x))))
[py_color(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) for i in eachindex(x)]
else
@@ -535,7 +535,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
shapes = series[:markershape]
msc = py_markerstrokecolor(series)
lw = py_thickness_scale(plt, series[:markerstrokewidth])
- for i=1:length(y)
+ for i=eachindex(y)
extrakw[:c] = _cycle(markercolor, i)
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
@@ -564,7 +564,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
delete!(extrakw, :c)
- for i=1:length(y)
+ for i=eachindex(y)
cur_marker = py_marker(_cycle(shapes,i))
if ( cur_marker == prev_marker )
@@ -672,7 +672,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
# contour fills
- if series[:fillrange] != nothing
+ if series[:fillrange] !== nothing
handle = ax."contourf"(x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
@@ -691,7 +691,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
z = transpose_z(series, z)
if st == :surface
- if series[:fill_z] != nothing
+ if series[:fill_z] !== nothing
# the surface colors are different than z-value
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
extrakw[:shade] = false
@@ -756,7 +756,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
cmap = py_colormap(cgrad([:black, :white])),
vmin = 0.0,
vmax = 1.0,
- extent = (xmin, xmax, ymax, ymin)
+ extent = (xmin-0.5, xmax+0.5, ymax+0.5, ymin-0.5)
)
push!(handles, handle)
@@ -830,7 +830,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# handle area filling
fillrange = series[:fillrange]
- if fillrange != nothing && st != :contour
+ if fillrange !== nothing && st != :contour
for (i, rng) in enumerate(iter_segments(series))
f, dim1, dim2 = if isvertical(series)
:fill_between, x[rng], y[rng]
@@ -871,7 +871,7 @@ end
function py_set_ticks(ax, ticks, letter)
ticks == :auto && return
axis = getproperty(ax, Symbol(letter,"axis"))
- if ticks == :none || ticks == nothing || ticks == false
+ if ticks == :none || ticks === nothing || ticks == false
kw = KW()
for dir in (:top,:bottom,:left,:right)
kw[dir] = kw[Symbol(:label,dir)] = false
@@ -927,7 +927,7 @@ function py_set_scale(ax, sp::Subplot, axis::Axis)
elseif scale == :log10
10
end
- kw[Symbol(:linthresh,letter)] = NaNMath.min(1e-16, py_compute_axis_minval(sp, axis))
+ kw[Symbol(:linthresh,letter)] = NaNMath.max(1e-16, py_compute_axis_minval(sp, axis))
"symlog"
end
func(arg; kw...)
@@ -978,7 +978,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update subplots
for sp in plt.subplots
ax = sp.o
- if ax == nothing
+ if ax === nothing
continue
end
@@ -1013,17 +1013,17 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw = KW()
if !isempty(sp[:zaxis][:discrete_values]) && colorbar_series[:seriestype] == :heatmap
locator, formatter = get_locator_and_formatter(sp[:zaxis][:discrete_values])
- # kw[:values] = 1:length(sp[:zaxis][:discrete_values])
+ # kw[:values] = eachindex(sp[:zaxis][:discrete_values])
kw[:values] = sp[:zaxis][:continuous_values]
kw[:ticks] = locator
kw[:format] = formatter
kw[:boundaries] = vcat(0, kw[:values] + 0.5)
- elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z))
+ 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)
- f = if colorbar_series[:line_z] != nothing
+ f = if colorbar_series[:line_z] !== nothing
py_linecolormap
- elseif colorbar_series[:fill_z] != nothing
+ elseif colorbar_series[:fill_z] !== nothing
py_fillcolormap
else
py_markercolormap
@@ -1186,7 +1186,7 @@ end
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PyPlotBackend})
ax = sp.o
- ax == nothing && return sp.minpad
+ ax === nothing && return sp.minpad
plotbb = py_bbox(ax)
# TODO: this should initialize to the margin from sp.attr
@@ -1228,7 +1228,7 @@ 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, annotation_clip = false)
end
@@ -1242,7 +1242,8 @@ function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
rotation = val.font.rotation,
size = py_thickness_scale(sp.plt, val.font.pointsize),
- zorder = 999
+ zorder = 999,
+ annotation_clip = false
)
end
@@ -1289,15 +1290,15 @@ py_legend_bbox(pos) = pos
function py_add_legend(plt::Plot, sp::Subplot, ax)
leg = sp[:legend]
- clims = get_clims(sp)
if leg != :none
# gotta do this to ensure both axes are included
labels = []
handles = []
for series in series_list(sp)
if should_add_to_legend(series)
+ clims = get_clims(sp, series)
# add a line/marker and a label
- push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
+ push!(handles, if series[:seriestype] == :shape || series[:fillrange] !== nothing
pypatches."Patch"(
edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
facecolor = py_color(single_color(get_fillcolor(series, clims)), get_fillalpha(series)),
@@ -1335,10 +1336,13 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
frame = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000)
- sp[:legendtitle] != nothing && leg."set_title"(sp[:legendtitle])
+ if sp[:legendtitle] !== nothing
+ leg."set_title"(sp[:legendtitle])
+ PyPlot.plt."setp"(leg."get_title"(), color = py_color(sp[:legendtitlefontcolor]), family = sp[:legendtitlefontfamily], fontsize = py_thickness_scale(plt, sp[:legendtitlefontsize]))
+ end
for txt in leg."get_texts"()
- PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
+ PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily], fontsize = py_thickness_scale(plt, sp[:legendfontsize]))
end
end
end
@@ -1352,7 +1356,7 @@ end
function _update_plot_object(plt::Plot{PyPlotBackend})
for sp in plt.subplots
ax = sp.o
- ax == nothing && return
+ ax === nothing && return
figw, figh = sp.plt[:size]
figw, figh = figw*px, figh*px
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
diff --git a/src/components.jl b/src/components.jl
index 097aee19..de10f663 100644
--- a/src/components.jl
+++ b/src/components.jl
@@ -187,7 +187,7 @@ end
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = coords(shape)
cx, cy = c
- for i=1:length(sx)
+ for i=eachindex(sx)
sx[i] = (sx[i] - cx) * x + cx
sy[i] = (sy[i] - cy) * y + cy
end
@@ -202,7 +202,7 @@ end
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape)
- for i=1:length(sx)
+ for i=eachindex(sx)
sx[i] += x
sy[i] += y
end
@@ -230,7 +230,7 @@ end
function rotate!(shape::Shape, Θ::Real, c = center(shape))
x, y = coords(shape)
cx, cy = c
- for i=1:length(x)
+ for i=eachindex(x)
xi = rotate_x(x[i], y[i], Θ, cx, cy)
yi = rotate_y(x[i], y[i], Θ, cx, cy)
x[i], y[i] = xi, yi
@@ -529,7 +529,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# end
# @show msw msh
- if anns != nothing && anns.baseshape != nothing
+ 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
@@ -568,7 +568,7 @@ mutable struct EachAnn
end
function Base.iterate(ea::EachAnn, i = 1)
- if ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
+ if ea.anns === nothing || isempty(ea.anns.strs) || i > length(ea.y)
return nothing
end
@@ -794,7 +794,7 @@ end
@deprecate curve_points coords
-coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50))
+coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, Base.range(range..., length=n))
# build a BezierCurve which leaves point p vertically upwards and arrives point q vertically upwards.
# may create a loop if necessary. Assumes the view is [0,1]
diff --git a/src/examples.jl b/src/examples.jl
index 6dd1b7f4..c0ac5a38 100644
--- a/src/examples.jl
+++ b/src/examples.jl
@@ -165,7 +165,7 @@ PlotExample("Marker types",
),
PlotExample("Bar",
- "x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
+ "`x` is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[:(begin
bar(randn(99))
end)]
@@ -238,12 +238,12 @@ build with the method `text(string, attr...)`, which wraps font and color attrib
""",
[:(begin
y = rand(10)
-plot(y, annotations = (3,y[3],text("this is #3",:left)), leg=false)
-annotate!([(5, y[5], text("this is #5",16,:red,:center)),
- (10, y[10], text("this is #10",:right,20,"courier"))])
+plot(y, annotations = (3,y[3], Plots.text("this is #3",:left)), leg=false)
+annotate!([(5, y[5], Plots.text("this is #5",16,:red,:center)),
+ (10, y[10], Plots.text("this is #10",:right,20,"courier"))])
scatter!(range(2, stop=8, length=6), rand(6), marker=(50,0.2,:orange),
series_annotations = ["series","annotations","map","to","series",
- text("data",:green)])
+ Plots.text("data",:green)])
end)]
),
@@ -305,7 +305,8 @@ PlotExample("3D",
PlotExample("DataFrames",
"Plot using DataFrame column symbols.",
- [:(begin
+ [:(using StatsPlots), # can't be inside begin block because @df gets expanded first
+ :(begin
import RDatasets
iris = RDatasets.dataset("datasets", "iris")
@df iris scatter(:SepalLength, :SepalWidth, group=:Species,
@@ -354,7 +355,8 @@ PlotExample("Layouts, margins, label rotation, title location",
PlotExample("Boxplot and Violin series recipes",
"",
- [:(begin
+ [:(using StatsPlots), # can't be inside begin block because @df gets expanded first
+ :(begin
import RDatasets
singers = RDatasets.dataset("lattice", "singer")
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue))
@@ -454,6 +456,49 @@ see: http://stackoverflow.com/a/37732384/5075246
end)]
),
+PlotExample("Ribbons",
+ """
+ Ribbons can be added to lines via the `ribbon` keyword;
+ you can pass a tuple of arrays (upper and lower bounds),
+ a single Array (for symmetric ribbons), a Function, or a number.
+ """,
+ [:(begin
+ plot(
+ plot(0:10; ribbon = (LinRange(0, 2, 10), LinRange(0, 1, 10))),
+ plot(0:10; ribbon = 0:0.5:5),
+ plot(0:10; ribbon = sqrt),
+ plot(0:10; ribbon = 1),
+ )
+ end)]
+),
+
+PlotExample("Histogram2D (complex values)",
+ "",
+ [:(begin
+ n = 10_000
+ x = exp.(0.1randn(n) .+ randn(n).*(im))
+ histogram2d(x, nbins=(20,40), show_empty_bins=true,
+ normed=true, aspect_ratio=1)
+ end)]
+),
+
+PlotExample("Unconnected lines using `missing` or `NaN`",
+"""
+Missing values and non-finite values, including `NaN`, are not plotted.
+Instead, lines are separated into segments at these values.
+""",
+ [:(begin
+ x,y = [1,2,2,1,1], [1,2,1,2,1]
+ plot(
+ plot([rand(5); NaN; rand(5); NaN; rand(5)]),
+ plot([1,missing,2,3], marker=true),
+ plot([x; NaN; x.+2], [y; NaN; y.+1], arrow=2),
+ plot([1, 2+3im, Inf, 4im, 3, -Inf*im, 0, 3+3im], marker=true),
+ legend=false
+ )
+ end)]
+),
+
]
# Some constants for PlotDocs and PlotReferenceImages
@@ -461,7 +506,7 @@ _animation_examples = [2, 30]
_backend_skips = Dict(
:gr => [25, 30],
:pyplot => [25, 30],
- :plotlyjs => [2, 21, 25, 30, 31],
+ :plotlyjs => [2, 21, 24, 25, 30, 31],
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30],
)
@@ -475,7 +520,12 @@ function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
@info("Testing plot: $pkgname:$idx:$(_examples[idx].header)")
backend(pkgname)
backend()
- map(eval, _examples[idx].exprs)
+
+ # prevent leaking variables (esp. functions) directly into Plots namespace
+ m = Module(:PlotExampleModule)
+ Base.eval(m, :(using Plots))
+ map(exprs -> Base.eval(m, exprs), _examples[idx].exprs)
+
plt = current()
if disp
gui(plt)
@@ -495,8 +545,8 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
skip = [], only = nothing)
Plots._debugMode.on = debug
plts = Dict()
- for i in 1:length(_examples)
- only != nothing && !(i in only) && continue
+ for i in eachindex(_examples)
+ only !== nothing && !(i in only) && continue
i in skip && continue
try
plt = test_examples(pkgname, i, debug=debug, disp=disp)
@@ -505,7 +555,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
# TODO: put error info into markdown?
@warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
end
- if sleep != nothing
+ if sleep !== nothing
Base.sleep(sleep)
end
end
diff --git a/src/ijulia.jl b/src/ijulia.jl
index a54c0ca9..1f0ef219 100644
--- a/src/ijulia.jl
+++ b/src/ijulia.jl
@@ -20,7 +20,10 @@ 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["application/vnd.plotly.v1+json"] = Dict(
+ :data => plotly_series(plt),
+ :layout => plotly_layout(plt)
+ )
out
end
diff --git a/src/init.jl b/src/init.jl
index bffc99f2..c6213001 100644
--- a/src/init.jl
+++ b/src/init.jl
@@ -28,12 +28,53 @@ function __init__()
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"))
- @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"))
- @require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" include(joinpath(@__DIR__, "backends", "plotlyjs.jl"))
- @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"))
+ @require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin
+ fn = joinpath(@__DIR__, "backends", "hdf5.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" begin
+ fn = joinpath(@__DIR__, "backends", "inspectdr.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" begin
+ fn = joinpath(@__DIR__, "backends", "pgfplots.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require ORCA = "47be7bcc-f1a6-5447-8b36-7eeeff7534fd" begin
+ fn = joinpath(@__DIR__, "backends", "orca.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925" begin
+ fn = joinpath(@__DIR__, "backends", "pgfplotsx.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" begin
+ fn = joinpath(@__DIR__, "backends", "plotlyjs.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" begin
+ fn = joinpath(@__DIR__, "backends", "pyplot.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
+
+ @require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" begin
+ fn = joinpath(@__DIR__, "backends", "unicodeplots.jl")
+ include(fn)
+ @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
+ end
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited
diff --git a/src/layouts.jl b/src/layouts.jl
index 83ae259d..1bc5367b 100644
--- a/src/layouts.jl
+++ b/src/layouts.jl
@@ -107,7 +107,6 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
if mix.len != 0mm
f = (letter == :x ? width : height)
totlen = f(plotarea(sp))
- @show totlen
pct += mix.len / totlen
end
if pct != 0
@@ -218,6 +217,7 @@ bottompad(layout::AbstractLayout) = 0mm
# this is the parent of the top-level layout
struct RootLayout <: AbstractLayout end
+Base.show(io::IO, layout::RootLayout) = Base.show_default(io, layout)
Base.parent(::RootLayout) = nothing
parent_bbox(::RootLayout) = defaultbox
bbox(::RootLayout) = defaultbox
@@ -469,7 +469,7 @@ function layout_args(plotattributes::KW)
end
function layout_args(plotattributes::KW, n_override::Integer)
- layout, n = layout_args(get(plotattributes, :layout, n_override))
+ layout, n = layout_args(n_override, get(plotattributes, :layout, n_override))
if n != n_override
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end
@@ -481,12 +481,27 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n
end
-function layout_args(sztup::NTuple{2,I}) where I<:Integer
+function layout_args(sztup::NTuple{2, Integer})
nr, nc = sztup
GridLayout(nr, nc), nr*nc
end
-function layout_args(sztup::NTuple{3,I}) where I<:Integer
+layout_args(n_override::Integer, n::Integer) = layout_args(n)
+layout_args(n, sztup::NTuple{2, Integer}) = layout_args(sztup)
+
+function layout_args(n, sztup::Tuple{Colon, Integer})
+ nc = sztup[2]
+ nr = ceil(Int, n / nc)
+ GridLayout(nr, nc), n
+end
+
+function layout_args(n, sztup::Tuple{Integer, Colon})
+ nr = sztup[1]
+ nc = ceil(Int, n / nr)
+ GridLayout(nr, nc), n
+end
+
+function layout_args(sztup::NTuple{3, Integer})
n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n
@@ -499,6 +514,8 @@ function layout_args(layout::GridLayout)
layout, n
end
+layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
+
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
diff --git a/src/output.jl b/src/output.jl
index 95a9c158..ac29815c 100644
--- a/src/output.jl
+++ b/src/output.jl
@@ -72,6 +72,7 @@ const _savemap = Dict(
"eps" => eps,
"tex" => tex,
"html" => html,
+ "tikz" => tex,
)
function getExtension(fn::AbstractString)
@@ -103,7 +104,7 @@ type is inferred from the file extension. All backends support png and pdf
file types, some also support svg, ps, eps, html and tex.
"""
function savefig(plt::Plot, fn::AbstractString)
-
+ fn = abspath(expanduser(fn))
# get the extension
local ext
try
@@ -201,6 +202,8 @@ for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml
end
end
+Base.show(io::IO, m::MIME"application/prs.juno.plotpane+html", plt::Plot) = showjuno(io, MIME("text/html"), plt)
+
# default text/plain for all backends
_show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt)
@@ -229,15 +232,16 @@ closeall() = closeall(backend())
# Atom PlotPane
# ---------------------------------------------------------
function showjuno(io::IO, m, plt)
- sz = plt[:size]
+ sz = collect(plt[:size])
dpi = plt[:dpi]
thickness_scaling = plt[:thickness_scaling]
jsize = get(io, :juno_plotsize, [400, 500])
+ jratio = get(io, :juno_dpi_ratio, 1)
scale = minimum(jsize[i] / sz[i] for i in 1:2)
- plt[:size] = (s * scale for s in sz)
- plt[:dpi] = Plots.DPI
+ plt[:size] = [s * scale for s in sz]
+ plt[:dpi] = jratio*Plots.DPI
plt[:thickness_scaling] *= scale
prepare_output(plt)
@@ -258,4 +262,6 @@ function _showjuno(io::IO, m::MIME"image/svg+xml", plt)
end
end
+Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot) = showable(MIME"text/html"(), plt)
+
_showjuno(io::IO, m, plt) = _show(io, m, plt)
diff --git a/src/pipeline.jl b/src/pipeline.jl
index 433997c2..4966b7f8 100644
--- a/src/pipeline.jl
+++ b/src/pipeline.jl
@@ -12,7 +12,7 @@ function _expand_seriestype_array(plotattributes::KW, args)
if typeof(sts) <: AbstractArray
delete!(plotattributes, :seriestype)
rd = Vector{RecipeData}(undef, size(sts, 1))
- for r in 1:size(sts, 1)
+ for r in axes(sts, 1)
dc = copy(plotattributes)
dc[:seriestype] = sts[r:r,:]
rd[r] = RecipeData(dc, args)
@@ -126,7 +126,7 @@ function _preprocess_userrecipe(kw::KW)
end
# convert a ribbon into a fillrange
- if get(kw, :ribbon, nothing) != nothing
+ if get(kw, :ribbon, nothing) !== nothing
make_fillrange_from_ribbon(kw)
end
return
@@ -136,7 +136,7 @@ function _add_errorbar_kw(kw_list::Vector{KW}, kw::KW)
# handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror)
- if get(kw, esym, nothing) != nothing
+ if get(kw, esym, nothing) !== nothing
# we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw)
errkw[:seriestype] = esym
@@ -227,7 +227,7 @@ function _plot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# handle inset subplots
insets = plt[:inset_subplots]
- if insets != nothing
+ if insets !== nothing
if !(typeof(insets) <: AVec)
insets = [insets]
end
diff --git a/src/plot.jl b/src/plot.jl
index 2c2ecd48..4352403a 100644
--- a/src/plot.jl
+++ b/src/plot.jl
@@ -4,7 +4,7 @@ mutable struct CurrentPlot
end
const CURRENT_PLOT = CurrentPlot(nothing)
-isplotnull() = CURRENT_PLOT.nullableplot == nothing
+isplotnull() = CURRENT_PLOT.nullableplot === nothing
"""
current()
diff --git a/src/precompile.jl b/src/precompile.jl
index 22c11ca0..a171ac36 100644
--- a/src/precompile.jl
+++ b/src/precompile.jl
@@ -1,3 +1,873 @@
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
+ isdefined(Plots, Symbol("#@layout")) && precompile(Tuple{getfield(Plots, Symbol("#@layout")), LineNumberNode, Module, Expr})
+ isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Array{Int64, 1}}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}}, Symbol})
+ isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Int64})
+ isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Tuple{Int64, Int64}})
+ isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}}, Symbol})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:flip,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:foreground_color_grid, :grid, :gridalpha, :gridstyle, :gridlinewidth), Tuple{ColorTypes.RGBA{Float64}, Bool, Float64, Symbol, Int64}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:formatter,), Tuple{Symbol}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :lims), Tuple{Bool, Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :lims, :flip), Tuple{Bool, Tuple{Int64, Int64}, Bool}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :ticks), Tuple{Bool, Nothing}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:guide,), Tuple{String}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims, :flip, :ticks, :guide), Tuple{Tuple{Int64, Int64}, Bool, Base.StepRange{Int64, Int64}, String}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Float64}}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:rotation,), Tuple{Int64}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:scale, :guide), Tuple{Symbol, String}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:ticks,), Tuple{Base.UnitRange{Int64}}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:ticks,), Tuple{Nothing}}, typeof(Plots.attr!), Plots.Axis})
+ isdefined(Plots, Symbol("#kw##contour")) && precompile(Tuple{getfield(Plots, Symbol("#kw##contour")), NamedTuple{(:fill,), Tuple{Bool}}, typeof(Plots.contour), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int})
+ isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Array{Float64, 1}, Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Array{Int64, 1}, Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Base.UnitRange{Int64}, Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##gr_set_font")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_set_font")), NamedTuple{(:halign, :valign, :rotation), Tuple{Symbol, Symbol, Int64}}, typeof(Plots.gr_set_font), Plots.Font})
+ isdefined(Plots, Symbol("#kw##gr_set_font")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_set_font")), NamedTuple{(:halign, :valign, :rotation), Tuple{Symbol, Symbol, Int64}}, typeof(Plots.gr_set_font), Plots.Font})
+ isdefined(Plots, Symbol("#kw##heatmap")) && precompile(Tuple{getfield(Plots, Symbol("#kw##heatmap")), NamedTuple{(:aspect_ratio,), Tuple{Int64}}, typeof(Plots.heatmap), Array{String, 1}, Int})
+ isdefined(Plots, Symbol("#kw##histogram")) && precompile(Tuple{getfield(Plots, Symbol("#kw##histogram")), NamedTuple{(:bins, :weights), Tuple{Symbol, Array{Int64, 1}}}, typeof(Plots.histogram), Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##histogram2d")) && precompile(Tuple{getfield(Plots, Symbol("#kw##histogram2d")), NamedTuple{(:nbins, :show_empty_bins, :normed, :aspect_ratio), Tuple{Tuple{Int64, Int64}, Bool, Bool, Int64}}, typeof(Plots.histogram2d), Array{Base.Complex{Float64}, 1}})
+ isdefined(Plots, Symbol("#kw##histogram2d")) && precompile(Tuple{getfield(Plots, Symbol("#kw##histogram2d")), NamedTuple{(:nbins,), Tuple{Int64}}, typeof(Plots.histogram2d), Array{Float64, 1}, Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##hline!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##hline!")), NamedTuple{(:line,), Tuple{Tuple{Int64, Symbol, Float64, Array{Symbol, 2}}}}, typeof(Plots.hline!), Array{Float64, 2}})
+ isdefined(Plots, Symbol("#kw##pie")) && precompile(Tuple{getfield(Plots, Symbol("#kw##pie")), NamedTuple{(:title, :l), Tuple{String, Float64}}, typeof(Plots.pie), Array{String, 1}, Int})
+ isdefined(Plots, Symbol("#kw##portfoliocomposition")) && precompile(Tuple{getfield(Plots, Symbol("#kw##portfoliocomposition")), NamedTuple{(:labels,), Tuple{Array{String, 2}}}, typeof(Plots.portfoliocomposition), Array{Float64, 2}, Int})
+ isdefined(Plots, Symbol("#kw##scatter!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##scatter!")), NamedTuple{(:marker, :series_annotations), Tuple{Tuple{Int64, Float64, Symbol}, Array{Any, 1}}}, typeof(Plots.scatter!), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int})
+ isdefined(Plots, Symbol("#kw##scatter!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##scatter!")), NamedTuple{(:markersize, :c), Tuple{Int64, Symbol}}, typeof(Plots.scatter!), Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##scatter!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##scatter!")), NamedTuple{(:zcolor, :m, :ms, :lab), Tuple{Array{Float64, 1}, Tuple{Symbol, Float64, Plots.Stroke}, Array{Float64, 1}, String}}, typeof(Plots.scatter!), Array{Float64, 1}})
+ isdefined(Plots, Symbol("#kw##scatter")) && precompile(Tuple{getfield(Plots, Symbol("#kw##scatter")), NamedTuple{(:framestyle, :title, :color, :layout, :label, :markerstrokewidth, :ticks), Tuple{Array{Symbol, 2}, Array{String, 2}, Base.ReshapedArray{Int64, 2, Base.UnitRange{Int64}, Tuple{}}, Int64, String, Int64, Base.UnitRange{Int64}}}, typeof(Plots.scatter), Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}})
+ isdefined(Plots, Symbol("#kw##scatter")) && precompile(Tuple{getfield(Plots, Symbol("#kw##scatter")), NamedTuple{(:m, :lab, :bg, :xlim, :ylim), Tuple{Tuple{Int64, Symbol}, Array{String, 2}, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}}}, typeof(Plots.scatter), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int})
+ isdefined(Plots, Symbol("#kw##test_examples")) && precompile(Tuple{getfield(Plots, Symbol("#kw##test_examples")), NamedTuple{(:disp,), Tuple{Bool}}, typeof(Plots.test_examples), Symbol})
+ precompile(Tuple{typeof(Plots.__init__)})
+ precompile(Tuple{typeof(Plots._add_defaults!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Int64})
+ precompile(Tuple{typeof(Plots._add_defaults!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Int64})
+ precompile(Tuple{typeof(Plots._add_errorbar_kw), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_errorbar_kw), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_markershape), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_markershape), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_smooth_kw), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_smooth_kw), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_the_series), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._add_the_series), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{Array{Float64, 1}, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{Array{T, 1} where T, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{Function, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{Function, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{String, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, Array{Union{Base.Missing, Int64}, 1}})
+ precompile(Tuple{typeof(Plots._apply_type_recipe), Base.Dict{Symbol, Any}, typeof(identity)})
+ precompile(Tuple{typeof(Plots._backend_instance), Symbol})
+ precompile(Tuple{typeof(Plots._backend_instance), Symbol})
+ precompile(Tuple{typeof(Plots._bin_centers), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots._binbarlike_baseline), Float64, Symbol})
+ precompile(Tuple{typeof(Plots._cbar_unique), Array{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, 1}, String})
+ precompile(Tuple{typeof(Plots._cbar_unique), Array{Int64, 1}, String})
+ precompile(Tuple{typeof(Plots._cbar_unique), Array{Nothing, 1}, String})
+ precompile(Tuple{typeof(Plots._cbar_unique), Array{PlotUtils.ColorGradient, 1}, String})
+ precompile(Tuple{typeof(Plots._cbar_unique), Array{Symbol, 1}, String})
+ precompile(Tuple{typeof(Plots._create_backend_figure), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._cycle), Array{Any, 1}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Array{Float64, 1}, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots._cycle), Array{Float64, 1}, Base.StepRange{Int64, Int64}})
+ precompile(Tuple{typeof(Plots._cycle), Array{Float64, 1}, Base.UnitRange{Int64}})
+ precompile(Tuple{typeof(Plots._cycle), Array{Float64, 1}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Array{Plots.Subplot{T} where T<:RecipesBase.AbstractBackend, 1}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Array{String, 1}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Base.OneTo{Int64}, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots._cycle), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Base.StepRange{Int64, Int64}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), ColorTypes.RGBA{Float64}, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Float64, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Int64, Base.StepRange{Int64, Int64}})
+ precompile(Tuple{typeof(Plots._cycle), Int64, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Nothing, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Plots.Shape, Int64})
+ precompile(Tuple{typeof(Plots._cycle), Symbol, Int64})
+ precompile(Tuple{typeof(Plots._display), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._display), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._do_plot_show), Plots.Plot{Plots.GRBackend}, Bool})
+ precompile(Tuple{typeof(Plots._do_plot_show), Plots.Plot{Plots.GRBackend}, Bool})
+ precompile(Tuple{typeof(Plots._do_plot_show), Plots.Plot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots._do_plot_show), Plots.Plot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Base.Complex{Float64}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Int64}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Int64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Plots.OHLC{T} where T<:Real, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{String, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Array{Union{Base.Missing, Int64}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.StepRange{Int64, Int64}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Array{T, 1} where T, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Array{T, 1} where T, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Base.Complex{Float64}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Function, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Function, 1}, Int64}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Int64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Plots.OHLC{T} where T<:Real, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{String, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{String, 1}, Array{String, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Array{Union{Base.Missing, Int64}, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.StepRange{Int64, Int64}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Plots.PortfolioComposition}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, Plots.Spy}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy, typeof(Base.log), Int64}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.GroupBy}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.PortfolioComposition}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{Plots.Spy}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{typeof(Base.log), Int64}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._expand_seriestype_array), Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._expand_subplot_extrema), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots._expand_subplot_extrema), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots._filter_input_data!), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._heatmap_edges), Array{Float64, 1}, Bool})
+ precompile(Tuple{typeof(Plots._hist_edge), Tuple{Array{Float64, 1}}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots._hist_edges), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Int64})
+ precompile(Tuple{typeof(Plots._hist_edges), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Tuple{Int64, Int64}})
+ precompile(Tuple{typeof(Plots._hist_edges), Tuple{Array{Float64, 1}}, Symbol})
+ precompile(Tuple{typeof(Plots._override_seriestype_check), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots._pick_default_backend)})
+ precompile(Tuple{typeof(Plots._pick_default_backend)})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Base.Complex{Float64}, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Int64}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Int64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Plots.OHLC{T} where T<:Real, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{String, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Union{Base.Missing, Int64}, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRange{Int64, Int64}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Plots.PortfolioComposition}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Plots.Spy}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{typeof(Base.log), Int64}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._plot!), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._plot_setup), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._plot_setup), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._plots_defaults)})
+ precompile(Tuple{typeof(Plots._prepare_annotations), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._prepare_annotations), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._prepare_subplot), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._prepare_subplot), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._prepare_subplot), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}, Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Base.Complex{Float64}, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Int64}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Int64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Plots.OHLC{T} where T<:Real, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{String, 1}, Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Array{Union{Base.Missing, Int64}, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.StepRange{Int64, Int64}, Array{Float64, 2}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Base.UnitRange{Int64}}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Plots.PortfolioComposition}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{Plots.Spy}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{typeof(Base.log), Int64}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_args), Base.Dict{Symbol, Any}, Tuple{}, Array{RecipesBase.RecipeData, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_barlike), Base.Dict{Symbol, Any}, Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_barlike), Base.Dict{Symbol, Any}, Array{Int64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_barlike), Base.Dict{Symbol, Any}, Base.OneTo{Int64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_binlike), Base.Dict{Symbol, Any}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots._preprocess_userrecipe), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._preprocess_userrecipe), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._process_plotrecipe), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._process_plotrecipe), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._process_seriesrecipe), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._process_seriesrecipe), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._process_seriesrecipe), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._process_userrecipe), Plots.Plot{Plots.GRBackend}, Array{Base.Dict{Symbol, Any}, 1}, RecipesBase.RecipeData})
+ precompile(Tuple{typeof(Plots._process_userrecipe), Plots.Plot{Plots.GRBackend}, Array{Base.Dict{Symbol, Any}, 1}, RecipesBase.RecipeData})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{Float64, 1}, 1}, Array{Array{Float64, 1}, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Array{T, 1} where T, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Base.Complex{Float64}, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Function, 1}, Int64}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Int64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Plots.OHLC{T} where T<:Real, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{String, 1}, Array{String, 1}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Array{Union{Base.Missing, Int64}, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.StepRange{Int64, Int64}, Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Base.UnitRange{Int64}}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Plots.PortfolioComposition}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{Plots.Spy}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{typeof(Base.log), Int64}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._process_userrecipes), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Tuple{}})
+ precompile(Tuple{typeof(Plots._replace_linewidth), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._replace_linewidth), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._replace_markershape), Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots._replace_markershape), Plots.Shape})
+ precompile(Tuple{typeof(Plots._scale_adjusted_values), Type{Float64}, Array{Float64, 1}, Symbol})
+ precompile(Tuple{typeof(Plots._series_index), Base.Dict{Symbol, Any}, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._show), Base.IOStream, Base.Multimedia.MIME{Symbol("image/png")}, Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._show), Base.IOStream, Base.Multimedia.MIME{Symbol("image/png")}, Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._subplot_setup), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._subplot_setup), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Array{Base.Dict{Symbol, Any}, 1}})
+ precompile(Tuple{typeof(Plots._transform_ticks), Base.StepRange{Int64, Int64}})
+ precompile(Tuple{typeof(Plots._transform_ticks), Base.UnitRange{Int64}})
+ precompile(Tuple{typeof(Plots._transform_ticks), Nothing})
+ precompile(Tuple{typeof(Plots._transform_ticks), Symbol})
+ precompile(Tuple{typeof(Plots._update_axis), Plots.Axis, Base.Dict{Symbol, Any}, Symbol, Int64})
+ precompile(Tuple{typeof(Plots._update_axis), Plots.Axis, Base.Dict{Symbol, Any}, Symbol, Int64})
+ precompile(Tuple{typeof(Plots._update_axis), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Symbol, Int64})
+ precompile(Tuple{typeof(Plots._update_axis), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Symbol, Int64})
+ precompile(Tuple{typeof(Plots._update_axis_colors), Plots.Axis})
+ precompile(Tuple{typeof(Plots._update_axis_colors), Plots.Axis})
+ precompile(Tuple{typeof(Plots._update_axis_links), Plots.Plot{Plots.GRBackend}, Plots.Axis, Symbol})
+ precompile(Tuple{typeof(Plots._update_axis_links), Plots.Plot{Plots.GRBackend}, Plots.Axis, Symbol})
+ precompile(Tuple{typeof(Plots._update_clims), Float64, Float64, Float64, Float64})
+ precompile(Tuple{typeof(Plots._update_clims), Float64, Float64, Int64, Int64})
+ precompile(Tuple{typeof(Plots._update_min_padding!), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots._update_min_padding!), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots._update_min_padding!), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_min_padding!), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_plot_args), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._update_plot_args), Plots.Plot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots._update_series_attributes!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_series_attributes!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_series_attributes!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_subplot_args), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Int64, Bool})
+ precompile(Tuple{typeof(Plots._update_subplot_args), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Int64, Bool})
+ precompile(Tuple{typeof(Plots._update_subplot_args), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}, Int64, Bool})
+ precompile(Tuple{typeof(Plots._update_subplot_colors), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_subplot_colors), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_subplot_colors), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots._update_subplot_periphery), Plots.Subplot{Plots.GRBackend}, Array{Any, 1}})
+ precompile(Tuple{typeof(Plots._update_subplot_periphery), Plots.Subplot{Plots.GRBackend}, Array{Any, 1}})
+ precompile(Tuple{typeof(Plots.addExtension), String, String})
+ precompile(Tuple{typeof(Plots.add_layout_pct!), Base.Dict{Symbol, Any}, Expr, Int64, Int64})
+ precompile(Tuple{typeof(Plots.add_layout_pct!), Base.Dict{Symbol, Any}, Expr, Int64, Int64})
+ precompile(Tuple{typeof(Plots.aliasesAndAutopick), Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Symbol}, Array{Symbol, 1}, Int64})
+ precompile(Tuple{typeof(Plots.aliasesAndAutopick), Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Symbol}, Array{Symbol, 1}, Int64})
+ precompile(Tuple{typeof(Plots.all3D), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.allAlphas), Int64})
+ precompile(Tuple{typeof(Plots.allStyles), Int64})
+ precompile(Tuple{typeof(Plots.allStyles), Symbol})
+ precompile(Tuple{typeof(Plots.annotate!), Array{Tuple{Int64, Float64, Plots.PlotText}, 1}})
+ precompile(Tuple{typeof(Plots.annotations), Array{Any, 1}})
+ precompile(Tuple{typeof(Plots.arrow), Int64})
+ precompile(Tuple{typeof(Plots.attr!), Plots.Axis})
+ precompile(Tuple{typeof(Plots.attr!), Plots.Axis})
+ precompile(Tuple{typeof(Plots.attr), Plots.EmptyLayout, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.attr), Plots.EmptyLayout, Symbol})
+ precompile(Tuple{typeof(Plots.autopick), Array{ColorTypes.RGBA{Float64}, 1}, Int64})
+ precompile(Tuple{typeof(Plots.autopick_ignore_none_auto), Array{Symbol, 1}, Int64})
+ precompile(Tuple{typeof(Plots.axis_drawing_info), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.axis_drawing_info), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.axis_drawing_info_3d), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.axis_drawing_info_3d), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.axis_limits), Plots.Subplot{Plots.GRBackend}, Symbol, Bool, Bool})
+ precompile(Tuple{typeof(Plots.axis_limits), Plots.Subplot{Plots.GRBackend}, Symbol, Bool, Bool})
+ precompile(Tuple{typeof(Plots.axis_limits), Plots.Subplot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots.axis_limits), Plots.Subplot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots.backend), Plots.GRBackend})
+ precompile(Tuple{typeof(Plots.backend), Symbol})
+ precompile(Tuple{typeof(Plots.backend), Symbol})
+ precompile(Tuple{typeof(Plots.backend)})
+ precompile(Tuple{typeof(Plots.backend)})
+ precompile(Tuple{typeof(Plots.bar), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.bbox!), Plots.GridLayout, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.bbox!), Plots.Subplot{Plots.GRBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.bottom), Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.bottompad), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.build_layout), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.build_layout), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.build_layout), Plots.GridLayout, Int64, Array{Plots.Plot{T} where T<:RecipesBase.AbstractBackend, 1}})
+ precompile(Tuple{typeof(Plots.build_layout), Plots.GridLayout, Int64, Array{Plots.Plot{T} where T<:RecipesBase.AbstractBackend, 1}})
+ precompile(Tuple{typeof(Plots.build_layout), Plots.GridLayout, Int64})
+ precompile(Tuple{typeof(Plots.build_layout), Plots.GridLayout, Int64})
+ precompile(Tuple{typeof(Plots.calc_num_subplots), Plots.EmptyLayout})
+ precompile(Tuple{typeof(Plots.calc_num_subplots), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots.color_or_nothing!), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.color_or_nothing!), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.colorbar_style), Plots.Series})
+ precompile(Tuple{typeof(Plots.colorbar_style), Plots.Series})
+ precompile(Tuple{typeof(Plots.command_idx), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.compute_gridsize), Int64, Int64, Int64})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{Float64, 1}, Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{Float64, 1}, Array{Float64, 1}, Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{Float64, 1}, Array{Float64, 1}, Plots.Surface{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{Float64, 1}, typeof(identity), Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{Float64, 1}, typeof(identity), Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{String, 1}, Array{Float64, 1}, Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Array{String, 1}, Array{String, 1}, Plots.Surface{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots.compute_xyz), Nothing, Array{Float64, 1}, Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Nothing, Array{Union{Base.Missing, Float64}, 1}, Nothing})
+ precompile(Tuple{typeof(Plots.compute_xyz), Nothing, Nothing, Nothing})
+ precompile(Tuple{typeof(Plots.contour), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int})
+ precompile(Tuple{typeof(Plots.contour_levels), Plots.Series, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.convertLegendValue), Bool})
+ precompile(Tuple{typeof(Plots.convertLegendValue), Symbol})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Array{Array{Float64, 1}, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Array{Array{T, 1} where T, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Array{Float64, 2}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Array{Function, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Array{Function, 1}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convertToAnyVector), Int64, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.convert_sci_unicode), String})
+ precompile(Tuple{typeof(Plots.convert_sci_unicode), String})
+ precompile(Tuple{typeof(Plots.convert_to_polar), Array{Float64, 1}, Array{Float64, 1}, Tuple{Int64, Float64}})
+ precompile(Tuple{typeof(Plots.create_grid), Expr})
+ precompile(Tuple{typeof(Plots.create_grid), Expr})
+ precompile(Tuple{typeof(Plots.create_grid), Symbol})
+ precompile(Tuple{typeof(Plots.create_grid_curly), Expr})
+ precompile(Tuple{typeof(Plots.create_grid_curly), Expr})
+ precompile(Tuple{typeof(Plots.create_grid_vcat), Expr})
+ precompile(Tuple{typeof(Plots.create_grid_vcat), Expr})
+ precompile(Tuple{typeof(Plots.default), Symbol})
+ precompile(Tuple{typeof(Plots.default_should_widen), Plots.Axis})
+ precompile(Tuple{typeof(Plots.default_should_widen), Plots.Axis})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, Array{Any, 1}})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, Array{String, 1}})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, Array{Union{Base.Missing, Float64}, 1}})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, Base.Missing})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, Char})
+ precompile(Tuple{typeof(Plots.discrete_value!), Plots.Axis, String})
+ precompile(Tuple{typeof(Plots.ensure_gradient!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.ensure_gradient!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.ensure_gradient!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Base.OneTo{Int64}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Base.OneTo{Int64}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Base.UnitRange{Int64}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Float64})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Float64})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Int64})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Int64})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Plots.Surface{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Plots.Surface{Array{Float64, 2}}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Axis, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Subplot{Plots.GRBackend}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.extendSeriesData), Array{Float64, 1}, Float64})
+ precompile(Tuple{typeof(Plots.extractGroupArgs), Array{String, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.fakedata), Int64, Int64})
+ precompile(Tuple{typeof(Plots.fakedata), Int64, Int64})
+ precompile(Tuple{typeof(Plots.fg_color), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.fg_color), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.filter_data!), Base.Dict{Symbol, Any}, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.filter_data), Array{Float64, 1}, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.filter_data), Base.OneTo{Int64}, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.filter_data), Nothing, Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.font), Int64, Int})
+ precompile(Tuple{typeof(Plots.font), String, Int})
+ precompile(Tuple{typeof(Plots.font), String, Int})
+ precompile(Tuple{typeof(Plots.font), Symbol, Int})
+ precompile(Tuple{typeof(Plots.frame), Plots.Animation, Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.frame), Plots.Animation})
+ precompile(Tuple{typeof(Plots.get_axis), Plots.Subplot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots.get_axis), Plots.Subplot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Subplot{Plots.GRBackend}, Plots.Series})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Subplot{Plots.GRBackend}, Plots.Series})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.get_clims), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.get_fillalpha), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_fillalpha), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_fillcolor), Plots.Series, Float64, Float64, Int64})
+ precompile(Tuple{typeof(Plots.get_fillcolor), Plots.Series, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.get_fillcolor), Plots.Series, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.get_linealpha), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_linealpha), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_linecolor), Plots.Series, Float64, Float64, Int64})
+ precompile(Tuple{typeof(Plots.get_linecolor), Plots.Series, Float64, Float64, Int64})
+ precompile(Tuple{typeof(Plots.get_linecolor), Plots.Series, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.get_linecolor), Plots.Series, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.get_linecolor), Plots.Series, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.get_linestyle), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_linestyle), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_linewidth), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_linewidth), Plots.Series})
+ precompile(Tuple{typeof(Plots.get_markeralpha), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_markercolor), Plots.Series, Float64, Float64, Int64})
+ precompile(Tuple{typeof(Plots.get_markercolor), Plots.Series, Float64, Float64, Int64})
+ precompile(Tuple{typeof(Plots.get_markerstrokealpha), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_markerstrokecolor), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.get_minor_ticks), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Tuple{Array{Float64, 1}, Array{Any, 1}}})
+ precompile(Tuple{typeof(Plots.get_minor_ticks), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Tuple{Array{Float64, 1}, Array{String, 1}}})
+ precompile(Tuple{typeof(Plots.get_minor_ticks), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Tuple{Array{Float64, 1}, Array{String, 1}}})
+ precompile(Tuple{typeof(Plots.get_series_color), ColorTypes.RGBA{Float64}, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), ColorTypes.RGBA{Float64}, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), ColorTypes.RGBA{Float64}, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), Int64, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), PlotUtils.ColorGradient, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), PlotUtils.ColorGradient, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), Symbol, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), Symbol, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_series_color), Symbol, Plots.Subplot{Plots.GRBackend}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.get_subplot), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.get_ticks), Plots.Subplot{Plots.GRBackend}, Plots.Axis})
+ precompile(Tuple{typeof(Plots.get_ticks), Plots.Subplot{Plots.GRBackend}, Plots.Axis})
+ precompile(Tuple{typeof(Plots.get_xy), Array{Plots.OHLC{T} where T<:Real, 1}, Base.OneTo{Int64}})
+ precompile(Tuple{typeof(Plots.get_xy), Plots.OHLC{Float64}, Int64, Float64})
+ precompile(Tuple{typeof(Plots.getxy), Plots.Plot{Plots.GRBackend}, Int64})
+ precompile(Tuple{typeof(Plots.gr_axis_height), Plots.Subplot{Plots.GRBackend}, Plots.Axis})
+ precompile(Tuple{typeof(Plots.gr_axis_width), Plots.Subplot{Plots.GRBackend}, Plots.Axis})
+ precompile(Tuple{typeof(Plots.gr_color), ColorTypes.RGBA{Float64}, Type{ColorTypes.RGB{Float64}}})
+ precompile(Tuple{typeof(Plots.gr_colorbar_colors), Plots.Series, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_contour_levels), Plots.Series, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_display), Plots.Plot{Plots.GRBackend}, String})
+ precompile(Tuple{typeof(Plots.gr_display), Plots.Plot{Plots.GRBackend}, String})
+ precompile(Tuple{typeof(Plots.gr_display), Plots.Subplot{Plots.GRBackend}, Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_display), Plots.Subplot{Plots.GRBackend}, Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_draw_colorbar), Plots.GRColorbar, Plots.Subplot{Plots.GRBackend}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Float64, Float64, Int64, Plots.Shape})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Float64, Float64, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Float64, Float64, Plots.Shape})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Float64, Float64, Symbol})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Float64, Int64, Plots.Shape})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Float64, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Int64, Int64, Plots.Shape})
+ precompile(Tuple{typeof(Plots.gr_draw_marker), Int64, Int64, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Float64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Float64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Float64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Float64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Int64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Int64, 1}, Array{Float64, 1}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Int64, 1}, Array{Int64, 1}, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Array{Int64, 1}, Array{Int64, 1}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Base.OneTo{Int64}, Array{Float64, 1}, Tuple{Float64, Float64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Base.OneTo{Int64}, Array{Float64, 1}, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Base.OneTo{Int64}, Array{Float64, 1}, Tuple{Float64, Float64}})
+ precompile(Tuple{typeof(Plots.gr_draw_markers), Plots.Series, Float64, Float64, Tuple{Float64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.gr_fill_viewport), Array{Float64, 1}, ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_get_color), Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_get_color), Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_get_ticks_size), Tuple{Array{Float64, 1}, Array{Any, 1}}, Int64})
+ precompile(Tuple{typeof(Plots.gr_get_ticks_size), Tuple{Array{Float64, 1}, Array{String, 1}}, Int64})
+ precompile(Tuple{typeof(Plots.gr_get_ticks_size), Tuple{Array{Float64, 1}, Array{String, 1}}, Int64})
+ precompile(Tuple{typeof(Plots.gr_inqtext), Int64, Int64, String})
+ precompile(Tuple{typeof(Plots.gr_inqtext), Int64, Int64, String})
+ precompile(Tuple{typeof(Plots.gr_legend_pos), Plots.Subplot{Plots.GRBackend}, Float64, Float64})
+ precompile(Tuple{typeof(Plots.gr_polaraxes), Int64, Float64, Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_polyline), Array{Float64, 1}, Array{Float64, 1}, typeof(identity)})
+ precompile(Tuple{typeof(Plots.gr_polyline), Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_set_fill), ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_fillcolor), ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_font), Plots.Font})
+ precompile(Tuple{typeof(Plots.gr_set_font), Plots.Font})
+ precompile(Tuple{typeof(Plots.gr_set_gradient), PlotUtils.ColorGradient})
+ precompile(Tuple{typeof(Plots.gr_set_gradient), Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_set_gradient), Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_set_line), Float64, Symbol, ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_line), Int64, Symbol, ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_line), Int64, Symbol, PlotUtils.ColorGradient})
+ precompile(Tuple{typeof(Plots.gr_set_linecolor), PlotUtils.ColorGradient})
+ precompile(Tuple{typeof(Plots.gr_set_markercolor), ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_textcolor), ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.gr_set_transparency), ColorTypes.RGBA{Float64}, Float64})
+ precompile(Tuple{typeof(Plots.gr_set_transparency), ColorTypes.RGBA{Float64}, Nothing})
+ precompile(Tuple{typeof(Plots.gr_set_viewport_cmap), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_set_viewport_polar)})
+ precompile(Tuple{typeof(Plots.gr_set_xticks_font), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_set_xticks_font), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_set_yticks_font), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_set_yticks_font), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.gr_text), Float64, Float64, String})
+ precompile(Tuple{typeof(Plots.gr_text), Float64, Float64, String})
+ precompile(Tuple{typeof(Plots.gr_text_size), String, Int64})
+ precompile(Tuple{typeof(Plots.gr_text_size), String, Int64})
+ precompile(Tuple{typeof(Plots.gr_text_size), String})
+ precompile(Tuple{typeof(Plots.gr_update_colorbar!), Plots.GRColorbar, Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_update_colorbar!), Plots.GRColorbar, Plots.Series})
+ precompile(Tuple{typeof(Plots.gr_viewport_from_bbox), Plots.Subplot{Plots.GRBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}, Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_viewport_from_bbox), Plots.Subplot{Plots.GRBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}, Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.gr_w3tondc), Float64, Float64, Float64})
+ precompile(Tuple{typeof(Plots.gui), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.guidefont), Plots.Axis})
+ precompile(Tuple{typeof(Plots.guidefont), Plots.Axis})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Array{Symbol, 2}, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Array{Symbol, 2}, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Array{Symbol, 2}, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, ColorTypes.RGBA{Float64}, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Plots.Shape, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.handleColors!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.has_attribute_segments), Plots.Series})
+ precompile(Tuple{typeof(Plots.has_attribute_segments), Plots.Series})
+ precompile(Tuple{typeof(Plots.hascolorbar), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.hascolorbar), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.hasgrid), Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Array{Float64, 1}, Symbol, Array{Float64, 1}, Symbol, Tuple{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Array{Float64, 1}, Symbol, Bool})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Array{Float64, 1}, Symbol, Bool})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Array{Float64, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol, Tuple{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol, Bool})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol, Bool})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol, Bool})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol})
+ precompile(Tuple{typeof(Plots.heatmap_edges), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Symbol})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Array{Float64, 2}})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Base.StepRange{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Plots.Axis})
+ precompile(Tuple{typeof(Plots.ignorenan_extrema), Plots.Axis})
+ precompile(Tuple{typeof(Plots.ignorenan_maximum), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.ignorenan_maximum), Base.OneTo{Int64}})
+ precompile(Tuple{typeof(Plots.ignorenan_minimum), Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.ignorenan_minimum), Base.OneTo{Int64}})
+ precompile(Tuple{typeof(Plots.inline), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.is3d), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.is3d), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.is3d), Symbol})
+ precompile(Tuple{typeof(Plots.is_2tuple), Int64})
+ precompile(Tuple{typeof(Plots.is_2tuple), Symbol})
+ precompile(Tuple{typeof(Plots.is_2tuple), Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots.is_2tuple), Tuple{Int64, Float64}})
+ precompile(Tuple{typeof(Plots.is_2tuple), Tuple{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.is_attr_supported), Plots.GRBackend, Symbol})
+ precompile(Tuple{typeof(Plots.is_attr_supported), Symbol})
+ precompile(Tuple{typeof(Plots.is_marker_supported), Plots.GRBackend, Symbol})
+ precompile(Tuple{typeof(Plots.is_marker_supported), Plots.Shape})
+ precompile(Tuple{typeof(Plots.is_marker_supported), Plots.Stroke})
+ precompile(Tuple{typeof(Plots.is_marker_supported), Symbol})
+ precompile(Tuple{typeof(Plots.is_marker_supported), Symbol})
+ precompile(Tuple{typeof(Plots.is_scale_supported), Plots.GRBackend, Symbol})
+ precompile(Tuple{typeof(Plots.is_seriestype_supported), Plots.GRBackend, Symbol})
+ precompile(Tuple{typeof(Plots.is_seriestype_supported), Symbol})
+ precompile(Tuple{typeof(Plots.is_seriestype_supported), Symbol})
+ precompile(Tuple{typeof(Plots.is_style_supported), Plots.GRBackend, Symbol})
+ precompile(Tuple{typeof(Plots.is_uniformly_spaced), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iscontour), Plots.Series})
+ precompile(Tuple{typeof(Plots.iscontour), Plots.Series})
+ precompile(Tuple{typeof(Plots.isijulia)})
+ precompile(Tuple{typeof(Plots.ispolar), Plots.Series})
+ precompile(Tuple{typeof(Plots.ispolar), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.isvertical), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.isvertical), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.iter_segments), Array{Float64, 1}, Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iter_segments), Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iter_segments), Array{Int64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iter_segments), Base.OneTo{Int64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iter_segments), Base.UnitRange{Int64}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.iter_segments), Plots.Series})
+ precompile(Tuple{typeof(Plots.iter_segments), Plots.Series})
+ precompile(Tuple{typeof(Plots.labelfunc), Symbol, Plots.GRBackend})
+ precompile(Tuple{typeof(Plots.layout_args), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.layout_args), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.layout_args), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.layout_args), Int64, Int64})
+ precompile(Tuple{typeof(Plots.layout_args), Int64, Plots.GridLayout})
+ precompile(Tuple{typeof(Plots.layout_args), Int64, Tuple{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.layout_args), Int64})
+ precompile(Tuple{typeof(Plots.layout_args), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots.leftpad), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.legendfont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.legendfont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.legendtitlefont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.legendtitlefont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.like_histogram), Symbol})
+ precompile(Tuple{typeof(Plots.like_surface), Symbol})
+ precompile(Tuple{typeof(Plots.link_axes!), Array{RecipesBase.AbstractLayout, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.link_axes!), Array{RecipesBase.AbstractLayout, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.link_axes!), Plots.Axis, Plots.Axis})
+ precompile(Tuple{typeof(Plots.link_axes!), Plots.Axis, Plots.Axis})
+ precompile(Tuple{typeof(Plots.link_axes!), Plots.GridLayout, Symbol})
+ precompile(Tuple{typeof(Plots.link_axes!), Plots.GridLayout, Symbol})
+ precompile(Tuple{typeof(Plots.link_axes!), Plots.Subplot{Plots.GRBackend}, Symbol})
+ precompile(Tuple{typeof(Plots.link_subplots), Array{RecipesBase.AbstractLayout, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.locate_annotation), Plots.Subplot{Plots.GRBackend}, Int64, Float64, Plots.PlotText})
+ precompile(Tuple{typeof(Plots.make_fillrange_from_ribbon), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.make_fillrange_side), Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.make_fillrange_side), Array{Float64, 1}, Int64})
+ precompile(Tuple{typeof(Plots.make_steps), Array{Float64, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.make_steps), Array{Int64, 1}, Symbol})
+ precompile(Tuple{typeof(Plots.make_steps), Base.OneTo{Int64}, Symbol})
+ precompile(Tuple{typeof(Plots.make_steps), Nothing, Symbol})
+ precompile(Tuple{typeof(Plots.nanappend!), Array{Float64, 1}, Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.nobigs), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.ohlc), Array{Plots.OHLC{T} where T<:Real, 1}})
+ precompile(Tuple{typeof(Plots.optimal_ticks_and_labels), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Base.StepRange{Int64, Int64}})
+ precompile(Tuple{typeof(Plots.optimal_ticks_and_labels), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Base.UnitRange{Int64}})
+ precompile(Tuple{typeof(Plots.optimal_ticks_and_labels), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Nothing})
+ precompile(Tuple{typeof(Plots.optimal_ticks_and_labels), Plots.Subplot{Plots.GRBackend}, Plots.Axis, Nothing})
+ precompile(Tuple{typeof(Plots.pie_labels), Plots.Subplot{Plots.GRBackend}, Plots.Series})
+ precompile(Tuple{typeof(Plots.plotarea!), Plots.GridLayout, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.plotarea!), Plots.Subplot{Plots.GRBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.png), Plots.Plot{Plots.GRBackend}, String})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Float64, 2}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Int32, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Union{Base.Missing, Int64}, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Union{Base.Missing, Number}, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Array{Union{Base.Missing, Number}, 1}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Base.LinRange{Float64}})
+ precompile(Tuple{typeof(Plots.prepareSeriesData), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
+ precompile(Tuple{typeof(Plots.prepare_output), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.prepare_output), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.preprocessArgs!), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.preprocessArgs!), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Bool})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Float64})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processFillArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processGridArg!), Base.Dict{Symbol, Any}, Bool, Symbol})
+ precompile(Tuple{typeof(Plots.processGridArg!), Base.Dict{Symbol, Any}, Float64, Symbol})
+ precompile(Tuple{typeof(Plots.processGridArg!), Base.Dict{Symbol, Any}, Int64, Symbol})
+ precompile(Tuple{typeof(Plots.processGridArg!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Float64})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processLineArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Bool})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, ColorTypes.RGBA{Float64}})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Float64})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Float64})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Int64})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Plots.Shape})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Plots.Stroke})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.processMarkerArg), Base.Dict{Symbol, Any}, Symbol})
+ precompile(Tuple{typeof(Plots.process_annotation), Plots.Subplot{Plots.GRBackend}, Int64, Float64, Plots.PlotText, Plots.Font})
+ precompile(Tuple{typeof(Plots.process_annotation), Plots.Subplot{Plots.GRBackend}, Int64, Float64, Plots.PlotText})
+ precompile(Tuple{typeof(Plots.process_axis_arg!), Base.Dict{Symbol, Any}, Base.StepRange{Int64, Int64}, Symbol})
+ precompile(Tuple{typeof(Plots.process_axis_arg!), Base.Dict{Symbol, Any}, String, Symbol})
+ precompile(Tuple{typeof(Plots.process_axis_arg!), Base.Dict{Symbol, Any}, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.process_axis_arg!), Base.Dict{Symbol, Any}, Tuple{Int64, Int64}, Symbol})
+ precompile(Tuple{typeof(Plots.process_fillrange), Int64, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_fillrange), Nothing, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_ribbon), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_ribbon), Int64, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_ribbon), Nothing, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_ribbon), Tuple{Base.LinRange{Float64}, Base.LinRange{Float64}}, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.process_ribbon), typeof(identity), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.recompute_lengths), Array{Measures.Measure, 1}})
+ precompile(Tuple{typeof(Plots.recompute_lengths), Array{Measures.Measure, 1}})
+ precompile(Tuple{typeof(Plots.replaceAlias!), Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Symbol}})
+ precompile(Tuple{typeof(Plots.replaceAliases!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Symbol}})
+ precompile(Tuple{typeof(Plots.reset_extrema!), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.reset_extrema!), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.right), Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}})
+ precompile(Tuple{typeof(Plots.rightpad), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.rowsize), Expr})
+ precompile(Tuple{typeof(Plots.rowsize), Symbol})
+ precompile(Tuple{typeof(Plots.series_annotations), Array{Any, 1}})
+ precompile(Tuple{typeof(Plots.series_annotations), Nothing})
+ precompile(Tuple{typeof(Plots.series_annotations), Plots.SeriesAnnotations})
+ precompile(Tuple{typeof(Plots.series_annotations_shapes!), Plots.Series, Symbol})
+ precompile(Tuple{typeof(Plots.series_annotations_shapes!), Plots.Series, Symbol})
+ precompile(Tuple{typeof(Plots.setxy!), Plots.Plot{Plots.GRBackend}, Tuple{Array{Float64, 1}, Array{Float64, 1}}, Int64})
+ precompile(Tuple{typeof(Plots.shape_data), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.shape_data), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.should_add_to_legend), Plots.Series})
+ precompile(Tuple{typeof(Plots.should_add_to_legend), Plots.Series})
+ precompile(Tuple{typeof(Plots.showaxis), Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Array{Any, 1}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Array{Any, 1}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Any}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Any}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Bool, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Bool, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Float64, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Float64, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Int64, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Int64, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Measures.Length{:mm, Float64}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Measures.Length{:mm, Float64}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Nothing, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Nothing, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, String, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, String, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Symbol, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Symbol, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Tuple{Int64, Int64}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Tuple{Int64, Int64}, Int64, Bool})
+ precompile(Tuple{typeof(Plots.slice_arg), Array{ColorTypes.RGBA{Float64}, 2}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Array{Measures.Length{:mm, Float64}, 2}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Array{String, 2}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Array{Symbol, 2}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Base.ReshapedArray{Int64, 2, Base.UnitRange{Int64}, Tuple{}}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Base.StepRange{Int64, Int64}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Base.UnitRange{Int64}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Bool, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), ColorTypes.RGBA{Float64}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Float64, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Int64, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Nothing, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), String, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Symbol, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Tuple{Int64, Float64}, Int64})
+ precompile(Tuple{typeof(Plots.slice_arg), Tuple{Int64, Int64}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Array{Int64, 1}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Array{String, 1}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Array{Symbol, 2}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, ColorTypes.RGB{Float64}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Float64, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Int64, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Plots.GridLayout, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Plots.Plot{Plots.GRBackend}, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, String, Int64})
+ precompile(Tuple{typeof(Plots.splittable_kw), Symbol, Symbol, Int64})
+ precompile(Tuple{typeof(Plots.straightline_data), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.straightline_data), Plots.Series, Int64})
+ precompile(Tuple{typeof(Plots.straightline_data), Tuple{Int64, Int64}, Tuple{Float64, Float64}, Array{Float64, 1}, Array{Float64, 1}, Int64})
+ precompile(Tuple{typeof(Plots.stroke), Int64, Int})
+ precompile(Tuple{typeof(Plots.supported_markers), Plots.GRBackend})
+ precompile(Tuple{typeof(Plots.supported_markers)})
+ precompile(Tuple{typeof(Plots.supported_styles), Plots.GRBackend})
+ precompile(Tuple{typeof(Plots.supported_styles)})
+ precompile(Tuple{typeof(Plots.text), String, Int64, Symbol, Symbol})
+ precompile(Tuple{typeof(Plots.text), String, Symbol, Int64, Int})
+ precompile(Tuple{typeof(Plots.text), String, Symbol})
+ precompile(Tuple{typeof(Plots.tickfont), Plots.Axis})
+ precompile(Tuple{typeof(Plots.tickfont), Plots.Axis})
+ precompile(Tuple{typeof(Plots.title!), String})
+ precompile(Tuple{typeof(Plots.titlefont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.titlefont), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.toppad), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.tovec), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.transpose_z), Plots.Series, Array{Float64, 2}, Bool})
+ precompile(Tuple{typeof(Plots.trueOrAllTrue), typeof(Plots.is3d), Symbol})
+ precompile(Tuple{typeof(Plots.trueOrAllTrue), typeof(identity), Array{Symbol, 2}})
+ precompile(Tuple{typeof(Plots.unzip), Array{Tuple{Float64, Float64, Float64}, 1}})
+ precompile(Tuple{typeof(Plots.update_child_bboxes!), Plots.GridLayout, Array{Measures.Length{:mm, Float64}, 1}})
+ precompile(Tuple{typeof(Plots.update_child_bboxes!), Plots.GridLayout, Array{Measures.Length{:mm, Float64}, 1}})
+ precompile(Tuple{typeof(Plots.update_child_bboxes!), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots.update_child_bboxes!), Plots.GridLayout})
+ precompile(Tuple{typeof(Plots.update_child_bboxes!), Plots.Subplot{Plots.GRBackend}, Array{Measures.Length{:mm, Float64}, 1}})
+ precompile(Tuple{typeof(Plots.update_inset_bboxes!), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.update_inset_bboxes!), Plots.Plot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.vline!), Array{Int64, 1}})
+ precompile(Tuple{typeof(Plots.wand_edges), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported_args), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported_args), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported_scales), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.warnOnUnsupported_scales), Plots.GRBackend, Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.widen), Float64, Float64, Symbol})
+ precompile(Tuple{typeof(Plots.wrap_surfaces), Base.Dict{Symbol, Any}})
+ precompile(Tuple{typeof(Plots.wraptuple), Array{Any, 1}})
+ precompile(Tuple{typeof(Plots.wraptuple), Array{Float64, 1}})
+ precompile(Tuple{typeof(Plots.wraptuple), Bool})
+ precompile(Tuple{typeof(Plots.wraptuple), Float64})
+ precompile(Tuple{typeof(Plots.wraptuple), Int64})
+ precompile(Tuple{typeof(Plots.wraptuple), Nothing})
+ precompile(Tuple{typeof(Plots.wraptuple), Plots.SeriesAnnotations})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Array{Float64, 1}, Array{Float64, 1}}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Array{Symbol, 2}, Int64, Float64, Plots.Stroke}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Array{Symbol, 2}, Int64}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Float64, Array{Symbol, 2}, Int64}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Float64, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Array{Symbol, 2}}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Float64, Symbol, Plots.Stroke}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Float64, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Symbol, Float64, Array{Symbol, 2}}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Symbol, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Int64, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Plots.Shape, Int64, ColorTypes.RGBA{Float64}}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{String, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{String, Tuple{Int64, Int64}, Base.StepRange{Int64, Int64}, Symbol}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Symbol, Float64, Plots.Stroke}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Symbol, Int64}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Symbol, Symbol, Int64, Symbol, Float64}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{Symbol, Symbol, Symbol, Int64, Float64}})
+ precompile(Tuple{typeof(Plots.wraptuple), Tuple{}})
+ precompile(Tuple{typeof(Plots.xgrid!), Plots.Plot{Plots.GRBackend}, Symbol, Int})
+ precompile(Tuple{typeof(Plots.xlims), Int64})
+ precompile(Tuple{typeof(Plots.xlims), Int64})
+ precompile(Tuple{typeof(Plots.xlims), Plots.Subplot{Plots.GRBackend}})
+ precompile(Tuple{typeof(Plots.yaxis!), String, Symbol})
+ precompile(Tuple{typeof(Plots.ylims), Int64})
+ precompile(Tuple{typeof(Plots.ylims), Int64})
+ precompile(Tuple{typeof(Plots.ylims), Plots.Subplot{Plots.GRBackend}})
end
diff --git a/src/recipes.jl b/src/recipes.jl
index 9be74970..06215cd2 100644
--- a/src/recipes.jl
+++ b/src/recipes.jl
@@ -239,7 +239,7 @@ end
@recipe function f(::Type{Val{:sticks}}, x, y, z)
n = length(x)
fr = plotattributes[:fillrange]
- if fr == nothing
+ if fr === nothing
sp = plotattributes[:subplot]
yaxis = sp[:yaxis]
fr = if yaxis[:scale] == :identity
@@ -291,13 +291,13 @@ end
# create segmented bezier curves in place of line segments
@recipe function f(::Type{Val{:curves}}, x, y, z; npoints = 30)
- args = z != nothing ? (x,y,z) : (x,y)
+ args = z !== nothing ? (x,y,z) : (x,y)
newx, newy = zeros(0), zeros(0)
fr = plotattributes[:fillrange]
- newfr = fr != nothing ? zeros(0) : nothing
- newz = z != nothing ? zeros(0) : nothing
+ newfr = fr !== nothing ? zeros(0) : nothing
+ newz = z !== nothing ? zeros(0) : nothing
# lz = plotattributes[:line_z]
- # newlz = lz != nothing ? zeros(0) : nothing
+ # newlz = lz !== nothing ? zeros(0) : nothing
# for each line segment (point series with no NaNs), convert it into a bezier curve
# where the points are the control points of the curve
@@ -306,13 +306,13 @@ end
ts = range(0, stop = 1, length = npoints)
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts))
- if z != nothing
+ if z !== nothing
nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
end
- if fr != nothing
+ if fr !== nothing
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
end
- # if lz != nothing
+ # if lz !== nothing
# lzrng = _cycle(lz, rng) # the line_z's for this segment
# push!(newlz, 0.0)
# append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
@@ -321,16 +321,16 @@ end
x := newx
y := newy
- if z == nothing
+ if z === nothing
seriestype := :path
else
seriestype := :path3d
z := newz
end
- if fr != nothing
+ if fr !== nothing
fillrange := newfr
end
- # if lz != nothing
+ # if lz !== nothing
# # line_z := newlz
# linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad())
# end
@@ -357,19 +357,19 @@ end
# compute half-width of bars
bw = plotattributes[:bar_width]
- hw = if bw == nothing
+ hw = if bw === nothing
if nx > 1
0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx)))
else
0.5 * _bar_width
end
else
- Float64[0.5_cycle(bw,i) for i=1:length(procx)]
+ Float64[0.5_cycle(bw,i) for i=eachindex(procx)]
end
# make fillto a vector... default fills to 0
fillto = plotattributes[:fillrange]
- if fillto == nothing
+ if fillto === nothing
fillto = 0
end
if (yscale in _logScales) && !all(_is_positive, fillto)
@@ -491,7 +491,7 @@ end
@recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
- if (plotattributes[:bar_width] == nothing)
+ if (plotattributes[:bar_width] === nothing)
bar_width := diff(edge)
end
x := _bin_centers(edge)
@@ -533,7 +533,7 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S
last_w = eltype(weights)(NaN)
- while it_tuple_e != nothing && it_tuple_w != nothing
+ while it_tuple_e !== nothing && it_tuple_w !== nothing
b, it_state_e = it_tuple_e
w, it_state_w = it_tuple_w
@@ -667,7 +667,7 @@ end
function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
localvs = _filternans(vs)
edges = _hist_edges(localvs, binning)
- h = float( weights == nothing ?
+ h = float( weights === nothing ?
StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left)
)
@@ -746,12 +746,14 @@ end
edge_x, edge_y, weights = x, y, z.surf
float_weights = float(weights)
- if float_weights === weights
- float_weights = deepcopy(float_weights)
- end
- for (i, c) in enumerate(float_weights)
- if c == 0
- float_weights[i] = NaN
+ if !plotattributes[:show_empty_bins]
+ if float_weights === weights
+ float_weights = deepcopy(float_weights)
+ end
+ for (i, c) in enumerate(float_weights)
+ if c == 0
+ float_weights[i] = NaN
+ end
end
end
@@ -996,7 +998,7 @@ function get_xy(o::OHLC, x, xdiff)
end
# get the joined vector
-function get_xy(v::AVec{OHLC}, x = 1:length(v))
+function get_xy(v::AVec{OHLC}, x = eachindex(v))
xdiff = 0.3ignorenan_mean(abs.(diff(x)))
x_out, y_out = zeros(0), zeros(0)
for (i,ohlc) in enumerate(v)
@@ -1054,8 +1056,8 @@ end
@assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix
seriestype := :spy
mat = g.args[1]
- n,m = size(mat)
- Plots.SliceIt, 1:m, 1:n, Surface(mat)
+ n,m = axes(mat)
+ Plots.SliceIt, m, n, Surface(mat)
end
@recipe function f(::Type{Val{:spy}}, x,y,z)
@@ -1101,6 +1103,11 @@ timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t)))
@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)))
+# -------------------------------------------------
+# Characters
+
+@recipe f(::Type{<:AbstractChar}, ::AbstractChar) = (string, string)
+
# -------------------------------------------------
# Complex Numbers
@@ -1178,7 +1185,7 @@ end
seriestype := :shape
# create a filled polygon for each item
- for c=1:size(weights,2)
+ for c=axes(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)
@@ -1199,9 +1206,9 @@ julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], f
@recipe function f(a::AreaPlot)
data = cumsum(a.args[end], dims=2)
- x = length(a.args) == 1 ? (1:size(data, 1)) : a.args[1]
+ x = length(a.args) == 1 ? (axes(data, 1)) : a.args[1]
seriestype := :line
- for i in 1:size(data, 2)
+ for i in axes(data, 2)
@series begin
fillrange := i > 1 ? data[:,i-1] : 0
x, data[:,i]
diff --git a/src/series.jl b/src/series.jl
index 023c7c4b..be5fc439 100644
--- a/src/series.jl
+++ b/src/series.jl
@@ -7,46 +7,76 @@
# 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}
+const MaybeNumber = Union{Number, Missing}
+const MaybeString = Union{AbstractString, Missing}
+const DataPoint = Union{MaybeNumber, MaybeString}
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)
+prepareSeriesData(f::Function) = f
+prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!(
+ x -> ismissing(x) || isinf(x) ? NaN : x,
+ map(float,a))
+prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
+prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
+prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image
+prepareSeriesData(v::Volume) = Volume(prepareSeriesData(v.v), v.x_extents, v.y_extents, v.z_extents)
# default: assume x represents a single series
-convertToAnyVector(x) = Any[prepareSeriesData(x)]
+convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)]
# fixed number of blank series
-convertToAnyVector(n::Integer) = Any[zeros(0) for i in 1:n]
+convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n]
# vector of data points is a single series
-convertToAnyVector(v::AVec{<:DataPoint}) = Any[prepareSeriesData(v)]
+convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)]
# list of things (maybe other vectors, functions, or something else)
-convertToAnyVector(v::AVec) = vcat((convertToAnyVector(vi) for vi in v)...)
+function convertToAnyVector(v::AVec, plotattributes)
+ if all(x -> x isa MaybeNumber, v)
+ convertToAnyVector(Vector{MaybeNumber}(v), plotattributes)
+ elseif all(x -> x isa MaybeString, v)
+ convertToAnyVector(Vector{MaybeString}(v), plotattributes)
+ else
+ vcat((convertToAnyVector(vi, plotattributes) for vi in v)...)
+ end
+end
# Matrix is split into columns
-convertToAnyVector(v::AMat{<:DataPoint}) = Any[prepareSeriesData(v[:,i]) for i in 1:size(v,2)]
+function convertToAnyVector(v::AMat{<:DataPoint}, plotattributes)
+ if all3D(plotattributes)
+ Any[prepareSeriesData(Surface(v))]
+ else
+ Any[prepareSeriesData(v[:, i]) for i in axes(v, 2)]
+ end
+end
+
+# --------------------------------------------------------------------
+# Fillranges & ribbons
+
+
+process_fillrange(range::Number, plotattributes) = [range]
+process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes)
+
+process_ribbon(ribbon::Number, plotattributes) = [ribbon]
+process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes)
+# ribbon as a tuple: (lower_ribbons, upper_ribbons)
+process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAnyVector(ribbon[1], plotattributes),
+ convertToAnyVector(ribbon[2], plotattributes)))
+
# --------------------------------------------------------------------
# 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::Nothing, y::Nothing, z) = axes(z,1)
+compute_x(x::Nothing, y, z) = axes(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::Nothing, y::Nothing, z) = axes(z,2)
compute_y(x, y::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y)
@@ -96,25 +126,17 @@ struct SliceIt end
z = z.data
end
- xs = convertToAnyVector(x)
- ys = convertToAnyVector(y)
- zs = convertToAnyVector(z)
+ xs = convertToAnyVector(x, plotattributes)
+ ys = convertToAnyVector(y, plotattributes)
+ zs = convertToAnyVector(z, plotattributes)
fr = pop!(plotattributes, :fillrange, nothing)
- fillranges = if typeof(fr) <: Number
- [fr]
- else
- convertToAnyVector(fr)
- end
+ fillranges = process_fillrange(fr, plotattributes)
mf = length(fillranges)
rib = pop!(plotattributes, :ribbon, nothing)
- ribbons = if typeof(rib) <: Number
- [rib]
- else
- convertToAnyVector(rib)
- end
+ ribbons = process_ribbon(rib, plotattributes)
mr = length(ribbons)
# @show zs
@@ -260,9 +282,9 @@ all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :hea
# 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)
- n,m = size(mat)
+ n,m = axes(mat)
wrap_surfaces(plotattributes)
- SliceIt, 1:m, 1:n, Surface(mat)
+ SliceIt, m, n, Surface(mat)
else
SliceIt, nothing, mat, nothing
end
@@ -272,9 +294,9 @@ end
@recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix
if all3D(plotattributes)
mat = fmt.data
- n,m = size(mat)
+ n,m = axes(mat)
wrap_surfaces(plotattributes)
- SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter)
+ SliceIt, m, n, Formatted(Surface(mat), fmt.formatter)
else
SliceIt, nothing, fmt, nothing
end
@@ -297,35 +319,35 @@ function clamp_greys!(mat::AMat{T}) where T<:Gray
end
@recipe function f(mat::AMat{T}) where T<:Gray
- n, m = size(mat)
+ n, m = axes(mat)
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
- SliceIt, 1:m, 1:n, Surface(clamp_greys!(mat))
+ SliceIt, m, n, Surface(clamp_greys!(mat))
else
seriestype := :heatmap
yflip --> true
cbar --> false
fillcolor --> ColorGradient([:black, :white])
- SliceIt, 1:m, 1:n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.))
+ SliceIt, m, n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.))
end
end
# # images - colors
@recipe function f(mat::AMat{T}) where T<:Colorant
- n, m = size(mat)
+ n, m = axes(mat)
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
- SliceIt, 1:m, 1:n, Surface(mat)
+ SliceIt, m, n, Surface(mat)
else
seriestype := :heatmap
yflip --> true
cbar --> false
z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat)
- SliceIt, 1:m, 1:n, Surface(z)
+ SliceIt, m, n, Surface(z)
end
end
@@ -344,23 +366,29 @@ end
@recipe function f(shapes::AMat{Shape})
seriestype --> :shape
- for j in 1:size(shapes,2)
+ for j in axes(shapes,2)
@series coords(vec(shapes[:,j]))
end
end
+# Dicts: each entry is a data point (x,y)=(key,value)
+@recipe f(d::AbstractDict) = collect(keys(d)), collect(values(d))
# function without range... use the current range of the x-axis
@recipe function f(f::FuncOrFuncs{F}) where F<:Function
plt = plotattributes[:plot_object]
- xmin, xmax = try
- axis_limits(plt[1], :x)
- catch
- 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])))
+ xmin, xmax = if haskey(plotattributes, :xlims)
+ plotattributes[:xlims]
+ else
+ try
+ axis_limits(plt[1], :x)
+ catch
+ 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
end
f, xmin, xmax
@@ -491,20 +519,25 @@ end
# # special handling... xmin/xmax with parametric function(s)
@recipe function f(f::Function, xmin::Number, xmax::Number)
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
- xs = _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
- xs, f
+ _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
end
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
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
+ xs = Array{Any}(undef, length(fs))
+ ys = Array{Any}(undef, length(fs))
+ for (i, (x, y)) in enumerate(_scaled_adapted_grid(f, xscale, yscale, xmin, xmax) for f in fs)
+ xs[i] = x
+ ys[i] = y
+ end
+ xs, ys
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))))
+ xs, ys = adapted_grid(yf∘f∘xinv, xf.((xmin, xmax)))
+ xinv.(xs), yinv.(ys)
end
#
@@ -550,7 +583,7 @@ end
# end
splittable_kw(key, val, lengthGroup) = false
-splittable_kw(key, val::AbstractArray, lengthGroup) = !(key in (:group, :color_palette)) && size(val,1) == lengthGroup
+splittable_kw(key, val::AbstractArray, lengthGroup) = !(key in (:group, :color_palette)) && length(axes(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)
@@ -564,7 +597,7 @@ end
function groupedvec2mat(x_ind, x, y::AbstractArray, groupby, def_val = y[1])
y_mat = Array{promote_type(eltype(y), typeof(def_val))}(undef, length(keys(x_ind)), length(groupby.groupLabels))
fill!(y_mat, def_val)
- for i in 1:length(groupby.groupLabels)
+ for i in eachindex(groupby.groupLabels)
xi = x[groupby.groupIds[i]]
yi = y[groupby.groupIds[i]]
y_mat[getindex.(Ref(x_ind), xi), i] = yi
@@ -597,7 +630,7 @@ group_as_matrix(t) = false
if length(g.args) == 1
x = zeros(Int, lengthGroup)
for indexes in groupby.groupIds
- x[indexes] = 1:length(indexes)
+ x[indexes] = eachindex(indexes)
end
last_args = g.args
else
@@ -605,7 +638,7 @@ group_as_matrix(t) = false
last_args = g.args[2:end]
end
x_u = unique(sort(x))
- x_ind = Dict(zip(x_u, 1:length(x_u)))
+ x_ind = Dict(zip(x_u, eachindex(x_u)))
for (key,val) in plotattributes
if splittable_kw(key, val, lengthGroup)
:($key) := groupedvec2mat(x_ind, x, val, groupby)
diff --git a/src/themes.jl b/src/themes.jl
index 592d0a78..4f47039b 100644
--- a/src/themes.jl
+++ b/src/themes.jl
@@ -4,39 +4,19 @@
Specify the colour theme for plots.
"""
function theme(s::Symbol; kw...)
- defaults = _get_defaults(s)
+ defaults = copy(PlotThemes._themes[s].defaults)
_theme(s, defaults; kw...)
end
-function _get_defaults(s::Symbol)
- thm = PlotThemes._themes[s]
- if :defaults in fieldnames(typeof(thm))
- return thm.defaults
- else # old PlotTheme type
- defaults = KW(
- :bg => thm.bg_secondary,
- :bginside => thm.bg_primary,
- :fg => thm.lines,
- :fgtext => thm.text,
- :fgguide => thm.text,
- :fglegend => thm.text,
- :palette => thm.palette,
- )
- if thm.gradient != nothing
- push!(defaults, :gradient => thm.gradient)
- end
- return defaults
- end
-end
-
function _theme(s::Symbol, defaults::KW; kw...)
# Reset to defaults to overwrite active theme
reset_defaults()
# Set the theme's gradient as default
- if haskey(defaults, :gradient)
+ if haskey(defaults, :colorgradient)
PlotUtils.clibrary(:misc)
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
+ pop!(defaults, :colorgradient)
else
PlotUtils.clibrary(:Plots)
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
@@ -44,8 +24,8 @@ function _theme(s::Symbol, defaults::KW; kw...)
# maybe overwrite the theme's gradient
kw = KW(kw)
- if haskey(kw, :gradient)
- kwgrad = pop!(kw, :gradient)
+ if haskey(kw, :colorgradient)
+ kwgrad = pop!(kw, :colorgradient)
for clib in clibraries()
if kwgrad in cgradients(clib)
PlotUtils.clibrary(clib)
@@ -74,11 +54,11 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
@recipe function showtheme(st::ShowTheme)
thm, cfunc = _get_showtheme_args(st.args...)
- defaults = _get_defaults(thm)
+ defaults = PlotThemes._themes[thm].defaults
# get the gradient
- gradient_colors = get(defaults, :gradient, cgrad(:inferno).colors)
- gradient = cgrad(cfunc.(RGB.(gradient_colors)))
+ gradient_colors = get(defaults, :colorgradient, cgrad(:inferno).colors)
+ colorgradient = cgrad(cfunc.(RGB.(gradient_colors)))
# get the palette
palette = get(defaults, :palette, get_color_palette(:auto, plot_color(:white), 17))
@@ -86,7 +66,7 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
# apply the theme
for k in keys(defaults)
- k in (:gradient, :palette) && continue
+ k in (:colorgradient, :palette) && continue
def = defaults[k]
arg = get(_keyAliases, k, k)
plotattributes[arg] = if typeof(def) <: Colorant
@@ -139,27 +119,30 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
@series begin
subplot := 4
seriestype := :heatmap
- seriescolor := gradient
- ticks := -5:5:5
+ seriescolor := colorgradient
+ xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
+ yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
x, y, z
end
@series begin
subplot := 5
seriestype := :surface
- seriescolor := gradient
+ seriescolor := colorgradient
+ xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
+ yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
x, y, z
end
n = 100
ts = range(0, stop = 10π, length = n)
- x = ts .* cos.(ts)
+ x = (0.1ts) .* cos.(ts)
y = (0.1ts) .* sin.(ts)
z = 1:n
@series begin
subplot := 6
- seriescolor := gradient
+ seriescolor := colorgradient
linewidth := 3
line_z := z
x, y, z
diff --git a/src/utils.jl b/src/utils.jl
index 666c878d..04ec2cae 100644
--- a/src/utils.jl
+++ b/src/utils.jl
@@ -26,7 +26,7 @@ function histogramHack(; kw...)
plotattributes[:x] = midpoints
plotattributes[:y] = float(counts)
plotattributes[:seriestype] = :bar
- plotattributes[:fillrange] = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
+ plotattributes[:fillrange] = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
plotattributes
end
@@ -38,12 +38,12 @@ function barHack(; kw...)
plotattributes = KW(kw)
midpoints = plotattributes[:x]
heights = plotattributes[:y]
- fillrange = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
+ fillrange = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
# estimate the edges
dists = diff(midpoints) * 0.5
edges = zeros(length(midpoints)+1)
- for i in 1:length(edges)
+ for i in eachindex(edges)
if i == 1
edge = midpoints[1] - dists[1]
elseif i == length(edges)
@@ -56,7 +56,7 @@ function barHack(; kw...)
x = Float64[]
y = Float64[]
- for i in 1:length(heights)
+ for i in eachindex(heights)
e1, e2 = edges[i:i+1]
append!(x, [e1, e1, e2, e2])
append!(y, [fillrange, heights[i], heights[i], fillrange])
@@ -81,7 +81,7 @@ function sticksHack(; kw...)
# these are the line vertices
x = Float64[]
y = Float64[]
- fillrange = plotattributesLine[:fillrange] == nothing ? 0.0 : plotattributesLine[:fillrange]
+ fillrange = plotattributesLine[:fillrange] === nothing ? 0.0 : plotattributesLine[:fillrange]
# calculate the vertices
yScatter = plotattributesScatter[:y]
@@ -115,7 +115,6 @@ function regressionXY(x, y)
end
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
- @show T, size(z)
n, m = size(z)
# idx = 0
colors = ColorGradient(vec(z))
@@ -146,16 +145,18 @@ end
Segments() = Segments(Float64)
Segments(::Type{T}) where {T} = Segments(T[])
-Segments(p::Int) = Segments(NTuple{2,Float64}[])
+Segments(p::Int) = Segments(NTuple{p, Float64}[])
# Segments() = Segments(zeros(0))
to_nan(::Type{Float64}) = NaN
to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
+to_nan(::Type{NTuple{3,Float64}}) = (NaN, NaN, NaN)
coords(segs::Segments{Float64}) = segs.pts
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
+coords(segs::Segments{NTuple{3,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts], Float64[p[3] for p in segs.pts]
function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts)
@@ -183,24 +184,26 @@ end
mutable struct SegmentsIterator
args::Tuple
- n::Int
+ n1::Int
+ n2::Int
end
function iter_segments(args...)
tup = Plots.wraptuple(args)
- n = maximum(map(length, tup))
- SegmentsIterator(tup, n)
+ n1 = minimum(map(firstindex, tup))
+ n2 = maximum(map(lastindex, tup))
+ SegmentsIterator(tup, n1, n2)
end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
- if x == nothing
+ 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)]
+ return [[i] for i in eachindex(y)]
else
- return [i:(i + 1) for i in 1:(length(y) - 1)]
+ return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
end
else
segs = UnitRange{Int}[]
@@ -218,13 +221,13 @@ 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)
- i = findfirst(!anynan(itr.args), nextidx:itr.n)
+function Base.iterate(itr::SegmentsIterator, nextidx::Int = itr.n1)
+ i = findfirst(!anynan(itr.args), nextidx:itr.n2)
i === nothing && return nothing
nextval = nextidx + i - 1
- j = findfirst(anynan(itr.args), nextval:itr.n)
- nextnan = j === nothing ? itr.n + 1 : nextval + j - 1
+ j = findfirst(anynan(itr.args), nextval:itr.n2)
+ nextnan = j === nothing ? itr.n2 + 1 : nextval + j - 1
nextval:nextnan-1, nextnan
end
@@ -343,8 +346,11 @@ const _scale_base = Dict{Symbol, Real}(
:ln => ℯ,
)
-function _heatmap_edges(v::AVec)
+function _heatmap_edges(v::AVec, isedges::Bool = false)
length(v) == 1 && return v[1] .+ [-0.5, 0.5]
+ if isedges return v end
+ # `isedges = true` means that v is a vector which already describes edges
+ # and does not need to be extended.
vmin, vmax = ignorenan_extrema(v)
extra_min = (v[2] - v[1]) / 2
extra_max = (v[end] - v[end - 1]) / 2
@@ -352,9 +358,30 @@ function _heatmap_edges(v::AVec)
end
"create an (n+1) list of the outsides of heatmap rectangles"
-function heatmap_edges(v::AVec, scale::Symbol = :identity)
+function heatmap_edges(v::AVec, scale::Symbol = :identity, isedges::Bool = false)
f, invf = scalefunc(scale), invscalefunc(scale)
- map(invf, _heatmap_edges(map(f,v)))
+ map(invf, _heatmap_edges(map(f,v), isedges))
+end
+
+function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size::Tuple{Int, Int})
+ nx, ny = length(x), length(y)
+ # ismidpoints = z_size == (ny, nx) # This fails some tests, but would actually be
+ # the correct check, since (4, 3) != (3, 4) and a missleading plot is produced.
+ ismidpoints = prod(z_size) == (ny * nx)
+ isedges = z_size == (ny - 1, nx - 1)
+ if !ismidpoints && !isedges
+ error("""Length of x & y does not match the size of z.
+ Must be either `size(z) == (length(y), length(x))` (x & y define midpoints)
+ or `size(z) == (length(y)+1, length(x)+1))` (x & y define edges).""")
+ end
+ x, y = heatmap_edges(x, xscale, isedges),
+ heatmap_edges(y, yscale, isedges)
+ return x, y
+end
+
+function is_uniformly_spaced(v; tol=1e-6)
+ dv = diff(v)
+ maximum(dv) - minimum(dv) < tol * mean(abs.(dv))
end
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
@@ -478,7 +505,7 @@ function make_fillrange_from_ribbon(kw::KW)
rib1, rib2 = -first(rib), last(rib)
# kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2)
- (get(kw, :fillalpha, nothing) == nothing) && (kw[:fillalpha] = 0.5)
+ (get(kw, :fillalpha, nothing) === nothing) && (kw[:fillalpha] = 0.5)
end
#turn tuple of fillranges to one path
@@ -524,14 +551,9 @@ zlims(sp_idx::Int = 1) = zlims(current(), sp_idx)
function get_clims(sp::Subplot)
zmin, zmax = Inf, -Inf
- 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) <: Union{Missing, Real})
- zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
- elseif (vals != nothing) && (eltype(vals) <: Union{Missing, Real})
- zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
- end
+ if series[:colorbar_entry]
+ zmin, zmax = _update_clims(zmin, zmax, get_clims(series)...)
end
end
clims = sp[:clims]
@@ -539,10 +561,37 @@ function get_clims(sp::Subplot)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
end
- return zmin < zmax ? (zmin, zmax) : (-0.1, 0.1)
+ return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
-_update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
+function get_clims(sp::Subplot, series::Series)
+ zmin, zmax = if series[:colorbar_entry]
+ get_clims(sp)
+ else
+ get_clims(series)
+ end
+ clims = sp[:clims]
+ if is_2tuple(clims)
+ isfinite(clims[1]) && (zmin = clims[1])
+ isfinite(clims[2]) && (zmax = clims[2])
+ end
+ return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
+end
+
+function get_clims(series::Series)
+ zmin, zmax = Inf, -Inf
+ z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface)
+ for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
+ if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real})
+ zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
+ elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
+ zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
+ end
+ end
+ return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
+end
+
+_update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax)
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
@@ -602,7 +651,7 @@ for comp in (:line, :fill, :marker)
function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
c = series[$Symbol($compcolor)]
z = series[$Symbol($comp_z)]
- if z == nothing
+ if z === nothing
isa(c, ColorGradient) ? c : plot_color(_cycle(c, i))
else
grad = isa(c, ColorGradient) ? c : cgrad()
@@ -613,7 +662,7 @@ for comp in (:line, :fill, :marker)
$get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1)
- if series[$Symbol($comp_z)] == nothing
+ if series[$Symbol($comp_z)] === nothing
$get_compcolor(series, 0, 1, i)
else
$get_compcolor(series, get_clims(series[:subplot]), i)
@@ -650,11 +699,11 @@ function has_attribute_segments(series::Series)
for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and
# SegmentsIterator is used
- series[letter] != nothing && NaN in collect(series[letter]) && return false
+ series[letter] !== nothing && NaN in collect(series[letter]) && return false
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 for attr in (:line_z, :fill_z, :marker_z))
+ return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :linestyle, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z))
end
# ---------------------------------------------------------------
@@ -1060,6 +1109,15 @@ legendfont(sp::Subplot) = font(
sp[:legendfontcolor],
)
+legendtitlefont(sp::Subplot) = font(
+ sp[:legendtitlefontfamily],
+ sp[:legendtitlefontsize],
+ sp[:legendtitlefontvalign],
+ sp[:legendtitlefonthalign],
+ sp[:legendtitlefontrotation],
+ sp[:legendtitlefontcolor],
+)
+
tickfont(ax::Axis) = font(
ax[:tickfontfamily],
ax[:tickfontsize],
@@ -1106,20 +1164,20 @@ function convert_sci_unicode(label::AbstractString)
label
end
-function straightline_data(series)
+function straightline_data(series, expansion_factor = 1)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
n = length(x)
if n == 2
- return straightline_data(xl, yl, x, y)
+ return straightline_data(xl, yl, x, y, expansion_factor)
else
k, r = divrem(n, 3)
if r == 0
xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k
inds = (3 * i - 2):(3 * i - 1)
- xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds])
+ xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds], expansion_factor)
end
return xdata, ydata
else
@@ -1128,7 +1186,7 @@ function straightline_data(series)
end
end
-function straightline_data(xl, yl, x, y)
+function straightline_data(xl, yl, x, y, expansion_factor = 1)
x_vals, y_vals = if y[1] == y[2]
if x[1] == x[2]
error("Two identical points cannot be used to describe a straight line.")
@@ -1149,29 +1207,28 @@ function straightline_data(xl, yl, x, y)
end
# expand the data outside the axis limits, by a certain factor too improve
# plotly(js) and interactive behaviour
- factor = 100
- x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* factor .* [-1, 1]
- y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* factor .* [-1, 1]
+ x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* expansion_factor .* [-1, 1]
+ y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* expansion_factor .* [-1, 1]
return x_vals, y_vals
end
-function shape_data(series)
+function shape_data(series, expansion_factor = 1)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
factor = 100
for i in eachindex(x)
if x[i] == -Inf
- x[i] = xl[1] - factor * (xl[2] - xl[1])
+ x[i] = xl[1] - expansion_factor * (xl[2] - xl[1])
elseif x[i] == Inf
- x[i] = xl[2] + factor * (xl[2] - xl[1])
+ x[i] = xl[2] + expansion_factor * (xl[2] - xl[1])
end
end
for i in eachindex(y)
if y[i] == -Inf
- y[i] = yl[1] - factor * (yl[2] - yl[1])
+ y[i] = yl[1] - expansion_factor * (yl[2] - yl[1])
elseif y[i] == Inf
- y[i] = yl[2] + factor * (yl[2] - yl[1])
+ y[i] = yl[2] + expansion_factor * (yl[2] - yl[1])
end
end
return x, y
diff --git a/test/imgcomp.jl b/test/imgcomp.jl
index 206b8d50..e7151573 100644
--- a/test/imgcomp.jl
+++ b/test/imgcomp.jl
@@ -1,34 +1,6 @@
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)
+function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = !is_ci(), sigma = [1,1], tol = 1e-2)
Plots._debugMode.on = debug
example = Plots._examples[idx]
Plots.theme(:default)
@@ -39,36 +11,9 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
# ensure consistent results
Random.seed!(1234)
- # reference image directory setup
- refdir = joinpath(ref_image_dir, "Plots", string(pkg))
fn = "ref$idx.png"
-
- # firgure out version info
- vns = filter(x->x[1] != '.', readdir(refdir))
- versions = sort(VersionNumber.(vns), rev = true)
- versions = filter(v -> v <= _current_plots_version, versions)
- # @show refdir fn versions
-
- newdir = joinpath(refdir, string(_current_plots_version))
- newfn = joinpath(newdir, fn)
-
- # figure out which reference file we should compare to, by finding the highest versioned file
- reffn = nothing
- for v in versions
- tmpfn = joinpath(refdir, string(v), fn)
- if isfile(tmpfn)
- reffn = tmpfn
- break
- end
- end
-
- # now we have the fn (if any)... do the comparison
- # @show reffn
- if reffn == nothing
- reffn = newfn
- end
- # @show reffn
- # return
+ reffn = reference_file(pkg, idx, _current_plots_version)
+ newfn = joinpath(reference_path(pkg, _current_plots_version), fn)
# test function
func = (fn, idx) -> begin
@@ -78,13 +23,6 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
png(fn)
end
- # try
- # run(`mkdir -p $newdir`)
- # catch err
- # display(err)
- # end
- # # reffn = joinpath(refdir, "ref$idx.png")
-
# the test
vtest = VisualTest(func, reffn, idx)
test_images(vtest, popup=popup, sigma=sigma, tol=tol, newfn = newfn)
@@ -98,7 +36,7 @@ function image_comparison_facts(pkg::Symbol;
tol = 1e-2) # acceptable error (percent)
for i in 1:length(Plots._examples)
i in skip && continue
- if only == nothing || i in only
+ if only === nothing || i in only
@test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, tol=tol) |> success == true
end
end
diff --git a/test/runtests.jl b/test/runtests.jl
index 0b73b148..16ad485f 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -1,40 +1,74 @@
+import ImageMagick
using VisualRegressionTests
using Plots
using Random
-using BinaryProvider
using Test
using FileIO
+using Gtk
+using LibGit2
using GeometryTypes
+include("test_pgfplotsx.jl")
+
+reference_dir(args...) = joinpath(homedir(), ".julia", "dev", "PlotReferenceImages", args...)
+
+function reference_file(backend, i, version)
+ refdir = reference_dir("Plots", string(backend))
+ fn = "ref$i.png"
+ versions = sort(VersionNumber.(readdir(refdir)), rev = true)
+
+ reffn = joinpath(refdir, string(version), fn)
+ for v in versions
+ tmpfn = joinpath(refdir, string(v), fn)
+ if isfile(tmpfn)
+ reffn = tmpfn
+ break
+ end
+ end
+
+ return reffn
+end
+
+reference_path(backend, version) = reference_dir("Plots", string(backend), string(version))
+
+if !isdir(reference_dir())
+ mkpath(reference_dir())
+ LibGit2.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git", reference_dir())
+end
+
include("imgcomp.jl")
# don't actually show the plots
Random.seed!(1234)
default(show=false, reuse=true)
-img_tol = isinteractive() ? 1e-2 : 10e-2
+is_ci() = get(ENV, "CI", "false") == "true"
+img_tol = is_ci() ? 10e-2 : 10e-2
-@testset "GR" begin
- ENV["PLOTS_TEST"] = "true"
- ENV["GKSwstype"] = "100"
- @test gr() == Plots.GRBackend()
- @test backend() == Plots.GRBackend()
+@testset "Backends" begin
- @static if Sys.islinux()
- image_comparison_facts(:gr, tol=img_tol, skip = [25, 30])
+ @testset "GR" begin
+ ENV["PLOTS_TEST"] = "true"
+ ENV["GKSwstype"] = "100"
+ @test gr() == Plots.GRBackend()
+ @test backend() == Plots.GRBackend()
+
+ @static if Sys.islinux()
+ image_comparison_facts(:gr, tol=img_tol, skip = Plots._backend_skips[:gr])
+ end
end
-end
+ @testset "UnicodePlots" begin
+ @test unicodeplots() == Plots.UnicodePlotsBackend()
+ @test backend() == Plots.UnicodePlotsBackend()
-@testset "UnicodePlots" begin
- @test unicodeplots() == Plots.UnicodePlotsBackend()
- @test backend() == Plots.UnicodePlotsBackend()
+ # lets just make sure it runs without error
+ 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
- # lets just make sure it runs without error
- 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
@testset "Axes" begin
@@ -61,6 +95,14 @@ end
for plt in plots
display(plt)
end
+ @test_nowarn plot(x->x^2,0,2)
+end
+
+@testset "EmptyAnim" begin
+ anim = @animate for i in []
+ end
+
+ @test_throws ArgumentError gif(anim)
end
@testset "Segments" begin
@@ -90,6 +132,6 @@ end
[(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)
+ @test isequal(collect(zip(Plots.unzip(GeometryTypes.Point.(z))...)), z)
end
end
diff --git a/test/test_pgfplotsx.jl b/test/test_pgfplotsx.jl
new file mode 100644
index 00000000..91456fe3
--- /dev/null
+++ b/test/test_pgfplotsx.jl
@@ -0,0 +1,166 @@
+using Plots, Test
+pgfplotsx()
+
+function create_plot( args...; kwargs... )
+ pgfx_plot = plot(args...; kwargs...)
+ return pgfx_plot, repr("application/x-tex", pgfx_plot)
+end
+
+function create_plot!( args...; kwargs... )
+ pgfx_plot = plot!(args...; kwargs...)
+ return pgfx_plot, repr("application/x-tex", pgfx_plot)
+end
+
+@testset "PGFPlotsX" begin
+ pgfx_plot = plot(1:5)
+ Plots._update_plot_object(pgfx_plot)
+ @test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument
+ @test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing
+ axis = Plots.pgfx_axes(pgfx_plot.o)[1]
+ @test count( x-> x isa PGFPlotsX.Plot, axis.contents ) == 1
+ @test !haskey(axis.contents[1].options.dict, "fill")
+
+ @testset "3D docs example" begin
+ n = 100
+ ts = range(0, stop=8π, length=n)
+ x = ts .* map(cos, ts)
+ y = (0.1ts) .* map(sin, ts)
+ z = 1:n
+ pl = plot(x, y, z, zcolor=reverse(z), m=(10, 0.8, :blues, Plots.stroke(0)), leg=false, cbar=true, w=5)
+ pgfx_plot = plot!(pl, zeros(n), zeros(n), 1:n, w=10)
+ Plots._update_plot_object(pgfx_plot)
+ if @test_nowarn(haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true)
+ @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing
+ end
+ end # testset
+ @testset "Color docs example" begin
+ y = rand(100)
+ plot(0:10:100, rand(11, 4), lab="lines", w=3, palette=:grays, fill=0, α=0.6)
+ pl = scatter!(y, zcolor=abs.(y .- 0.5), m=(:heat, 0.8, Plots.stroke(1, :green)), ms=10 * abs.(y .- 0.5) .+ 4, lab="grad")
+ Plots._update_plot_object(pl)
+ axis = Plots.pgfx_axes(pl.o)[1]
+ @test count( x->x isa PGFPlotsX.LegendEntry, axis.contents ) == 5
+ @test count( x->x isa PGFPlotsX.Plot, axis.contents ) == 108 # each marker is its own plot, fillranges create 2 plot-objects
+ marker = axis.contents[15]
+ @test marker isa PGFPlotsX.Plot
+ @test marker.options["mark"] == "*"
+ @test marker.options["mark options"]["color"] == RGBA{Float64}( colorant"green", 0.8)
+ @test marker.options["mark options"]["line width"] == 1
+ end # testset
+ @testset "Plot in pieces" begin
+ plot(rand(100) / 3, reg=true, fill=(0, :green))
+ scatter!(rand(100), markersize=6, c=:orange)
+ end # testset
+ @testset "Marker types" begin
+ markers = filter((m->begin
+ m in Plots.supported_markers()
+ end), Plots._shape_keys)
+ markers = reshape(markers, 1, length(markers))
+ n = length(markers)
+ x = (range(0, stop=10, length=n + 2))[2:end - 1]
+ y = repeat(reshape(reverse(x), 1, :), n, 1)
+ scatter(x, y, m=(8, :auto), lab=map(string, markers), bg=:linen, xlim=(0, 10), ylim=(0, 10))
+ end # testset
+ @testset "Layout" begin
+ plot(Plots.fakedata(100, 10), layout=4, palette=[:grays :blues :heat :lightrainbow], bg_inside=[:orange :pink :darkblue :black])
+ end # testset
+ @testset "Polar plots" begin
+ Θ = range(0, stop=1.5π, length=100)
+ r = abs.(0.1 * randn(100) + sin.(3Θ))
+ plot(Θ, r, proj=:polar, m=2)
+ end # testset
+ @testset "Drawing shapes" begin
+ verts = [(-1.0, 1.0), (-1.28, 0.6), (-0.2, -1.4), (0.2, -1.4), (1.28, 0.6), (1.0, 1.0), (-1.0, 1.0), (-0.2, -0.6), (0.0, -0.2), (-0.4, 0.6), (1.28, 0.6), (0.2, -1.4), (-0.2, -1.4), (0.6, 0.2), (-0.2, 0.2), (0.0, -0.2), (0.2, 0.2), (-0.2, -0.6)]
+ x = 0.1:0.2:0.9
+ y = 0.7 * rand(5) .+ 0.15
+ plot(x, y, line=(3, :dash, :lightblue), marker=(Shape(verts), 30, RGBA(0, 0, 0, 0.2)), bg=:pink, fg=:darkblue, xlim=(0, 1), ylim=(0, 1), leg=false)
+ end # testset
+ @testset "Histogram 2D" begin
+ histogram2d(randn(10000), randn(10000), nbins=20)
+ end # testset
+ @testset "Heatmap-like" begin
+ xs = [string("x", i) for i = 1:10]
+ ys = [string("y", i) for i = 1:4]
+ z = float((1:4) * reshape(1:10, 1, :))
+ pgfx_plot = heatmap(xs, ys, z, aspect_ratio=1)
+ Plots._update_plot_object(pgfx_plot)
+ if @test_nowarn(haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true)
+ @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing
+ @test Plots.pgfx_axes(pgfx_plot.o)[1]["colormap name"] == "plots1"
+ end
+
+ pgfx_plot = wireframe(xs, ys, z, aspect_ratio=1)
+ # TODO: clims are wrong
+ end # testset
+ @testset "Contours" begin
+ x = 1:0.5:20
+ y = 1:0.5:10
+ f(x, y) = begin
+ (3x + y ^ 2) * abs(sin(x) + cos(y))
+ end
+ X = repeat(reshape(x, 1, :), length(y), 1)
+ Y = repeat(y, 1, length(x))
+ Z = map(f, X, Y)
+ p2 = contour(x, y, Z)
+ p1 = contour(x, y, f, fill=true)
+ plot(p1, p2)
+ # TODO: colorbar for filled contours
+ end # testset
+ @testset "Varying colors" begin
+ t = range(0, stop=1, length=100)
+ θ = (6π) .* t
+ x = t .* cos.(θ)
+ y = t .* sin.(θ)
+ p1 = plot(x, y, line_z=t, linewidth=3, legend=false)
+ p2 = scatter(x, y, marker_z=((x, y)->begin
+ x + y
+ end), color=:bluesreds, legend=false)
+ plot(p1, p2)
+ end # testset
+ @testset "Framestyles" begin
+ scatter(fill(randn(10), 6), fill(randn(10), 6), framestyle=[:box :semi :origin :zerolines :grid :none], title=[":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], color=permutedims(1:6), layout=6, label="", markerstrokewidth=0, ticks=-2:2)
+ # TODO: support :semi
+ end # testset
+ @testset "Quiver" begin
+ x = -2pi:0.2:2*pi
+ y = sin.(x)
+
+ u = ones(length(x))
+ v = cos.(x)
+ arrow_plot = plot( x, y, quiver = (u, v), arrow = true )
+ # TODO: could adjust limits to fit arrows if too long, but how?
+ # TODO: get latex available on CI
+ # mktempdir() do path
+ # @test_nowarn savefig(arrow_plot, path*"arrow.pdf")
+ # end
+ end # testset
+ @testset "Annotations" begin
+ y = rand(10)
+ plot(y, annotations=(3, y[3], Plots.text("this is \\#3", :left)), leg=false)
+ annotate!([(5, y[5], Plots.text("this is \\#5", 16, :red, :center)), (10, y[10], Plots.text("this is \\#10", :right, 20, "courier"))])
+ annotation_plot = scatter!(range(2, stop=8, length=6), rand(6), marker=(50, 0.2, :orange), series_annotations=["series", "annotations", "map", "to", "series", Plots.text("data", :green)])
+ # mktempdir() do path
+ # @test_nowarn savefig(annotation_plot, path*"annotation.pdf")
+ # end
+ end # testset
+ @testset "Ribbon" begin
+ aa = rand(10)
+ bb = rand(10)
+ cc = rand(10)
+ conf = [aa-cc bb-cc]
+ ribbon_plot = plot(collect(1:10),fill(1,10), ribbon=(conf[:,1],conf[:,2]))
+ Plots._update_plot_object(ribbon_plot)
+ axis = Plots.pgfx_axes(ribbon_plot.o)[1]
+ plots = filter(x->x isa PGFPlotsX.Plot, axis.contents)
+ @test length(plots) == 4
+ @test !haskey(plots[1].options.dict, "fill")
+ @test !haskey(plots[2].options.dict, "fill")
+ @test !haskey(plots[3].options.dict, "fill")
+ @test haskey(plots[4].options.dict, "fill")
+ @test ribbon_plot.o !== nothing
+ @test ribbon_plot.o.the_plot !== nothing
+ # mktempdir() do path
+ # @test_nowarn savefig(ribbon_plot, path*"ribbon.svg")
+ # end
+ end # testset
+ end # testset