Merge branch 'master' into plotly_autoresize

This commit is contained in:
Nathan Daly 2019-12-31 13:40:51 -05:00
commit 4a3160da29
37 changed files with 3708 additions and 797 deletions

24
.github/workflows/CompatHelper.yml vendored Normal file
View File

@ -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()'

View File

@ -4,13 +4,22 @@ os:
- linux - linux
# - osx # - osx
julia: julia:
- 1.1 - 1
- 1.2
- nightly - nightly
matrix: matrix:
allow_failures: allow_failures:
- julia: nightly - julia: nightly
addons:
apt:
packages:
- at-spi2-core
- libgtk-3-dev
- xauth
- xvfb
sudo: required sudo: required
before_install: before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi
@ -18,3 +27,8 @@ before_install:
notifications: notifications:
email: true 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)'

36
NEWS.md
View File

@ -3,14 +3,38 @@
#### notes on release changes, ongoing development, and future planned work #### 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) ## (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 ## 0.26.0
- use FFMPEG.jl - use FFMPEG.jl
- add missing method for convertToAnyVector - add missing method for convertToAnyVector

View File

@ -1,7 +1,7 @@
name = "Plots" name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"] author = ["Tom Breloff (@tbreloff)"]
version = "0.26.0" version = "0.28.4"
[deps] [deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@ -31,27 +31,39 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat] [compat]
FixedPointNumbers = "≥ 0.3.0" Contour = "0.5"
GR = "≥ 0.31.0" FFMPEG = "0.2"
PlotThemes = "≥ 0.1.3" FixedPointNumbers = "0.6, 0.7"
PlotUtils = "≥ 0.4.1" GR = "0.44"
RecipesBase = "≥ 0.6.0" GeometryTypes = "0.7"
StatsBase = "≥ 0.14.0" JSON = "0.21"
julia = "≥ 1.0.0" 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] [extras]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" 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" RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
[targets] [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"]

View File

@ -2,6 +2,7 @@ environment:
matrix: matrix:
# - julia_version: 0.7 # - julia_version: 0.7
- julia_version: 1 - julia_version: 1
- julia_version: 1.2
- julia_version: nightly - julia_version: nightly
platform: platform:

51
deps/generateprecompiles.jl vendored Normal file
View File

@ -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)

View File

@ -1,4 +0,0 @@
git checkout master
git merge --ff-only dev
git push origin master
git checkout dev

View File

@ -1,6 +1,6 @@
module Plots 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 using Reexport
@ -222,4 +222,7 @@ end
const CURRENT_BACKEND = CurrentBackend(:none) const CURRENT_BACKEND = CurrentBackend(:none)
include("precompile.jl")
_precompile_()
end # module end # module

View File

@ -60,31 +60,39 @@ end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end] file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...) gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...) mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, 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; is_animated_gif::Bool=true;
fps::Integer = 20, loop::Integer = 0, fps::Real = 20, loop::Integer = 0,
variable_palette::Bool=false, variable_palette::Bool=false,
show_msg::Bool=true) 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 is_animated_gif
if variable_palette if variable_palette
# generate a colorpalette for each frame for highest quality, but larger filesize # generate a colorpalette for each frame for highest quality, but larger filesize
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1" 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 else
# generate a colorpalette first so ffmpeg does not have to guess it # 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"`) 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 # 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 end
else 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 end
show_msg && @info("Saved animation to ", fn) show_msg && @info("Saved animation to ", fn)
@ -96,13 +104,18 @@ end
# write out html to view the gif # write out html to view the gif
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
ext = file_extension(agif.filename) ext = file_extension(agif.filename)
write(io, if ext == "gif" if ext == "gif"
"<img src=\"$(relpath(agif.filename))\" />" html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />"
elseif ext in ("mov", "mp4") elseif ext in ("mov", "mp4")
"<video controls><source src=\"$(relpath(agif.filename)) type=\"video/$ext\"></video>" mimetype = ext == "mov" ? "video/quicktime" : "video/mp4"
html = "<video controls><source src=\"data:$mimetype;base64," *
base64encode(read(agif.filename)) *
"\" type = \"$mimetype\"></video>"
else else
error("Cannot show animation with extension $ext: $agif") error("Cannot show animation with extension $ext: $agif")
end) end
write(io, html)
return nothing return nothing
end end

View File

@ -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.", :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).", :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.", :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.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:contour_labels => "Bool. Show labels at the contour lines?", :contour_labels => "Bool. Show labels at the contour lines?",
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.", :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`.",
@ -95,9 +96,16 @@ const _arg_desc = KW(
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center", :legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries", :legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color 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)", :colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.", :clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.", :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.", :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'", :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.", :aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.",

View File

@ -272,6 +272,7 @@ const _series_defaults = KW(
:arrow => nothing, # allows for adding arrows to line/path... call `arrow(args...)` :arrow => nothing, # allows for adding arrows to line/path... call `arrow(args...)`
:normalize => false, # do we want a normalized histogram? :normalize => false, # do we want a normalized histogram?
:weights => nothing, # optional weights for histograms (1D and 2D) :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 :contours => false, # add contours to 3d surface and wireframe plots
:contour_labels => false, :contour_labels => false,
:match_dimensions => false, # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196 :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, :legendfontvalign => :vcenter,
:legendfontrotation => 0.0, :legendfontrotation => 0.0,
:legendfontcolor => :match, :legendfontcolor => :match,
:legendtitlefontfamily => :match,
:legendtitlefontsize => 11,
:legendtitlefonthalign => :hcenter,
:legendtitlefontvalign => :vcenter,
:legendtitlefontrotation => 0.0,
:legendtitlefontcolor => :match,
:annotations => [], # annotation tuples... list of (x,y,annotation) :annotations => [], # annotation tuples... list of (x,y,annotation)
:projection => :none, # can also be :polar or :3d :projection => :none, # can also be :polar or :3d
:aspect_ratio => :none, # choose from :none or :equal :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 # to be able to reset font sizes to initial values
const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize], const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize], :legendfontsize => _subplot_defaults[:legendfontsize],
:legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:tickfontsize => _axis_defaults[:tickfontsize], :tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize]) :guidefontsize => _axis_defaults[:guidefontsize])
@ -574,6 +582,7 @@ add_aliases(:xerror, :xerr, :xerrorbar)
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar) add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield) add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized) 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(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
add_aliases(:match_dimensions, :transpose, :transpose_z) add_aliases(:match_dimensions, :transpose, :transpose_z)
add_aliases(:subplot, :sp, :subplt, :splt) add_aliases(:subplot, :sp, :subplt, :splt)
@ -685,15 +694,15 @@ function processLineArg(plotattributes::KW, arg)
plotattributes[:linestyle] = arg plotattributes[:linestyle] = arg
elseif typeof(arg) <: Stroke elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[:linewidth] = arg.width) arg.width === nothing || (plotattributes[:linewidth] = arg.width)
arg.color == nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color)) arg.color === nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:linealpha] = arg.alpha) arg.alpha === nothing || (plotattributes[:linealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:linestyle] = arg.style) arg.style === nothing || (plotattributes[:linestyle] = arg.style)
elseif typeof(arg) <: Brush elseif typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:fillrange] = arg.size) arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color)) arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha) arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows) elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows)
plotattributes[:arrow] = arg plotattributes[:arrow] = arg
@ -724,15 +733,15 @@ function processMarkerArg(plotattributes::KW, arg)
plotattributes[:markerstrokestyle] = arg plotattributes[:markerstrokestyle] = arg
elseif typeof(arg) <: Stroke elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[:markerstrokewidth] = arg.width) arg.width === nothing || (plotattributes[:markerstrokewidth] = arg.width)
arg.color == nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color)) arg.color === nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markerstrokealpha] = arg.alpha) arg.alpha === nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:markerstrokestyle] = arg.style) arg.style === nothing || (plotattributes[:markerstrokestyle] = arg.style)
elseif typeof(arg) <: Brush elseif typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:markersize] = arg.size) arg.size === nothing || (plotattributes[:markersize] = arg.size)
arg.color == nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color)) arg.color === nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markeralpha] = arg.alpha) arg.alpha === nothing || (plotattributes[:markeralpha] = arg.alpha)
# linealpha # linealpha
elseif allAlphas(arg) elseif allAlphas(arg)
@ -757,9 +766,9 @@ end
function processFillArg(plotattributes::KW, arg) function processFillArg(plotattributes::KW, arg)
# fr = get(plotattributes, :fillrange, 0) # fr = get(plotattributes, :fillrange, 0)
if typeof(arg) <: Brush if typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:fillrange] = arg.size) arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color)) arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha) arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Bool elseif typeof(arg) <: Bool
plotattributes[:fillrange] = arg ? 0 : nothing plotattributes[:fillrange] = arg ? 0 : nothing
@ -793,10 +802,10 @@ function processGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :gridstyle)] = arg plotattributes[Symbol(letter, :gridstyle)] = arg
elseif typeof(arg) <: Stroke elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width) 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.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.alpha === nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style) arg.style === nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
# linealpha # linealpha
elseif allAlphas(arg) elseif allAlphas(arg)
@ -822,10 +831,10 @@ function processMinorGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :minorgrid)] = true plotattributes[Symbol(letter, :minorgrid)] = true
elseif typeof(arg) <: Stroke elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width) 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.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.alpha === nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style) arg.style === nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
plotattributes[Symbol(letter, :minorgrid)] = true plotattributes[Symbol(letter, :minorgrid)] = true
# linealpha # linealpha
@ -930,6 +939,15 @@ function preprocessArgs!(plotattributes::KW)
end end
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 # handle grid args common to all axes
args = pop!(plotattributes, :grid, ()) args = pop!(plotattributes, :grid, ())
for arg in wraptuple(args) for arg in wraptuple(args)
@ -961,7 +979,7 @@ function preprocessArgs!(plotattributes::KW)
end end
end end
# fonts # fonts
for fontname in (:titlefont, :legendfont) for fontname in (:titlefont, :legendfont, :legendtitlefont)
args = pop!(plotattributes, fontname, ()) args = pop!(plotattributes, fontname, ())
for arg in wraptuple(args) for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg) processFontArg!(plotattributes, fontname, arg)
@ -1080,7 +1098,7 @@ function extractGroupArgs(v::AVec, args...; legendEntry = string)
if n > 100 if n > 100
@warn("You created n=$n groups... Is that intended?") @warn("You created n=$n groups... Is that intended?")
end 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) GroupBy(map(legendEntry, groupLabels), groupIds)
end end
@ -1088,7 +1106,7 @@ legendEntryFromTuple(ns::Tuple) = join(ns, ' ')
# this is when given a tuple of vectors of values to group by # this is when given a tuple of vectors of values to group by
function extractGroupArgs(vs::Tuple, args...) 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...) v = map(tuple, vs...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple) extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end end
@ -1098,7 +1116,7 @@ legendEntryFromTuple(ns::NamedTuple) =
join(["$k = $v" for (k, v) in pairs(ns)], ", ") join(["$k = $v" for (k, v) in pairs(ns)], ", ")
function extractGroupArgs(vs::NamedTuple, args...) 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)...) v = map(NamedTuple{keys(vs)}tuple, values(vs)...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple) extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end end
@ -1121,7 +1139,7 @@ end
function _filter_input_data!(plotattributes::KW) function _filter_input_data!(plotattributes::KW)
idxfilter = pop!(plotattributes, :idxfilter, nothing) idxfilter = pop!(plotattributes, :idxfilter, nothing)
if idxfilter != nothing if idxfilter !== nothing
filter_data!(plotattributes, idxfilter) filter_data!(plotattributes, idxfilter)
end end
end end
@ -1207,7 +1225,8 @@ convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
# anything else is returned as-is # anything else is returned as-is
function slice_arg(v::AMat, idx::Int) function slice_arg(v::AMat, idx::Int)
c = mod1(idx, size(v,2)) 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 end
slice_arg(wrapper::InputWrapper, idx) = wrapper.obj slice_arg(wrapper::InputWrapper, idx) = wrapper.obj
slice_arg(v, idx) = v slice_arg(v, idx) = v
@ -1237,7 +1256,7 @@ end
# v = plotattributes[k] # v = plotattributes[k]
# plotattributes[k] = if v == :match # plotattributes[k] = if v == :match
# match_color # match_color
# elseif v == nothing # elseif v === nothing
# plot_color(RGBA(0,0,0,0)) # plot_color(RGBA(0,0,0,0))
# else # else
# v # v
@ -1246,7 +1265,7 @@ end
function color_or_nothing!(plotattributes::KW, k::Symbol) function color_or_nothing!(plotattributes::KW, k::Symbol)
v = plotattributes[k] v = plotattributes[k]
plotattributes[k] = if v == nothing || v == false plotattributes[k] = if v === nothing || v == false
RGBA{Float64}(0,0,0,0) RGBA{Float64}(0,0,0,0)
elseif v != :match elseif v != :match
plot_color(v) plot_color(v)
@ -1271,8 +1290,10 @@ const _match_map = KW(
:bottom_margin => :margin, :bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot, :titlefontfamily => :fontfamily_subplot,
:legendfontfamily => :fontfamily_subplot, :legendfontfamily => :fontfamily_subplot,
:legendtitlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot, :titlefontcolor => :foreground_color_subplot,
:legendfontcolor => :foreground_color_subplot, :legendfontcolor => :foreground_color_subplot,
:legendtitlefontcolor => :foreground_color_subplot,
:tickfontcolor => :foreground_color_text, :tickfontcolor => :foreground_color_text,
:guidefontcolor => :foreground_color_guide, :guidefontcolor => :foreground_color_guide,
) )
@ -1563,11 +1584,11 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
# update alphas # update alphas
for asym in (:linealpha, :markeralpha, :fillalpha) for asym in (:linealpha, :markeralpha, :fillalpha)
if plotattributes[asym] == nothing if plotattributes[asym] === nothing
plotattributes[asym] = plotattributes[:seriesalpha] plotattributes[asym] = plotattributes[:seriesalpha]
end end
end end
if plotattributes[:markerstrokealpha] == nothing if plotattributes[:markerstrokealpha] === nothing
plotattributes[:markerstrokealpha] = plotattributes[:markeralpha] plotattributes[:markerstrokealpha] = plotattributes[:markeralpha]
end end
@ -1602,13 +1623,13 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
end end
# if marker_z, fill_z or line_z are set, ensure we have a gradient # 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) ensure_gradient!(plotattributes, :markercolor, :markeralpha)
end end
if plotattributes[:line_z] != nothing if plotattributes[:line_z] !== nothing
ensure_gradient!(plotattributes, :linecolor, :linealpha) ensure_gradient!(plotattributes, :linecolor, :linealpha)
end end
if plotattributes[:fill_z] != nothing if plotattributes[:fill_z] !== nothing
ensure_gradient!(plotattributes, :fillcolor, :fillalpha) ensure_gradient!(plotattributes, :fillcolor, :fillalpha)
end end

View File

@ -67,7 +67,7 @@ function process_axis_arg!(plotattributes::KW, arg, letter = "")
elseif T <: AVec elseif T <: AVec
plotattributes[Symbol(letter,:ticks)] = arg plotattributes[Symbol(letter,:ticks)] = arg
elseif arg == nothing elseif arg === nothing
plotattributes[Symbol(letter,:ticks)] = [] plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs 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 # or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format # rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime # 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 if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on # optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes # 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 end
# get a list of well-laid-out ticks # get a list of well-laid-out ticks
if ticks == nothing if ticks === nothing
scaled_ticks = optimize_ticks( scaled_ticks = optimize_ticks(
sf(amin), sf(amin),
sf(amax); 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)) map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :plain))
elseif formatter == :scientific elseif formatter == :scientific
Showoff.showoff(unscaled_ticks, :scientific) Showoff.showoff(unscaled_ticks, :scientific)
elseif formatter == :latex
map(x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"), Showoff.showoff(unscaled_ticks, :auto))
else else
# there was an override for the formatter... use that on the unscaled ticks # there was an override for the formatter... use that on the unscaled ticks
map(formatter, 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 #Add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits
if length(ticks) > 2 if length(ticks) > 2
ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1]) ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1])
elseif axis[:scale] == :none elseif axis[:scale] in (:none, :identity)
ratio = 1 ratio = 1
else else
return nothing return nothing
@ -309,8 +311,10 @@ function get_minor_ticks(sp, axis, ticks)
minorticks = typeof(ticks[1])[] minorticks = typeof(ticks[1])[]
for (i,hi) in enumerate(ticks[2:end]) for (i,hi) in enumerate(ticks[2:end])
lo = ticks[i] lo = ticks[i]
if isfinite(lo) && hi > lo
append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n)) append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
end end
end
minorticks[amin .<= minorticks .<= amax] minorticks[amin .<= minorticks .<= amax]
end end
@ -382,7 +386,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf)) data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
end end
expand_extrema!(axis, data) expand_extrema!(axis, data)
elseif data != nothing elseif data !== nothing
# TODO: need more here... gotta track the discrete reference value # TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all # as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value) # correspond to the same x-value)
@ -399,10 +403,10 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
# expand for fillrange # expand for fillrange
fr = plotattributes[:fillrange] fr = plotattributes[:fillrange]
if fr == nothing && plotattributes[:seriestype] == :bar if fr === nothing && plotattributes[:seriestype] == :bar
fr = 0.0 fr = 0.0
end end
if fr != nothing && !all3D(plotattributes) if fr !== nothing && !all3D(plotattributes)
axis = sp.attr[vert ? :yaxis : :xaxis] axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple if typeof(fr) <: Tuple
for fri in fr for fri in fr
@ -419,7 +423,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[dsym] data = plotattributes[dsym]
bw = plotattributes[:bar_width] 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)))) bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end end
axis = sp.attr[Symbol(dsym, :axis)] 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 # add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AVec) function discrete_value!(axis::Axis, v::AVec)
n = length(v) n = eachindex(v)
cvec = zeros(n) cvec = zeros(axes(v))
discrete_indices = zeros(Int, n) discrete_indices = similar(Array{Int}, axes(v))
for i=1:n for i in n
cvec[i], discrete_indices[i] = discrete_value!(axis, v[i]) cvec[i], discrete_indices[i] = discrete_value!(axis, v[i])
end end
cvec, discrete_indices cvec, discrete_indices
@ -584,10 +588,10 @@ end
# add the discrete value for each item. return the continuous values and the indices # add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AMat) function discrete_value!(axis::Axis, v::AMat)
n,m = size(v) n,m = axes(v)
cmat = zeros(n,m) cmat = zeros(axes(v))
discrete_indices = zeros(Int, n, m) discrete_indices = similar(Array{Int}, axes(v))
for i=1:n, j=1:m for i in n, j in m
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j]) cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j])
end end
cmat, discrete_indices cmat, discrete_indices
@ -633,13 +637,13 @@ function axis_drawing_info(sp::Subplot)
if sp[:framestyle] != :none if sp[:framestyle] != :none
# xaxis # xaxis
if xaxis[:showaxis]
if sp[:framestyle] != :grid
y1, y2 = if sp[:framestyle] in (:origin, :zerolines) y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0 0.0, 0.0
else else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax) xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
push!(xaxis_segs, (xmin, y1), (xmax, y1)) push!(xaxis_segs, (xmin, y1), (xmax, y1))
# don't show the 0 tick label for the origin framestyle # don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1 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)) if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale]) f = scalefunc(yaxis[:scale])
invf = invscalefunc(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 ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(ymin) + 0.015 * (f(ymax) - f(ymin)) * ticks_in) t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
t2 = invf(f(ymax) - 0.015 * (f(ymax) - f(ymin)) * ticks_in) (y1, t)
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in) end
for xtick in xticks[1] for xtick in xticks[1]
if xaxis[:showaxis] 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 push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end 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 xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end 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[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3) t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1) t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end end
push!(xtick_segs, (xminortick, tick_start), (xminortick, tick_stop)) # bottom tick 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 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
end end
# yaxis # yaxis
if yaxis[:showaxis]
if sp[:framestyle] != :grid
x1, x2 = if sp[:framestyle] in (:origin, :zerolines) x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0 0.0, 0.0
else else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax) xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
push!(yaxis_segs, (x1, ymin), (x1, ymax)) push!(yaxis_segs, (x1, ymin), (x1, ymax))
# don't show the 0 tick label for the origin framestyle # don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1 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)) if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale]) f = scalefunc(xaxis[:scale])
invf = invscalefunc(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 ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(xmin) + 0.015 * (f(xmax) - f(xmin)) * ticks_in) t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
t2 = invf(f(xmax) - 0.015 * (f(xmax) - f(xmin)) * ticks_in) (x1, t)
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in) end
for ytick in yticks[1] for ytick in yticks[1]
if yaxis[:showaxis] 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 push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end 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 yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end 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)
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 for ytick in yminorticks
if yaxis[:showaxis] 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 push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end 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 yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end end
end end
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 xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xminorgrid_segs, yminorgrid_segs, xborder_segs, yborder_segs
end 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

View File

@ -37,7 +37,6 @@ macro init_backend(s)
_backendType[Symbol($str)] = $T _backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str) _backendSymbol[$T] = Symbol($str)
_backend_packages[Symbol($str)] = Symbol($package_str) _backend_packages[Symbol($str)] = Symbol($package_str)
# include("backends/" * $str * ".jl")
end) end)
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 # account for the size/length/rotation of tick labels
function tick_padding(sp::Subplot, axis::Axis) function tick_padding(sp::Subplot, axis::Axis)
ticks = get_ticks(sp, axis) ticks = get_ticks(sp, axis)
if ticks == nothing if ticks === nothing
0mm 0mm
else else
vals, labs = ticks vals, labs = ticks
@ -229,7 +228,7 @@ const _base_supported_args = [
:subplot_index, :subplot_index,
:discrete_values, :discrete_values,
:projection, :projection,
:show_empty_bins
] ]
function merge_with_base_supported(v::AVec) function merge_with_base_supported(v::AVec)
@ -252,6 +251,7 @@ end
@init_backend PlotlyJS @init_backend PlotlyJS
@init_backend GR @init_backend GR
@init_backend PGFPlots @init_backend PGFPlots
@init_backend PGFPlotsX
@init_backend InspectDR @init_backend InspectDR
@init_backend HDF5 @init_backend HDF5
@ -296,9 +296,6 @@ end
_initialize_backend(pkg::GRBackend) = nothing _initialize_backend(pkg::GRBackend) = nothing
_initialize_backend(pkg::PlotlyBackend) = nothing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# gr # gr
@ -357,6 +354,16 @@ is_marker_supported(::GRBackend, shape::Shape) = true
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# plotly # 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([ const _plotly_attr = merge_with_base_supported([
:annotations, :annotations,
:background_color_legend, :background_color_inside, :background_color_outside, :background_color_legend, :background_color_inside, :background_color_outside,
@ -661,3 +668,57 @@ const _inspectdr_marker = Symbol[
] ]
const _inspectdr_scale = [:identity, :ln, :log2, :log10] 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

View File

@ -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) function gr_getcolorind(c)
gr_set_transparency(float(alpha(c))) gr_set_transparency(float(alpha(c)))
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(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
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)) gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s) function gr_inqtext(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$' if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.inqmathtex(x, y, s[2:end-1]) 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) GR.inqtextext(x, y, s)
else else
GR.inqtext(x, y, s) 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) function gr_text(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$' if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.mathtex(x, y, s[2:end-1]) 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) GR.textext(x, y, s)
else else
GR.text(x, y, s) GR.text(x, y, s)
@ -184,7 +239,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
if xaxis[:grid] if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) 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]) GR.polyline([sinf[i], 0], [cosf[i], 0])
end end
end end
@ -193,7 +248,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
if yaxis[:grid] if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) 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) r = (rtick_values[i] - rmin) / (rmax - rmin)
if r <= 1.0 && r >= 0.0 if r <= 1.0 && r >= 0.0
GR.drawarc(-r, r, -r, r, 0, 359) GR.drawarc(-r, r, -r, r, 0, 359)
@ -210,7 +265,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw angular ticks #draw angular ticks
if xaxis[:showaxis] if xaxis[:showaxis]
GR.drawarc(-1, 1, -1, 1, 0, 359) 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]) x, y = GR.wctondc(1.1 * sinf[i], 1.1 * cosf[i])
GR.textext(x, y, string((360-α[i])%360, "^o")) GR.textext(x, y, string((360-α[i])%360, "^o"))
end end
@ -218,7 +273,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw radial ticks #draw radial ticks
if yaxis[:showaxis] if yaxis[:showaxis]
for i in 1:length(rtick_values) for i in eachindex(rtick_values)
r = (rtick_values[i] - rmin) / (rmax - rmin) r = (rtick_values[i] - rmin) / (rmax - rmin)
if r <= 1.0 && r >= 0.0 if r <= 1.0 && r >= 0.0
x, y = GR.wctondc(0.05, r) 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_z_axislims(sp::Subplot) = axis_limits(sp, :z)
gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)... 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) function gr_fill_viewport(vp::AVec{Float64}, c)
GR.savestate() GR.savestate()
@ -260,19 +303,6 @@ function gr_fill_viewport(vp::AVec{Float64}, c)
GR.restorestate() GR.restorestate()
end 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 # draw ONE Shape
@ -305,7 +335,7 @@ function gr_draw_markers(series::Series, x, y, clims, msize = series[:markersize
shapes = series[:markershape] shapes = series[:markershape]
if shapes != :none if shapes != :none
for i=1:length(x) for i=eachindex(x)
msi = _cycle(msize, i) msi = _cycle(msize, i)
shape = _cycle(shapes, i) shape = _cycle(shapes, i)
cfunc = isa(shape, Shape) ? gr_set_fillcolor : gr_set_markercolor cfunc = isa(shape, Shape) ? gr_set_fillcolor : gr_set_markercolor
@ -370,6 +400,12 @@ function gr_nans_to_infs!(z)
end end
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 # 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[2] = viewport_canvas[2] * (right(bb) / w)
viewport[3] = viewport_canvas[4] * (1.0 - bottom(bb) / h) viewport[3] = viewport_canvas[4] * (1.0 - bottom(bb) / h)
viewport[4] = viewport_canvas[4] * (1.0 - top(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) if hascolorbar(sp)
viewport[2] -= gr_colorbar_ratio viewport[2] -= gr_colorbar_ratio * (1 + is3d(sp) / 2)
end end
viewport viewport
end end
@ -481,7 +509,7 @@ function _cbar_unique(values, propname)
out = last(values) out = last(values)
if any(x != out for x in values) if any(x != out for x in values)
@warn "Multiple series with different $propname share a colorbar. " * @warn "Multiple series with different $propname share a colorbar. " *
"Colorbar may not refelct all series correctly." "Colorbar may not reflect all series correctly."
end end
out out
end end
@ -567,13 +595,13 @@ function gr_legend_pos(sp::Subplot, w, h)
if occursin("right", str) if occursin("right", str)
if occursin("outer", str) if occursin("outer", str)
# As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525 # 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 else
xpos = viewport_plotarea[2] - 0.05 - w xpos = viewport_plotarea[2] - 0.05 - w
end end
elseif occursin("left", str) elseif occursin("left", str)
if occursin("outer", 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 else
xpos = viewport_plotarea[1] + 0.11 xpos = viewport_plotarea[1] + 0.11
end end
@ -582,13 +610,13 @@ function gr_legend_pos(sp::Subplot, w, h)
end end
if occursin("top", str) if occursin("top", str)
if s == :outertop 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 else
ypos = viewport_plotarea[4] - 0.06 ypos = viewport_plotarea[4] - 0.06
end end
elseif occursin("bottom", str) elseif occursin("bottom", str)
if s == :outerbottom 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 else
ypos = viewport_plotarea[3] + h + 0.06 ypos = viewport_plotarea[3] + h + 0.06
end end
@ -629,11 +657,11 @@ function gr_get_color(series::Series)
series[:fillcolor] series[:fillcolor]
elseif st in (:contour, :wireframe) elseif st in (:contour, :wireframe)
series[:linecolor] series[:linecolor]
elseif series[:marker_z] != nothing elseif series[:marker_z] !== nothing
series[:markercolor] series[:markercolor]
elseif series[:line_z] != nothing elseif series[:line_z] !== nothing
series[:linecolor] series[:linecolor]
elseif series[:fill_z] != nothing elseif series[:fill_z] !== nothing
series[:fillcolor] series[:fillcolor]
end end
end end
@ -747,26 +775,24 @@ function gr_get_ticks_size(ticks, rot)
return w, h return w, h
end end
function gr_xaxis_height(sp) function gr_axis_height(sp, axis)
xaxis = sp[:xaxis] ticks = get_ticks(sp, axis)
xticks, yticks = axis_drawing_info(sp)[1:2] gr_set_font(tickfont(axis))
gr_set_font(tickfont(xaxis)) h = (ticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(ticks, axis[:rotation])))
h = (xticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(xticks, xaxis[:rotation]))) if axis[:guide] != ""
if xaxis[:guide] != "" gr_set_font(guidefont(axis))
gr_set_font(guidefont(xaxis)) h += last(gr_text_size(axis[:guide]))
h += last(gr_text_size(xaxis[:guide]))
end end
return h return h
end end
function gr_yaxis_width(sp) function gr_axis_width(sp, axis)
yaxis = sp[:yaxis] ticks = get_ticks(sp, axis)
xticks, yticks = axis_drawing_info(sp)[1:2] gr_set_font(tickfont(axis))
gr_set_font(tickfont(yaxis)) w = (ticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(ticks, axis[:rotation])))
w = (xticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(yticks, yaxis[:rotation]))) if axis[:guide] != ""
if yaxis[:guide] != "" gr_set_font(guidefont(axis))
gr_set_font(guidefont(yaxis)) w += last(gr_text_size(axis[:guide]))
w += last(gr_text_size(yaxis[:guide]))
end end
return w return w
end end
@ -790,8 +816,90 @@ function _update_min_padding!(sp::Subplot{GRBackend})
h = 1mm + gr_plot_size[2] * l * px h = 1mm + gr_plot_size[2] * l * px
toppad += h toppad += h
end end
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 # Add margin for x and y ticks
xticks, yticks = axis_drawing_info(sp)[1:2] 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
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
if h > 0mm
if xaxis[:mirror] || yaxis[:mirror]
toppad += h
end
if !xaxis[:mirror] || !yaxis[:mirror]
bottompad += h
end
end
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)) if !(xticks in (nothing, false, :none))
flip, mirror = gr_set_xticks_font(sp) flip, mirror = gr_set_xticks_font(sp)
l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
@ -812,6 +920,7 @@ function _update_min_padding!(sp::Subplot{GRBackend})
leftpad += w leftpad += w
end end
end end
# Add margin for x label # Add margin for x label
if sp[:xaxis][:guide] != "" if sp[:xaxis][:guide] != ""
gr_set_font(guidefont(sp[:xaxis])) gr_set_font(guidefont(sp[:xaxis]))
@ -834,12 +943,18 @@ function _update_min_padding!(sp::Subplot{GRBackend})
leftpad += w leftpad += w
end end
end end
end
if sp[:colorbar_title] != "" if sp[:colorbar_title] != ""
rightpad += 4mm rightpad += 4mm
end end
sp.minpad = Tuple(dpi * [leftpad, toppad, rightpad, bottompad]) sp.minpad = Tuple(dpi * [leftpad, toppad, rightpad, bottompad])
end 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) function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
_update_min_padding!(sp) _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. # has to be done now due to a potential adjustment to the plotarea given an outer legend.
legendn = 0 legendn = 0
legendw = 0 legendw = 0
legendi = 0
if sp[:legend] != :none if sp[:legend] != :none
GR.savestate() GR.savestate()
GR.selntran(0) GR.selntran(0)
GR.setscale(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])) tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
legendw = tbx[3] - tbx[1] legendw = tbx[3] - tbx[1]
legendn += 1 legendn += 1
end end
gr_set_font(legendfont(sp))
for series in series_list(sp) for series in series_list(sp)
should_add_to_legend(series) || continue should_add_to_legend(series) || continue
legendn += 1 legendn += 1
if typeof(series[:label]) <: Array
legendi += 1
lab = series[:label][legendi]
else
lab = series[:label] lab = series[:label]
end
tbx, tby = gr_inqtext(0, 0, string(lab)) tbx, tby = gr_inqtext(0, 0, string(lab))
legendw = max(legendw, tbx[3] - tbx[1]) legendw = max(legendw, tbx[3] - tbx[1])
end end
@ -908,7 +1018,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
leg_str = string(sp[:legend]) leg_str = string(sp[:legend])
if occursin("outer", leg_str) if occursin("outer", leg_str)
if occursin("right", leg_str) if occursin("right", leg_str)
viewport_plotarea[2] -= legendw + 0.11 viewport_plotarea[2] -= legendw + 0.12
elseif occursin("left", leg_str) elseif occursin("left", leg_str)
viewport_plotarea[1] += legendw + 0.11 viewport_plotarea[1] += legendw + 0.11
elseif occursin("top", leg_str) 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 # fill in the plot area background
bg = plot_color(sp[:background_color_inside]) 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 # reduced from before... set some flags based on the series in this subplot
# TODO: can these be generic flags? # TODO: can these be generic flags?
outside_ticks = false outside_ticks = false
# calculate the colorbar limits once for a subplot
clims = get_clims(sp)
cbar = GRColorbar() cbar = GRColorbar()
draw_axes = sp[:framestyle] != :none draw_axes = sp[:framestyle] != :none
@ -940,11 +1048,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
outside_ticks = true outside_ticks = true
for ax in (sp[:xaxis], sp[:yaxis]) for ax in (sp[:xaxis], sp[:yaxis])
v = series[ax[:letter]] 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
end x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
x, y = heatmap_edges(series[:x], sp[:xaxis][:scale]), heatmap_edges(series[:y], sp[:yaxis][:scale])
xy_lims = x[1], x[end], y[1], y[end] xy_lims = x[1], x[end], y[1], y[end]
expand_extrema!(sp[:xaxis], x) expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y) 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]) GR.setlinewidth(sp.plt[:thickness_scaling])
if is3d(sp) if is3d(sp)
# TODO do we really need a different clims computation here from the one zmin, zmax = axis_limits(sp, :z)
# 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
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...) 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] if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) 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 end
if yaxis[:grid] if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) 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 end
if zaxis[:grid] if zaxis[:grid]
gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid]) gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid])
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha]) 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 end
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]) gr_set_line(1, :solid, xaxis[:foreground_color_axis])
gr_set_transparency(xaxis[:foreground_color_axis]) end
GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize) GR.setclip(0)
GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize) 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) elseif ispolar(sp)
r = gr_set_viewport_polar() 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) # @show cv dv ymin xi yi flip mirror (flip $ mirror)
if xaxis[:ticks] in (:auto, :native) if xaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks # ensure correct dispatch in gr_text for automatic log ticks
if xaxis[:formatter] in (:scientific, :auto)
if xaxis[:scale] in _logScales if xaxis[:scale] in _logScales
dv = string(dv, "\\ ") dv = string(dv, "\\ ")
elseif xaxis[:formatter] in (:scientific, :auto) end
dv = convert_sci_unicode(dv) dv = convert_sci_unicode(dv)
end end
end end
@ -1140,9 +1435,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# @show cv dv xmin xi yi # @show cv dv xmin xi yi
if yaxis[:ticks] in (:auto, :native) if yaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks # ensure correct dispatch in gr_text for automatic log ticks
if yaxis[:formatter] in (:scientific, :auto)
if yaxis[:scale] in _logScales if yaxis[:scale] in _logScales
dv = string(dv, "\\ ") dv = string(dv, "\\ ")
elseif yaxis[:formatter] in (:scientific, :auto) end
dv = convert_sci_unicode(dv) dv = convert_sci_unicode(dv)
end end
end end
@ -1182,12 +1478,54 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_text(xpos, viewport_subplot[4], sp[:title]) gr_text(xpos, viewport_subplot[4], sp[:title])
end end
if is3d(sp) 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] != "" 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)) gr_set_font(guidefont(xaxis))
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) 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 end
if yaxis[:guide] != "" if yaxis[:guide] != ""
w = 0.02 + gr_yaxis_width(sp) w = 0.02 + gr_axis_width(sp, yaxis)
gr_set_font(guidefont(yaxis)) gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0) GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) 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] x, y, z = series[:x], series[:y], series[:z]
frng = series[:fillrange] frng = series[:fillrange]
clims = get_clims(sp, series)
# add custom frame shapes to markershape? # add custom frame shapes to markershape?
series_annotations_shapes!(series) series_annotations_shapes!(series)
# ------------------------------------------------------- # -------------------------------------------------------
@ -1247,7 +1587,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if typeof(z) <: Surface if typeof(z) <: Surface
z = vec(transpose_z(series, z.surf, false)) z = vec(transpose_z(series, z.surf, false))
elseif ispolar(sp) elseif ispolar(sp)
if frng != nothing if frng !== nothing
_, frng = convert_to_polar(x, frng, (rmin, rmax)) _, frng = convert_to_polar(x, frng, (rmin, rmax))
end end
x, y = convert_to_polar(x, y, (rmin, rmax)) x, y = convert_to_polar(x, y, (rmin, rmax))
@ -1258,11 +1598,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end end
if st in (:path, :scatter, :straightline) if st in (:path, :scatter, :straightline)
if x != nothing && length(x) > 1 if x !== nothing && length(x) > 1
lz = series[:line_z] lz = series[:line_z]
segments = iter_segments(series) segments = iter_segments(series)
# do area fill # do area fill
if frng != nothing if frng !== nothing
GR.setfillintstyle(GR.INTSTYLE_SOLID) GR.setfillintstyle(GR.INTSTYLE_SOLID)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng)) fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i, rng) in enumerate(segments) 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]) plot_color(series[:linecolor]) in (black,[black])
end end
h = gr_contour_levels(series, clims) h = gr_contour_levels(series, clims)
if series[:fillrange] != nothing if series[:fillrange] !== nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines") @warn("GR: filled contour only supported with black contour lines")
end end
@ -1335,26 +1675,45 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :heatmap elseif st == :heatmap
zmin, zmax = clims zmin, zmax = clims
if !ispolar(sp) 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) GR.setspace(zmin, zmax, 0, 90)
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad() x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
colors = [plot_color(grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)], series[:fillalpha]) for zi=z] w, h = length(x) - 1, length(y) - 1
rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 + z_normalized = map(x -> GR.jlgr.normalize_color(x, zmin, zmax), z)
round(UInt, blue(c) * 255) << 16 + if is_uniformly_spaced(x) && is_uniformly_spaced(y)
round(UInt, green(c) * 255) << 8 + # For uniformly spaced data use GR.drawimage, which can be
round(UInt, red(c) * 255) ), colors) # much faster than GR.nonuniformcellarray, especially for
w, h = length(x), length(y) # pdf output, and also supports alpha values.
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) # 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 else
h, w = length(x), length(y) (something(series[:fillalpha],1) < 1 || any(_gr_gradient_alpha .< 1)) && @warn(
z = reshape(z, h, w) "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored.")
colors = Int32[round(Int32, 1000 + _i * 255) for _i in z'] z_normalized = map(x -> isnan(x) ? 256/255 : x, z_normalized) # results in color index = 1256 -> transparent
GR.setwindow(-1, 1, -1, 1) colors = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
GR.polarcellarray(0, 0, 0, 360, 0, 1, w, h, colors) GR.nonuniformcellarray(x, y, w, h, colors)
end
else
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 end
elseif st in (:path3d, :scatter3d) elseif st in (:path3d, :scatter3d)
@ -1454,19 +1813,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :image elseif st == :image
z = transpose_z(series, series[:z].surf, true)' z = transpose_z(series, series[:z].surf, true)'
w, h = size(z) 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]) xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
if eltype(z) <: Colors.AbstractGray rgba = gr_color.(z)
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
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
end end
@ -1481,7 +1829,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end end
# draw the colorbar # draw the colorbar
hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims) hascolorbar(sp) && gr_draw_colorbar(cbar, sp, get_clims(sp))
# add the legend # add the legend
if sp[:legend] != :none if sp[:legend] != :none
@ -1490,7 +1838,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setscale(0) GR.setscale(0)
gr_set_font(legendfont(sp)) gr_set_font(legendfont(sp))
w = legendw w = legendw
i = legendi
n = legendn n = legendn
if w > 0 if w > 0
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 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_set_line(1, :solid, sp[:foreground_color_legend])
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n) GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
i = 0 i = 0
if sp[:legendtitle] != nothing if sp[:legendtitle] !== nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(sp[:legendfontcolor]) gr_set_font(legendtitlefont(sp))
gr_set_transparency(sp[:legendfontcolor])
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle])) gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy ypos -= dy
gr_set_font(legendfont(sp))
end end
for series in series_list(sp) for series in series_list(sp)
clims = get_clims(sp, series)
should_add_to_legend(series) || continue should_add_to_legend(series) || continue
st = series[:seriestype] st = series[:seriestype]
lc = get_linecolor(series, clims) lc = get_linecolor(series, clims)
gr_set_line(get_linewidth(series), get_linestyle(series), lc) #, series[:linealpha]) 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) fc = get_fillcolor(series, clims)
gr_set_fill(fc) #, series[:fillalpha]) gr_set_fill(fc) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01 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) if st in (:path, :straightline)
gr_set_transparency(lc, get_linealpha(series)) 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]) GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
else else
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos+0.4dy, ypos+0.4dy]) 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) gr_draw_markers(series, xpos - .035, ypos, clims, 6)
end end
if typeof(series[:label]) <: Array
i += 1
lab = series[:label][i]
else
lab = series[:label] lab = series[:label]
end
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF) 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)) gr_text(xpos, ypos, string(lab))
ypos -= dy ypos -= dy
end end
@ -1573,7 +1916,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
for ann in sp[:annotations] for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...) x, y, val = locate_annotation(sp, ann...)
x, y = if is3d(sp) x, y = if is3d(sp)
# GR.wc3towc(x, y, z) gr_w3tondc(x, y, z)
else else
GR.wctondc(x, y) GR.wctondc(x, y)
end end

View File

@ -121,9 +121,9 @@ function _create_backend_figure(plt::Plot{InspectDRBackend})
gplot = _inspectdr_getgui(plt.o) gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure #:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot != nothing if plt[:overwrite_figure] && mplot !== nothing
mplot.subplots = [] #Reset mplot.subplots = [] #Reset
if gplot != nothing #Ensure still references current plot if gplot !== nothing #Ensure still references current plot
gplot.src = mplot gplot.src = mplot
end end
else #want new one: else #want new one:

24
src/backends/orca.jl Normal file
View File

@ -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

View File

@ -96,7 +96,7 @@ pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(plotattributes, i = 1) function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(plotattributes, i)) cstr,a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(plotattributes, i) fa = get_fillalpha(plotattributes, i)
if fa != nothing if fa !== nothing
a = fa a = fa
end end
"fill = $cstr, fill opacity=$a" "fill = $cstr, fill opacity=$a"
@ -128,16 +128,18 @@ function pgf_marker(plotattributes, i = 1)
shape = _cycle(plotattributes[:markershape], i) shape = _cycle(plotattributes[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, 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))) cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i)))
""" return string(
mark = $(get(_pgfplots_markers, shape, "*")), "mark = $(get(_pgfplots_markers, shape, "*")),\n",
mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)), "mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),\n",
mark options = { plotattributes[:seriestype] == :scatter ? "only marks,\n" : "",
"mark options = {
color = $cstr_stroke, draw opacity = $a_stroke, color = $cstr_stroke, draw opacity = $a_stroke,
fill = $cstr, fill opacity = $a, fill = $cstr, fill opacity = $a,
line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)), line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0), rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid")) $(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
}""" }"
)
end end
function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1) function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1)
@ -178,11 +180,11 @@ function pgf_series(sp::Subplot, series::Series)
end end
# PGFPlots can't handle non-Vector? # PGFPlots can't handle non-Vector?
args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector # args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
collect(a) # collect(a)
else # else
a # a
end, args) # end, args)
if st in (:contour, :histogram2d) if st in (:contour, :histogram2d)
style = [] style = []
@ -216,12 +218,12 @@ function pgf_series(sp::Subplot, series::Series)
# add to legend? # add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series) if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if plotattributes[:fillrange] != nothing if plotattributes[:fillrange] !== nothing
push!(style, "forget plot") push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args)) push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
else else
kw[:legendentry] = plotattributes[:label] kw[:legendentry] = plotattributes[:label]
if st == :shape # || plotattributes[:fillrange] != nothing if st == :shape # || plotattributes[:fillrange] !== nothing
push!(style, "area legend") push!(style, "area legend")
end end
end end
@ -238,7 +240,7 @@ function pgf_series(sp::Subplot, series::Series)
kw[:style] = join(style, ',') kw[:style] = join(style, ',')
# add fillrange # 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...)) push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
end end
@ -476,8 +478,18 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
if haskey(_pgfplots_legend_pos, legpos) if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos] kw[:legendPos] = _pgfplots_legend_pos[legpos]
end end
cstr, a = pgf_color(plot_color(sp[:background_color_legend])) cstr, bg_alpha = 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)), "}")) 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)) if any(s[:seriestype] == :contour for s in series_list(sp))
kw[:view] = "{0}{90}" kw[:view] = "{0}{90}"

862
src/backends/pgfplotsx.jl Normal file
View File

@ -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

View File

@ -26,7 +26,6 @@ const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js"
# end # end
using UUIDs using UUIDs
push!(_initialized_backends, :plotly)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
const _plotly_legend_pos = KW( const _plotly_legend_pos = KW(
@ -346,12 +345,12 @@ function plotly_layout(plt::Plot)
end end
function plotly_layout_json(plt::Plot) function plotly_layout_json(plt::Plot)
JSON.json(plotly_layout(plt)) JSON.json(plotly_layout(plt), 4)
end end
function plotly_colorscale(grad::ColorGradient, α) 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 end
plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α) plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α) 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 # we split by NaNs and then construct/destruct the shapes to get the closed coords
function plotly_close_shapes(x, y) function plotly_close_shapes(x, y)
xs, ys = nansplit(x), nansplit(y) xs, ys = nansplit(x), nansplit(y)
for i=1:length(xs) for i=eachindex(xs)
shape = Shape(xs[i], ys[i]) shape = Shape(xs[i], ys[i])
xs[i], ys[i] = coords(shape) xs[i], ys[i] = coords(shape)
end end
@ -402,7 +401,7 @@ end
function plotly_data(series::Series, letter::Symbol, data) function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)] 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) plotly_native_data(axis, data)
else else
data data
@ -414,7 +413,8 @@ function plotly_data(series::Series, letter::Symbol, data)
plotly_data(data) plotly_data(data)
end end
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(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v) plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
@ -453,7 +453,7 @@ function plotly_series(plt::Plot, series::Series)
st = series[:seriestype] st = series[:seriestype]
sp = series[:subplot] sp = series[:subplot]
clims = get_clims(sp) clims = get_clims(sp, series)
if st == :shape if st == :shape
return plotly_series_shapes(plt, series, clims) 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) plotattributes_out[:showlegend] = should_add_to_legend(series)
if st == :straightline if st == :straightline
x, y = straightline_data(series) x, y = straightline_data(series, 100)
z = series[:z] z = series[:z]
else else
x, y, z = series[:x], series[:y], series[:z] x, y, z = series[:x], series[:y], series[:z]
@ -528,7 +528,7 @@ function plotly_series(plt::Plot, series::Series)
else else
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = 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]) plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end end
plotattributes_out[:showscale] = hascolorbar(sp) 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) 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) 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)) plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[i] = plotattributes_out plotattributes_outs[i] = plotattributes_out
end end
if series[:fill_z] != nothing if series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill)) 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)) 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)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end end
plotattributes_outs 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)) (isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series) 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) for (i,rng) in enumerate(segments)
!isscatter && length(rng) < 2 && continue
plotattributes_out = deepcopy(plotattributes_base) plotattributes_out = deepcopy(plotattributes_base)
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotattributes_out[:legendgroup] = series[:label] plotattributes_out[:legendgroup] = series[:label]
@ -734,11 +732,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
end end
end end
if series[:line_z] != nothing if series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line)) 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)) 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)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end end
@ -783,7 +781,7 @@ function plotly_hover!(plotattributes_out::KW, hover)
# hover text # hover text
if hover in (:none, false) if hover in (:none, false)
plotattributes_out[:hoverinfo] = "none" plotattributes_out[:hoverinfo] = "none"
elseif hover != nothing elseif hover !== nothing
plotattributes_out[:hoverinfo] = "text" plotattributes_out[:hoverinfo] = "text"
plotattributes_out[:text] = hover plotattributes_out[:text] = hover
end end
@ -799,13 +797,16 @@ function plotly_series(plt::Plot)
end end
# get json string for a list of dictionaries, each representing the series params # 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) const ijulia_initialized = Ref(false)
function html_head(plt::Plot{PlotlyBackend}) function plotly_html_head(plt::Plot)
local_file = ("file://" * plotly_local_file_path) local_file = ("file://" * plotly_local_file_path)
plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path
if isijulia() && !ijulia_initialized[] if isijulia() && !ijulia_initialized[]
@ -821,12 +822,10 @@ function html_head(plt::Plot{PlotlyBackend})
""") """)
ijulia_initialized[] = true ijulia_initialized[] = true
end end
# IJulia just needs one initialization
isijulia() && return ""
return "<script src=$(repr(plotly))></script>" return "<script src=$(repr(plotly))></script>"
end end
function html_body(plt::Plot{PlotlyBackend}, style = nothing) function plotly_html_body(plt, style = nothing)
if style == nothing if style == nothing
style = "width:100%;height:100%;" style = "width:100%;height:100%;"
end end
@ -839,7 +838,7 @@ function html_body(plt::Plot{PlotlyBackend}, style = nothing)
""" """
end end
function js_body(plt::Plot{PlotlyBackend}, divid) function js_body(plt::Plot, divid)
""" """
gd = (function() { gd = (function() {
var WIDTH_IN_PERCENT_OF_PARENT = 100; 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 = [] data = []
for series in plot.series_list for series in plot.series_list
append!(data, plotly_series(plot, series)) 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)) JSON.print(io, Dict(:data => data, :layout => layout))
end 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}) function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt) standalone_html_window(plt)
end end

View File

@ -1,78 +1,44 @@
# https://github.com/sglyon/PlotlyJS.jl # https://github.com/sglyon/PlotlyJS.jl
# -------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
function plotlyjs_syncplot(plt::Plot{PlotlyJSBackend})
function _create_backend_figure(plt::Plot{PlotlyJSBackend}) plt[:overwrite_figure] && closeall()
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot) plt.o = PlotlyJS.plot()
PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options) traces = PlotlyJS.GenericTrace[]
else for series_dict in plotly_series(plt)
PlotlyJS.plot() plotly_type = pop!(series_dict, :type)
push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...))
end end
end PlotlyJS.addtraces!(plt.o, traces...)
layout = plotly_layout(plt)
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
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
# ----------------------------------------------------------------
function _update_plot_object(plt::Plot{PlotlyJSBackend})
pdict = plotly_layout(plt)
syncplot = plt.o
w, h = plt[:size] w, h = plt[:size]
PlotlyJS.relayout!(syncplot, pdict, width = w, height = h) PlotlyJS.relayout!(plt.o, layout, width = w, height = h)
return plt.o
end end
# ------------------------------------------------------------------------------
# ---------------------------------------------------------------- const _plotlyjs_mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"image/svg+xml" => "svg",
"image/eps" => "eps",
)
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o) for (mime, fmt) in _plotlyjs_mimeformats
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="svg") @eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
_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 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)
function write_temp_html(plt::Plot{PlotlyJSBackend}) html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt)
filename = string(tempname(), ".html") html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt)
savefig(plt, filename)
filename
end
function _display(plt::Plot{PlotlyJSBackend}) _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, standalone_html(plt))
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
display(plt.o) _display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt))
else
standalone_html_window(plt)
end
end
@require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin @require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin
function WebIO.render(plt::Plot{PlotlyJSBackend}) function WebIO.render(plt::Plot{PlotlyJSBackend})

View File

@ -187,7 +187,7 @@ end
# end # end
function get_locator_and_formatter(vals::AVec) function get_locator_and_formatter(vals::AVec)
pyticker."FixedLocator"(1:length(vals)), pyticker."FixedFormatter"(vals) pyticker."FixedLocator"(eachindex(vals)), pyticker."FixedFormatter"(vals)
end end
function add_pyfixedformatter(cbar, vals::AVec) function add_pyfixedformatter(cbar, vals::AVec)
@ -216,7 +216,7 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series) function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
if series[:x] != nothing if series[:x] !== nothing
x, y = series[:x], series[:y] x, y = series[:x], series[:y]
nx, ny = length(x), length(y) nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny 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 # handle zcolor and get c/cmap
needs_colorbar = hascolorbar(sp) needs_colorbar = hascolorbar(sp)
vmin, vmax = clims = get_clims(sp) vmin, vmax = clims = get_clims(sp, series)
# Dict to store extra kwargs # Dict to store extra kwargs
if st == :wireframe if st == :wireframe
@ -434,7 +434,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if maximum(series[:linewidth]) > 0 if maximum(series[:linewidth]) > 0
segments = iter_segments(series) segments = iter_segments(series)
# TODO: check LineCollection alternative for speed # 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 # # multicolored line segments
# n = length(segments) # n = length(segments)
# # segments = Array(Any,n) # # segments = Array(Any,n)
@ -478,7 +478,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# end # end
a = series[:arrow] 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 if typeof(a) != Arrow
@warn("Unexpected type for arrow: $(typeof(a))") @warn("Unexpected type for arrow: $(typeof(a))")
else else
@ -508,7 +508,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:markershape] != :none && st in (:path, :scatter, :path3d, if series[:markershape] != :none && st in (:path, :scatter, :path3d,
:scatter3d, :steppre, :steppost, :scatter3d, :steppre, :steppost,
:bar) :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, 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)] [py_color(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) for i in eachindex(x)]
else else
@ -535,7 +535,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
shapes = series[:markershape] shapes = series[:markershape]
msc = py_markerstrokecolor(series) msc = py_markerstrokecolor(series)
lw = py_thickness_scale(plt, series[:markerstrokewidth]) lw = py_thickness_scale(plt, series[:markerstrokewidth])
for i=1:length(y) for i=eachindex(y)
extrakw[:c] = _cycle(markercolor, i) extrakw[:c] = _cycle(markercolor, i)
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i); push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
@ -564,7 +564,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
delete!(extrakw, :c) delete!(extrakw, :c)
for i=1:length(y) for i=eachindex(y)
cur_marker = py_marker(_cycle(shapes,i)) cur_marker = py_marker(_cycle(shapes,i))
if ( cur_marker == prev_marker ) if ( cur_marker == prev_marker )
@ -672,7 +672,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle) push!(handles, handle)
# contour fills # contour fills
if series[:fillrange] != nothing if series[:fillrange] !== nothing
handle = ax."contourf"(x, y, z, levelargs...; handle = ax."contourf"(x, y, z, levelargs...;
label = series[:label], label = series[:label],
zorder = series[:series_plotindex] + 0.5, zorder = series[:series_plotindex] + 0.5,
@ -691,7 +691,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end end
z = transpose_z(series, z) z = transpose_z(series, z)
if st == :surface if st == :surface
if series[:fill_z] != nothing if series[:fill_z] !== nothing
# the surface colors are different than z-value # the surface colors are different than z-value
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf)) extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
extrakw[:shade] = false extrakw[:shade] = false
@ -756,7 +756,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
cmap = py_colormap(cgrad([:black, :white])), cmap = py_colormap(cgrad([:black, :white])),
vmin = 0.0, vmin = 0.0,
vmax = 1.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) push!(handles, handle)
@ -830,7 +830,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# handle area filling # handle area filling
fillrange = series[:fillrange] fillrange = series[:fillrange]
if fillrange != nothing && st != :contour if fillrange !== nothing && st != :contour
for (i, rng) in enumerate(iter_segments(series)) for (i, rng) in enumerate(iter_segments(series))
f, dim1, dim2 = if isvertical(series) f, dim1, dim2 = if isvertical(series)
:fill_between, x[rng], y[rng] :fill_between, x[rng], y[rng]
@ -871,7 +871,7 @@ end
function py_set_ticks(ax, ticks, letter) function py_set_ticks(ax, ticks, letter)
ticks == :auto && return ticks == :auto && return
axis = getproperty(ax, Symbol(letter,"axis")) axis = getproperty(ax, Symbol(letter,"axis"))
if ticks == :none || ticks == nothing || ticks == false if ticks == :none || ticks === nothing || ticks == false
kw = KW() kw = KW()
for dir in (:top,:bottom,:left,:right) for dir in (:top,:bottom,:left,:right)
kw[dir] = kw[Symbol(:label,dir)] = false kw[dir] = kw[Symbol(:label,dir)] = false
@ -927,7 +927,7 @@ function py_set_scale(ax, sp::Subplot, axis::Axis)
elseif scale == :log10 elseif scale == :log10
10 10
end 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" "symlog"
end end
func(arg; kw...) func(arg; kw...)
@ -978,7 +978,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update subplots # update subplots
for sp in plt.subplots for sp in plt.subplots
ax = sp.o ax = sp.o
if ax == nothing if ax === nothing
continue continue
end end
@ -1013,17 +1013,17 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw = KW() kw = KW()
if !isempty(sp[:zaxis][:discrete_values]) && colorbar_series[:seriestype] == :heatmap if !isempty(sp[:zaxis][:discrete_values]) && colorbar_series[:seriestype] == :heatmap
locator, formatter = get_locator_and_formatter(sp[:zaxis][:discrete_values]) 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[:values] = sp[:zaxis][:continuous_values]
kw[:ticks] = locator kw[:ticks] = locator
kw[:format] = formatter kw[:format] = formatter
kw[:boundaries] = vcat(0, kw[:values] + 0.5) 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) cmin, cmax = get_clims(sp)
norm = pycolors."Normalize"(vmin = cmin, vmax = cmax) norm = pycolors."Normalize"(vmin = cmin, vmax = cmax)
f = if colorbar_series[:line_z] != nothing f = if colorbar_series[:line_z] !== nothing
py_linecolormap py_linecolormap
elseif colorbar_series[:fill_z] != nothing elseif colorbar_series[:fill_z] !== nothing
py_fillcolormap py_fillcolormap
else else
py_markercolormap py_markercolormap
@ -1186,7 +1186,7 @@ end
# to fit ticks, tick labels, guides, colorbars, etc. # to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PyPlotBackend}) function _update_min_padding!(sp::Subplot{PyPlotBackend})
ax = sp.o ax = sp.o
ax == nothing && return sp.minpad ax === nothing && return sp.minpad
plotbb = py_bbox(ax) plotbb = py_bbox(ax)
# TODO: this should initialize to the margin from sp.attr # 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) function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val)
ax = sp.o ax = sp.o
ax."annotate"(val, xy = (x,y), zorder = 999) ax."annotate"(val, xy = (x,y), zorder = 999, annotation_clip = false)
end 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), verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
rotation = val.font.rotation, rotation = val.font.rotation,
size = py_thickness_scale(sp.plt, val.font.pointsize), size = py_thickness_scale(sp.plt, val.font.pointsize),
zorder = 999 zorder = 999,
annotation_clip = false
) )
end end
@ -1289,15 +1290,15 @@ py_legend_bbox(pos) = pos
function py_add_legend(plt::Plot, sp::Subplot, ax) function py_add_legend(plt::Plot, sp::Subplot, ax)
leg = sp[:legend] leg = sp[:legend]
clims = get_clims(sp)
if leg != :none if leg != :none
# gotta do this to ensure both axes are included # gotta do this to ensure both axes are included
labels = [] labels = []
handles = [] handles = []
for series in series_list(sp) for series in series_list(sp)
if should_add_to_legend(series) if should_add_to_legend(series)
clims = get_clims(sp, series)
# add a line/marker and a label # 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"( pypatches."Patch"(
edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)), edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
facecolor = py_color(single_color(get_fillcolor(series, clims)), get_fillalpha(series)), 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 = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1)) frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000) 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"() 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 end
end end
@ -1352,7 +1356,7 @@ end
function _update_plot_object(plt::Plot{PyPlotBackend}) function _update_plot_object(plt::Plot{PyPlotBackend})
for sp in plt.subplots for sp in plt.subplots
ax = sp.o ax = sp.o
ax == nothing && return ax === nothing && return
figw, figh = sp.plt[:size] figw, figh = sp.plt[:size]
figw, figh = figw*px, figh*px figw, figh = figw*px, figh*px
pcts = bbox_to_pcts(sp.plotarea, figw, figh) pcts = bbox_to_pcts(sp.plotarea, figw, figh)

View File

@ -187,7 +187,7 @@ end
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape)) function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = coords(shape) sx, sy = coords(shape)
cx, cy = c cx, cy = c
for i=1:length(sx) for i=eachindex(sx)
sx[i] = (sx[i] - cx) * x + cx sx[i] = (sx[i] - cx) * x + cx
sy[i] = (sy[i] - cy) * y + cy sy[i] = (sy[i] - cy) * y + cy
end end
@ -202,7 +202,7 @@ end
"translate a Shape in space" "translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x) function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape) sx, sy = coords(shape)
for i=1:length(sx) for i=eachindex(sx)
sx[i] += x sx[i] += x
sy[i] += y sy[i] += y
end end
@ -230,7 +230,7 @@ end
function rotate!(shape::Shape, Θ::Real, c = center(shape)) function rotate!(shape::Shape, Θ::Real, c = center(shape))
x, y = coords(shape) x, y = coords(shape)
cx, cy = c cx, cy = c
for i=1:length(x) for i=eachindex(x)
xi = rotate_x(x[i], y[i], Θ, cx, cy) xi = rotate_x(x[i], y[i], Θ, cx, cy)
yi = rotate_y(x[i], y[i], Θ, cx, cy) yi = rotate_y(x[i], y[i], Θ, cx, cy)
x[i], y[i] = xi, yi x[i], y[i] = xi, yi
@ -529,7 +529,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# end # end
# @show msw msh # @show msw msh
if anns != nothing && anns.baseshape != nothing if anns !== nothing && anns.baseshape !== nothing
# we use baseshape to overwrite the markershape attribute # we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each # with a list of custom shapes for each
msw,msh = anns.scalefactor msw,msh = anns.scalefactor
@ -568,7 +568,7 @@ mutable struct EachAnn
end end
function Base.iterate(ea::EachAnn, i = 1) 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 return nothing
end end
@ -794,7 +794,7 @@ end
@deprecate curve_points coords @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. # 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] # may create a loop if necessary. Assumes the view is [0,1]

View File

@ -165,7 +165,7 @@ PlotExample("Marker types",
), ),
PlotExample("Bar", 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 [:(begin
bar(randn(99)) bar(randn(99))
end)] end)]
@ -238,12 +238,12 @@ build with the method `text(string, attr...)`, which wraps font and color attrib
""", """,
[:(begin [:(begin
y = rand(10) y = rand(10)
plot(y, annotations = (3,y[3],text("this is #3",:left)), leg=false) plot(y, annotations = (3,y[3], Plots.text("this is #3",:left)), leg=false)
annotate!([(5, y[5], text("this is #5",16,:red,:center)), annotate!([(5, y[5], Plots.text("this is #5",16,:red,:center)),
(10, y[10], text("this is #10",:right,20,"courier"))]) (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), scatter!(range(2, stop=8, length=6), rand(6), marker=(50,0.2,:orange),
series_annotations = ["series","annotations","map","to","series", series_annotations = ["series","annotations","map","to","series",
text("data",:green)]) Plots.text("data",:green)])
end)] end)]
), ),
@ -305,7 +305,8 @@ PlotExample("3D",
PlotExample("DataFrames", PlotExample("DataFrames",
"Plot using DataFrame column symbols.", "Plot using DataFrame column symbols.",
[:(begin [:(using StatsPlots), # can't be inside begin block because @df gets expanded first
:(begin
import RDatasets import RDatasets
iris = RDatasets.dataset("datasets", "iris") iris = RDatasets.dataset("datasets", "iris")
@df iris scatter(:SepalLength, :SepalWidth, group=:Species, @df iris scatter(:SepalLength, :SepalWidth, group=:Species,
@ -354,7 +355,8 @@ PlotExample("Layouts, margins, label rotation, title location",
PlotExample("Boxplot and Violin series recipes", PlotExample("Boxplot and Violin series recipes",
"", "",
[:(begin [:(using StatsPlots), # can't be inside begin block because @df gets expanded first
:(begin
import RDatasets import RDatasets
singers = RDatasets.dataset("lattice", "singer") singers = RDatasets.dataset("lattice", "singer")
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue)) @df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue))
@ -454,6 +456,49 @@ see: http://stackoverflow.com/a/37732384/5075246
end)] 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 # Some constants for PlotDocs and PlotReferenceImages
@ -461,7 +506,7 @@ _animation_examples = [2, 30]
_backend_skips = Dict( _backend_skips = Dict(
:gr => [25, 30], :gr => [25, 30],
:pyplot => [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], :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)") @info("Testing plot: $pkgname:$idx:$(_examples[idx].header)")
backend(pkgname) backend(pkgname)
backend() 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() plt = current()
if disp if disp
gui(plt) gui(plt)
@ -495,8 +545,8 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
skip = [], only = nothing) skip = [], only = nothing)
Plots._debugMode.on = debug Plots._debugMode.on = debug
plts = Dict() plts = Dict()
for i in 1:length(_examples) for i in eachindex(_examples)
only != nothing && !(i in only) && continue only !== nothing && !(i in only) && continue
i in skip && continue i in skip && continue
try try
plt = test_examples(pkgname, i, debug=debug, disp=disp) 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? # TODO: put error info into markdown?
@warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex") @warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
end end
if sleep != nothing if sleep !== nothing
Base.sleep(sleep) Base.sleep(sleep)
end end
end end

View File

@ -20,7 +20,10 @@ frontends like jupyterlab and nteract.
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out _ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict) 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 out
end end

View File

@ -28,12 +28,53 @@ function __init__()
insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
end) end)
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl")) @require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" include(joinpath(@__DIR__, "backends", "inspectdr.jl")) fn = joinpath(@__DIR__, "backends", "hdf5.jl")
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" include(joinpath(@__DIR__, "backends", "pgfplots.jl")) include(fn)
@require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" include(joinpath(@__DIR__, "backends", "plotlyjs.jl")) @require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" include(joinpath(@__DIR__, "backends", "pyplot.jl")) end
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" include(joinpath(@__DIR__, "backends", "unicodeplots.jl"))
@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 @require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited if IJulia.inited

View File

@ -107,7 +107,6 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
if mix.len != 0mm if mix.len != 0mm
f = (letter == :x ? width : height) f = (letter == :x ? width : height)
totlen = f(plotarea(sp)) totlen = f(plotarea(sp))
@show totlen
pct += mix.len / totlen pct += mix.len / totlen
end end
if pct != 0 if pct != 0
@ -218,6 +217,7 @@ bottompad(layout::AbstractLayout) = 0mm
# this is the parent of the top-level layout # this is the parent of the top-level layout
struct RootLayout <: AbstractLayout end struct RootLayout <: AbstractLayout end
Base.show(io::IO, layout::RootLayout) = Base.show_default(io, layout)
Base.parent(::RootLayout) = nothing Base.parent(::RootLayout) = nothing
parent_bbox(::RootLayout) = defaultbox parent_bbox(::RootLayout) = defaultbox
bbox(::RootLayout) = defaultbox bbox(::RootLayout) = defaultbox
@ -469,7 +469,7 @@ function layout_args(plotattributes::KW)
end end
function layout_args(plotattributes::KW, n_override::Integer) 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 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.") 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 end
@ -481,12 +481,27 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n GridLayout(nr, nc), n
end end
function layout_args(sztup::NTuple{2,I}) where I<:Integer function layout_args(sztup::NTuple{2, Integer})
nr, nc = sztup nr, nc = sztup
GridLayout(nr, nc), nr*nc GridLayout(nr, nc), nr*nc
end 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 n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc) nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n GridLayout(nr, nc), n
@ -499,6 +514,8 @@ function layout_args(layout::GridLayout)
layout, n layout, n
end end
layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh") layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")

View File

@ -72,6 +72,7 @@ const _savemap = Dict(
"eps" => eps, "eps" => eps,
"tex" => tex, "tex" => tex,
"html" => html, "html" => html,
"tikz" => tex,
) )
function getExtension(fn::AbstractString) 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. file types, some also support svg, ps, eps, html and tex.
""" """
function savefig(plt::Plot, fn::AbstractString) function savefig(plt::Plot, fn::AbstractString)
fn = abspath(expanduser(fn))
# get the extension # get the extension
local ext local ext
try try
@ -201,6 +202,8 @@ for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml
end end
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 # default text/plain for all backends
_show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt) _show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt)
@ -229,15 +232,16 @@ closeall() = closeall(backend())
# Atom PlotPane # Atom PlotPane
# --------------------------------------------------------- # ---------------------------------------------------------
function showjuno(io::IO, m, plt) function showjuno(io::IO, m, plt)
sz = plt[:size] sz = collect(plt[:size])
dpi = plt[:dpi] dpi = plt[:dpi]
thickness_scaling = plt[:thickness_scaling] thickness_scaling = plt[:thickness_scaling]
jsize = get(io, :juno_plotsize, [400, 500]) 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) scale = minimum(jsize[i] / sz[i] for i in 1:2)
plt[:size] = (s * scale for s in sz) plt[:size] = [s * scale for s in sz]
plt[:dpi] = Plots.DPI plt[:dpi] = jratio*Plots.DPI
plt[:thickness_scaling] *= scale plt[:thickness_scaling] *= scale
prepare_output(plt) prepare_output(plt)
@ -258,4 +262,6 @@ function _showjuno(io::IO, m::MIME"image/svg+xml", plt)
end end
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) _showjuno(io::IO, m, plt) = _show(io, m, plt)

View File

@ -12,7 +12,7 @@ function _expand_seriestype_array(plotattributes::KW, args)
if typeof(sts) <: AbstractArray if typeof(sts) <: AbstractArray
delete!(plotattributes, :seriestype) delete!(plotattributes, :seriestype)
rd = Vector{RecipeData}(undef, size(sts, 1)) rd = Vector{RecipeData}(undef, size(sts, 1))
for r in 1:size(sts, 1) for r in axes(sts, 1)
dc = copy(plotattributes) dc = copy(plotattributes)
dc[:seriestype] = sts[r:r,:] dc[:seriestype] = sts[r:r,:]
rd[r] = RecipeData(dc, args) rd[r] = RecipeData(dc, args)
@ -126,7 +126,7 @@ function _preprocess_userrecipe(kw::KW)
end end
# convert a ribbon into a fillrange # convert a ribbon into a fillrange
if get(kw, :ribbon, nothing) != nothing if get(kw, :ribbon, nothing) !== nothing
make_fillrange_from_ribbon(kw) make_fillrange_from_ribbon(kw)
end end
return 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 # handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from # the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror) 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 # we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw) errkw = copy(kw)
errkw[:seriestype] = esym errkw[:seriestype] = esym
@ -227,7 +227,7 @@ function _plot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# handle inset subplots # handle inset subplots
insets = plt[:inset_subplots] insets = plt[:inset_subplots]
if insets != nothing if insets !== nothing
if !(typeof(insets) <: AVec) if !(typeof(insets) <: AVec)
insets = [insets] insets = [insets]
end end

View File

@ -4,7 +4,7 @@ mutable struct CurrentPlot
end end
const CURRENT_PLOT = CurrentPlot(nothing) const CURRENT_PLOT = CurrentPlot(nothing)
isplotnull() = CURRENT_PLOT.nullableplot == nothing isplotnull() = CURRENT_PLOT.nullableplot === nothing
""" """
current() current()

View File

@ -1,3 +1,873 @@
function _precompile_() function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing 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 end

View File

@ -239,7 +239,7 @@ end
@recipe function f(::Type{Val{:sticks}}, x, y, z) @recipe function f(::Type{Val{:sticks}}, x, y, z)
n = length(x) n = length(x)
fr = plotattributes[:fillrange] fr = plotattributes[:fillrange]
if fr == nothing if fr === nothing
sp = plotattributes[:subplot] sp = plotattributes[:subplot]
yaxis = sp[:yaxis] yaxis = sp[:yaxis]
fr = if yaxis[:scale] == :identity fr = if yaxis[:scale] == :identity
@ -291,13 +291,13 @@ end
# create segmented bezier curves in place of line segments # create segmented bezier curves in place of line segments
@recipe function f(::Type{Val{:curves}}, x, y, z; npoints = 30) @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) newx, newy = zeros(0), zeros(0)
fr = plotattributes[:fillrange] fr = plotattributes[:fillrange]
newfr = fr != nothing ? zeros(0) : nothing newfr = fr !== nothing ? zeros(0) : nothing
newz = z != nothing ? zeros(0) : nothing newz = z !== nothing ? zeros(0) : nothing
# lz = plotattributes[:line_z] # 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 # 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 # where the points are the control points of the curve
@ -306,13 +306,13 @@ end
ts = range(0, stop = 1, length = npoints) ts = range(0, stop = 1, length = npoints)
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts)) nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,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)) nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
end end
if fr != nothing if fr !== nothing
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts)) nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
end end
# if lz != nothing # if lz !== nothing
# lzrng = _cycle(lz, rng) # the line_z's for this segment # lzrng = _cycle(lz, rng) # the line_z's for this segment
# push!(newlz, 0.0) # push!(newlz, 0.0)
# append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts)) # append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
@ -321,16 +321,16 @@ end
x := newx x := newx
y := newy y := newy
if z == nothing if z === nothing
seriestype := :path seriestype := :path
else else
seriestype := :path3d seriestype := :path3d
z := newz z := newz
end end
if fr != nothing if fr !== nothing
fillrange := newfr fillrange := newfr
end end
# if lz != nothing # if lz !== nothing
# # line_z := newlz # # line_z := newlz
# linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad()) # linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad())
# end # end
@ -357,19 +357,19 @@ end
# compute half-width of bars # compute half-width of bars
bw = plotattributes[:bar_width] bw = plotattributes[:bar_width]
hw = if bw == nothing hw = if bw === nothing
if nx > 1 if nx > 1
0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx))) 0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx)))
else else
0.5 * _bar_width 0.5 * _bar_width
end end
else else
Float64[0.5_cycle(bw,i) for i=1:length(procx)] Float64[0.5_cycle(bw,i) for i=eachindex(procx)]
end end
# make fillto a vector... default fills to 0 # make fillto a vector... default fills to 0
fillto = plotattributes[:fillrange] fillto = plotattributes[:fillrange]
if fillto == nothing if fillto === nothing
fillto = 0 fillto = 0
end end
if (yscale in _logScales) && !all(_is_positive, fillto) if (yscale in _logScales) && !all(_is_positive, fillto)
@ -491,7 +491,7 @@ end
@recipe function f(::Type{Val{:barbins}}, x, y, z) @recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y) edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
if (plotattributes[:bar_width] == nothing) if (plotattributes[:bar_width] === nothing)
bar_width := diff(edge) bar_width := diff(edge)
end end
x := _bin_centers(edge) x := _bin_centers(edge)
@ -533,7 +533,7 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S
last_w = eltype(weights)(NaN) 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 b, it_state_e = it_tuple_e
w, it_state_w = it_tuple_w 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 function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
localvs = _filternans(vs) localvs = _filternans(vs)
edges = _hist_edges(localvs, binning) 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, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left) StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left)
) )
@ -746,6 +746,7 @@ end
edge_x, edge_y, weights = x, y, z.surf edge_x, edge_y, weights = x, y, z.surf
float_weights = float(weights) float_weights = float(weights)
if !plotattributes[:show_empty_bins]
if float_weights === weights if float_weights === weights
float_weights = deepcopy(float_weights) float_weights = deepcopy(float_weights)
end end
@ -754,6 +755,7 @@ end
float_weights[i] = NaN float_weights[i] = NaN
end end
end end
end
x := Plots._bin_centers(edge_x) x := Plots._bin_centers(edge_x)
y := Plots._bin_centers(edge_y) y := Plots._bin_centers(edge_y)
@ -996,7 +998,7 @@ function get_xy(o::OHLC, x, xdiff)
end end
# get the joined vector # 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))) xdiff = 0.3ignorenan_mean(abs.(diff(x)))
x_out, y_out = zeros(0), zeros(0) x_out, y_out = zeros(0), zeros(0)
for (i,ohlc) in enumerate(v) for (i,ohlc) in enumerate(v)
@ -1054,8 +1056,8 @@ end
@assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix @assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix
seriestype := :spy seriestype := :spy
mat = g.args[1] mat = g.args[1]
n,m = size(mat) n,m = axes(mat)
Plots.SliceIt, 1:m, 1:n, Surface(mat) Plots.SliceIt, m, n, Surface(mat)
end end
@recipe function f(::Type{Val{:spy}}, x,y,z) @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{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))) @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 # Complex Numbers
@ -1178,7 +1185,7 @@ end
seriestype := :shape seriestype := :shape
# create a filled polygon for each item # 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])) sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1]))
sy = vcat(returns, reverse(returns)) sy = vcat(returns, reverse(returns))
@series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) @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) @recipe function f(a::AreaPlot)
data = cumsum(a.args[end], dims=2) 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 seriestype := :line
for i in 1:size(data, 2) for i in axes(data, 2)
@series begin @series begin
fillrange := i > 1 ? data[:,i-1] : 0 fillrange := i > 1 ? data[:,i-1] : 0
x, data[:,i] x, data[:,i]

View File

@ -7,46 +7,76 @@
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now # note: returns meta information... mainly for use with automatic labeling from DataFrames for now
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
const DataPoint = Union{Number, AbstractString, Missing} const MaybeNumber = Union{Number, Missing}
const SeriesData = Union{AVec{<:DataPoint}, Function, Surface, Volume} const MaybeString = Union{AbstractString, Missing}
const DataPoint = Union{MaybeNumber, MaybeString}
prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting")
prepareSeriesData(::Nothing) = nothing prepareSeriesData(::Nothing) = nothing
prepareSeriesData(s::SeriesData) = handlemissings(s) prepareSeriesData(f::Function) = f
prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!(
handlemissings(v) = v x -> ismissing(x) || isinf(x) ? NaN : x,
handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: Number = replace(v, missing => NaN) map(float,a))
handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: AbstractString = replace(v, missing => "") prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
handlemissings(s::Surface) = Surface(handlemissings(s.surf)) prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
handlemissings(v::Volume) = Volume(handlemissings(v.v), v.x_extents, v.y_extents, v.z_extents) 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 # default: assume x represents a single series
convertToAnyVector(x) = Any[prepareSeriesData(x)] convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)]
# fixed number of blank series # 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 # 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) # 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 # 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 # 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 # 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::Nothing, z) = axes(z,1)
compute_x(x::Nothing, y, z) = 1:size(y,1) compute_x(x::Nothing, y, z) = axes(y,1)
compute_x(x::Function, y, z) = map(x, y) compute_x(x::Function, y, z) = map(x, y)
compute_x(x, y, z) = copy(x) compute_x(x, y, z) = copy(x)
# compute_y(x::Void, y::Function, z) = error() # 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::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y) compute_y(x, y, z) = copy(y)
@ -96,25 +126,17 @@ struct SliceIt end
z = z.data z = z.data
end end
xs = convertToAnyVector(x) xs = convertToAnyVector(x, plotattributes)
ys = convertToAnyVector(y) ys = convertToAnyVector(y, plotattributes)
zs = convertToAnyVector(z) zs = convertToAnyVector(z, plotattributes)
fr = pop!(plotattributes, :fillrange, nothing) fr = pop!(plotattributes, :fillrange, nothing)
fillranges = if typeof(fr) <: Number fillranges = process_fillrange(fr, plotattributes)
[fr]
else
convertToAnyVector(fr)
end
mf = length(fillranges) mf = length(fillranges)
rib = pop!(plotattributes, :ribbon, nothing) rib = pop!(plotattributes, :ribbon, nothing)
ribbons = if typeof(rib) <: Number ribbons = process_ribbon(rib, plotattributes)
[rib]
else
convertToAnyVector(rib)
end
mr = length(ribbons) mr = length(ribbons)
# @show zs # @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 # 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} @recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing}
if all3D(plotattributes) if all3D(plotattributes)
n,m = size(mat) n,m = axes(mat)
wrap_surfaces(plotattributes) wrap_surfaces(plotattributes)
SliceIt, 1:m, 1:n, Surface(mat) SliceIt, m, n, Surface(mat)
else else
SliceIt, nothing, mat, nothing SliceIt, nothing, mat, nothing
end end
@ -272,9 +294,9 @@ end
@recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix @recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix
if all3D(plotattributes) if all3D(plotattributes)
mat = fmt.data mat = fmt.data
n,m = size(mat) n,m = axes(mat)
wrap_surfaces(plotattributes) wrap_surfaces(plotattributes)
SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter) SliceIt, m, n, Formatted(Surface(mat), fmt.formatter)
else else
SliceIt, nothing, fmt, nothing SliceIt, nothing, fmt, nothing
end end
@ -297,35 +319,35 @@ function clamp_greys!(mat::AMat{T}) where T<:Gray
end end
@recipe function f(mat::AMat{T}) where T<:Gray @recipe function f(mat::AMat{T}) where T<:Gray
n, m = size(mat) n, m = axes(mat)
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
SliceIt, 1:m, 1:n, Surface(clamp_greys!(mat)) SliceIt, m, n, Surface(clamp_greys!(mat))
else else
seriestype := :heatmap seriestype := :heatmap
yflip --> true yflip --> true
cbar --> false cbar --> false
fillcolor --> ColorGradient([:black, :white]) 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
end end
# # images - colors # # images - colors
@recipe function f(mat::AMat{T}) where T<:Colorant @recipe function f(mat::AMat{T}) where T<:Colorant
n, m = size(mat) n, m = axes(mat)
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
SliceIt, 1:m, 1:n, Surface(mat) SliceIt, m, n, Surface(mat)
else else
seriestype := :heatmap seriestype := :heatmap
yflip --> true yflip --> true
cbar --> false cbar --> false
z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat) z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat)
SliceIt, 1:m, 1:n, Surface(z) SliceIt, m, n, Surface(z)
end end
end end
@ -344,24 +366,30 @@ end
@recipe function f(shapes::AMat{Shape}) @recipe function f(shapes::AMat{Shape})
seriestype --> :shape seriestype --> :shape
for j in 1:size(shapes,2) for j in axes(shapes,2)
@series coords(vec(shapes[:,j])) @series coords(vec(shapes[:,j]))
end end
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 # function without range... use the current range of the x-axis
@recipe function f(f::FuncOrFuncs{F}) where F<:Function @recipe function f(f::FuncOrFuncs{F}) where F<:Function
plt = plotattributes[:plot_object] plt = plotattributes[:plot_object]
xmin, xmax = try xmin, xmax = if haskey(plotattributes, :xlims)
plotattributes[:xlims]
else
try
axis_limits(plt[1], :x) axis_limits(plt[1], :x)
catch catch
xinv = invscalefunc(get(plotattributes, :xscale, :identity)) xinv = invscalefunc(get(plotattributes, :xscale, :identity))
xm = tryrange(f, xinv.([-5,-1,0,0.01])) xm = tryrange(f, xinv.([-5,-1,0,0.01]))
xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01]))) xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01])))
end end
end
f, xmin, xmax f, xmin, xmax
end end
@ -491,20 +519,25 @@ end
# # special handling... xmin/xmax with parametric function(s) # # special handling... xmin/xmax with parametric function(s)
@recipe function f(f::Function, xmin::Number, xmax::Number) @recipe function f(f::Function, xmin::Number, xmax::Number)
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)] xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
xs = _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
xs, f
end end
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function @recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)] 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 = Array{Any}(undef, length(fs))
xs, 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 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}, 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) @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) function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
(xf, xinv), (yf, yinv) = ((scalefunc(s),invscalefunc(s)) for s in (xscale,yscale)) (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 end
# #
@ -550,7 +583,7 @@ end
# end # end
splittable_kw(key, val, lengthGroup) = false 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::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup))
splittable_kw(key, val::SeriesAnnotations, lengthGroup) = splittable_kw(key, val.strs, 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]) 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)) y_mat = Array{promote_type(eltype(y), typeof(def_val))}(undef, length(keys(x_ind)), length(groupby.groupLabels))
fill!(y_mat, def_val) fill!(y_mat, def_val)
for i in 1:length(groupby.groupLabels) for i in eachindex(groupby.groupLabels)
xi = x[groupby.groupIds[i]] xi = x[groupby.groupIds[i]]
yi = y[groupby.groupIds[i]] yi = y[groupby.groupIds[i]]
y_mat[getindex.(Ref(x_ind), xi), i] = yi y_mat[getindex.(Ref(x_ind), xi), i] = yi
@ -597,7 +630,7 @@ group_as_matrix(t) = false
if length(g.args) == 1 if length(g.args) == 1
x = zeros(Int, lengthGroup) x = zeros(Int, lengthGroup)
for indexes in groupby.groupIds for indexes in groupby.groupIds
x[indexes] = 1:length(indexes) x[indexes] = eachindex(indexes)
end end
last_args = g.args last_args = g.args
else else
@ -605,7 +638,7 @@ group_as_matrix(t) = false
last_args = g.args[2:end] last_args = g.args[2:end]
end end
x_u = unique(sort(x)) 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 for (key,val) in plotattributes
if splittable_kw(key, val, lengthGroup) if splittable_kw(key, val, lengthGroup)
:($key) := groupedvec2mat(x_ind, x, val, groupby) :($key) := groupedvec2mat(x_ind, x, val, groupby)

View File

@ -4,39 +4,19 @@
Specify the colour theme for plots. Specify the colour theme for plots.
""" """
function theme(s::Symbol; kw...) function theme(s::Symbol; kw...)
defaults = _get_defaults(s) defaults = copy(PlotThemes._themes[s].defaults)
_theme(s, defaults; kw...) _theme(s, defaults; kw...)
end 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...) function _theme(s::Symbol, defaults::KW; kw...)
# Reset to defaults to overwrite active theme # Reset to defaults to overwrite active theme
reset_defaults() reset_defaults()
# Set the theme's gradient as default # Set the theme's gradient as default
if haskey(defaults, :gradient) if haskey(defaults, :colorgradient)
PlotUtils.clibrary(:misc) PlotUtils.clibrary(:misc)
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s)) PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
pop!(defaults, :colorgradient)
else else
PlotUtils.clibrary(:Plots) PlotUtils.clibrary(:Plots)
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno) PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
@ -44,8 +24,8 @@ function _theme(s::Symbol, defaults::KW; kw...)
# maybe overwrite the theme's gradient # maybe overwrite the theme's gradient
kw = KW(kw) kw = KW(kw)
if haskey(kw, :gradient) if haskey(kw, :colorgradient)
kwgrad = pop!(kw, :gradient) kwgrad = pop!(kw, :colorgradient)
for clib in clibraries() for clib in clibraries()
if kwgrad in cgradients(clib) if kwgrad in cgradients(clib)
PlotUtils.clibrary(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) @recipe function showtheme(st::ShowTheme)
thm, cfunc = _get_showtheme_args(st.args...) thm, cfunc = _get_showtheme_args(st.args...)
defaults = _get_defaults(thm) defaults = PlotThemes._themes[thm].defaults
# get the gradient # get the gradient
gradient_colors = get(defaults, :gradient, cgrad(:inferno).colors) gradient_colors = get(defaults, :colorgradient, cgrad(:inferno).colors)
gradient = cgrad(cfunc.(RGB.(gradient_colors))) colorgradient = cgrad(cfunc.(RGB.(gradient_colors)))
# get the palette # get the palette
palette = get(defaults, :palette, get_color_palette(:auto, plot_color(:white), 17)) 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 # apply the theme
for k in keys(defaults) for k in keys(defaults)
k in (:gradient, :palette) && continue k in (:colorgradient, :palette) && continue
def = defaults[k] def = defaults[k]
arg = get(_keyAliases, k, k) arg = get(_keyAliases, k, k)
plotattributes[arg] = if typeof(def) <: Colorant plotattributes[arg] = if typeof(def) <: Colorant
@ -139,27 +119,30 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
@series begin @series begin
subplot := 4 subplot := 4
seriestype := :heatmap seriestype := :heatmap
seriescolor := gradient seriescolor := colorgradient
ticks := -5:5:5 xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
x, y, z x, y, z
end end
@series begin @series begin
subplot := 5 subplot := 5
seriestype := :surface 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 x, y, z
end end
n = 100 n = 100
ts = range(0, stop = 10π, length = n) ts = range(0, stop = 10π, length = n)
x = ts .* cos.(ts) x = (0.1ts) .* cos.(ts)
y = (0.1ts) .* sin.(ts) y = (0.1ts) .* sin.(ts)
z = 1:n z = 1:n
@series begin @series begin
subplot := 6 subplot := 6
seriescolor := gradient seriescolor := colorgradient
linewidth := 3 linewidth := 3
line_z := z line_z := z
x, y, z x, y, z

View File

@ -26,7 +26,7 @@ function histogramHack(; kw...)
plotattributes[:x] = midpoints plotattributes[:x] = midpoints
plotattributes[:y] = float(counts) plotattributes[:y] = float(counts)
plotattributes[:seriestype] = :bar plotattributes[:seriestype] = :bar
plotattributes[:fillrange] = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange] plotattributes[:fillrange] = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
plotattributes plotattributes
end end
@ -38,12 +38,12 @@ function barHack(; kw...)
plotattributes = KW(kw) plotattributes = KW(kw)
midpoints = plotattributes[:x] midpoints = plotattributes[:x]
heights = plotattributes[:y] heights = plotattributes[:y]
fillrange = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange] fillrange = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
# estimate the edges # estimate the edges
dists = diff(midpoints) * 0.5 dists = diff(midpoints) * 0.5
edges = zeros(length(midpoints)+1) edges = zeros(length(midpoints)+1)
for i in 1:length(edges) for i in eachindex(edges)
if i == 1 if i == 1
edge = midpoints[1] - dists[1] edge = midpoints[1] - dists[1]
elseif i == length(edges) elseif i == length(edges)
@ -56,7 +56,7 @@ function barHack(; kw...)
x = Float64[] x = Float64[]
y = Float64[] y = Float64[]
for i in 1:length(heights) for i in eachindex(heights)
e1, e2 = edges[i:i+1] e1, e2 = edges[i:i+1]
append!(x, [e1, e1, e2, e2]) append!(x, [e1, e1, e2, e2])
append!(y, [fillrange, heights[i], heights[i], fillrange]) append!(y, [fillrange, heights[i], heights[i], fillrange])
@ -81,7 +81,7 @@ function sticksHack(; kw...)
# these are the line vertices # these are the line vertices
x = Float64[] x = Float64[]
y = Float64[] y = Float64[]
fillrange = plotattributesLine[:fillrange] == nothing ? 0.0 : plotattributesLine[:fillrange] fillrange = plotattributesLine[:fillrange] === nothing ? 0.0 : plotattributesLine[:fillrange]
# calculate the vertices # calculate the vertices
yScatter = plotattributesScatter[:y] yScatter = plotattributesScatter[:y]
@ -115,7 +115,6 @@ function regressionXY(x, y)
end end
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
@show T, size(z)
n, m = size(z) n, m = size(z)
# idx = 0 # idx = 0
colors = ColorGradient(vec(z)) colors = ColorGradient(vec(z))
@ -146,16 +145,18 @@ end
Segments() = Segments(Float64) Segments() = Segments(Float64)
Segments(::Type{T}) where {T} = Segments(T[]) 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)) # Segments() = Segments(zeros(0))
to_nan(::Type{Float64}) = NaN to_nan(::Type{Float64}) = NaN
to_nan(::Type{NTuple{2,Float64}}) = (NaN, 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{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{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 function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts) if !isempty(segments.pts)
@ -183,24 +184,26 @@ end
mutable struct SegmentsIterator mutable struct SegmentsIterator
args::Tuple args::Tuple
n::Int n1::Int
n2::Int
end end
function iter_segments(args...) function iter_segments(args...)
tup = Plots.wraptuple(args) tup = Plots.wraptuple(args)
n = maximum(map(length, tup)) n1 = minimum(map(firstindex, tup))
SegmentsIterator(tup, n) n2 = maximum(map(lastindex, tup))
SegmentsIterator(tup, n1, n2)
end end
function iter_segments(series::Series) function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z] x, y, z = series[:x], series[:y], series[:z]
if x == nothing if x === nothing
return UnitRange{Int}[] return UnitRange{Int}[]
elseif has_attribute_segments(series) elseif has_attribute_segments(series)
if series[:seriestype] in (:scatter, :scatter3d) if series[:seriestype] in (:scatter, :scatter3d)
return [[i] for i in 1:length(y)] return [[i] for i in eachindex(y)]
else 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 end
else else
segs = UnitRange{Int}[] 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) anynan(istart::Int, iend::Int, args::Tuple) = any(anynan(args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend) allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend)
function Base.iterate(itr::SegmentsIterator, nextidx::Int = 1) function Base.iterate(itr::SegmentsIterator, nextidx::Int = itr.n1)
i = findfirst(!anynan(itr.args), nextidx:itr.n) i = findfirst(!anynan(itr.args), nextidx:itr.n2)
i === nothing && return nothing i === nothing && return nothing
nextval = nextidx + i - 1 nextval = nextidx + i - 1
j = findfirst(anynan(itr.args), nextval:itr.n) j = findfirst(anynan(itr.args), nextval:itr.n2)
nextnan = j === nothing ? itr.n + 1 : nextval + j - 1 nextnan = j === nothing ? itr.n2 + 1 : nextval + j - 1
nextval:nextnan-1, nextnan nextval:nextnan-1, nextnan
end end
@ -343,8 +346,11 @@ const _scale_base = Dict{Symbol, Real}(
:ln => , :ln => ,
) )
function _heatmap_edges(v::AVec) function _heatmap_edges(v::AVec, isedges::Bool = false)
length(v) == 1 && return v[1] .+ [-0.5, 0.5] 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) vmin, vmax = ignorenan_extrema(v)
extra_min = (v[2] - v[1]) / 2 extra_min = (v[2] - v[1]) / 2
extra_max = (v[end] - v[end - 1]) / 2 extra_max = (v[end] - v[end - 1]) / 2
@ -352,9 +358,30 @@ function _heatmap_edges(v::AVec)
end end
"create an (n+1) list of the outsides of heatmap rectangles" "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) 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 end
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r)) 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) rib1, rib2 = -first(rib), last(rib)
# kw[:ribbon] = nothing # kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2) 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 end
#turn tuple of fillranges to one path #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) function get_clims(sp::Subplot)
zmin, zmax = Inf, -Inf zmin, zmax = Inf, -Inf
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface)
for series in series_list(sp) 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 series[:colorbar_entry]
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real}) zmin, zmax = _update_clims(zmin, zmax, get_clims(series)...)
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 end
end end
clims = sp[:clims] clims = sp[:clims]
@ -539,10 +561,37 @@ function get_clims(sp::Subplot)
isfinite(clims[1]) && (zmin = clims[1]) isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2]) isfinite(clims[2]) && (zmax = clims[2])
end end
return zmin < zmax ? (zmin, zmax) : (-0.1, 0.1) return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end 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 @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) function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
c = series[$Symbol($compcolor)] c = series[$Symbol($compcolor)]
z = series[$Symbol($comp_z)] z = series[$Symbol($comp_z)]
if z == nothing if z === nothing
isa(c, ColorGradient) ? c : plot_color(_cycle(c, i)) isa(c, ColorGradient) ? c : plot_color(_cycle(c, i))
else else
grad = isa(c, ColorGradient) ? c : cgrad() 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) $get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1) 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) $get_compcolor(series, 0, 1, i)
else else
$get_compcolor(series, get_clims(series[:subplot]), i) $get_compcolor(series, get_clims(series[:subplot]), i)
@ -650,11 +699,11 @@ function has_attribute_segments(series::Series)
for letter in (:x, :y, :z) for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and # If we have NaNs in the data they define the segments and
# SegmentsIterator is used # SegmentsIterator is used
series[letter] != nothing && NaN in collect(series[letter]) && return false series[letter] !== nothing && NaN in collect(series[letter]) && return false
end end
series[:seriestype] == :shape && return false series[:seriestype] == :shape && return false
# ... else we check relevant attributes if they have multiple inputs # ... 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 end
# --------------------------------------------------------------- # ---------------------------------------------------------------
@ -1060,6 +1109,15 @@ legendfont(sp::Subplot) = font(
sp[:legendfontcolor], sp[:legendfontcolor],
) )
legendtitlefont(sp::Subplot) = font(
sp[:legendtitlefontfamily],
sp[:legendtitlefontsize],
sp[:legendtitlefontvalign],
sp[:legendtitlefonthalign],
sp[:legendtitlefontrotation],
sp[:legendtitlefontcolor],
)
tickfont(ax::Axis) = font( tickfont(ax::Axis) = font(
ax[:tickfontfamily], ax[:tickfontfamily],
ax[:tickfontsize], ax[:tickfontsize],
@ -1106,20 +1164,20 @@ function convert_sci_unicode(label::AbstractString)
label label
end end
function straightline_data(series) function straightline_data(series, expansion_factor = 1)
sp = series[:subplot] sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp)) xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y] x, y = series[:x], series[:y]
n = length(x) n = length(x)
if n == 2 if n == 2
return straightline_data(xl, yl, x, y) return straightline_data(xl, yl, x, y, expansion_factor)
else else
k, r = divrem(n, 3) k, r = divrem(n, 3)
if r == 0 if r == 0
xdata, ydata = fill(NaN, n), fill(NaN, n) xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k for i in 1:k
inds = (3 * i - 2):(3 * i - 1) 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 end
return xdata, ydata return xdata, ydata
else else
@ -1128,7 +1186,7 @@ function straightline_data(series)
end end
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] x_vals, y_vals = if y[1] == y[2]
if x[1] == x[2] if x[1] == x[2]
error("Two identical points cannot be used to describe a straight line.") error("Two identical points cannot be used to describe a straight line.")
@ -1149,29 +1207,28 @@ function straightline_data(xl, yl, x, y)
end end
# expand the data outside the axis limits, by a certain factor too improve # expand the data outside the axis limits, by a certain factor too improve
# plotly(js) and interactive behaviour # plotly(js) and interactive behaviour
factor = 100 x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* expansion_factor .* [-1, 1]
x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* factor .* [-1, 1] y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* expansion_factor .* [-1, 1]
y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* factor .* [-1, 1]
return x_vals, y_vals return x_vals, y_vals
end end
function shape_data(series) function shape_data(series, expansion_factor = 1)
sp = series[:subplot] sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp)) xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y] x, y = series[:x], series[:y]
factor = 100 factor = 100
for i in eachindex(x) for i in eachindex(x)
if x[i] == -Inf 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 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
end end
for i in eachindex(y) for i in eachindex(y)
if y[i] == -Inf 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 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
end end
return x, y return x, y

View File

@ -1,34 +1,6 @@
import Plots._current_plots_version import Plots._current_plots_version
# Taken from MakieGallery function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = !is_ci(), sigma = [1,1], tol = 1e-2)
"""
Downloads the reference images from ReferenceImages for a specific version
"""
function download_reference(version = v"0.0.1")
download_dir = abspath(@__DIR__, "reference_images")
isdir(download_dir) || mkpath(download_dir)
tarfile = joinpath(download_dir, "reference_images.zip")
url = "https://github.com/JuliaPlots/PlotReferenceImages.jl/archive/v$(version).tar.gz"
refpath = joinpath(download_dir, "PlotReferenceImages.jl-$(version)")
if !isdir(refpath) # if not yet downloaded
@info "downloading reference images for version $version"
download(url, tarfile)
BinaryProvider.unpack(tarfile, download_dir)
# check again after download
if !isdir(refpath)
error("Something went wrong while downloading reference images. Plots can't be compared to references")
else
rm(tarfile, force = true)
end
else
@info "using reference images for version $version (already downloaded)"
end
refpath
end
const ref_image_dir = download_reference()
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2)
Plots._debugMode.on = debug Plots._debugMode.on = debug
example = Plots._examples[idx] example = Plots._examples[idx]
Plots.theme(:default) Plots.theme(:default)
@ -39,36 +11,9 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
# ensure consistent results # ensure consistent results
Random.seed!(1234) Random.seed!(1234)
# reference image directory setup
refdir = joinpath(ref_image_dir, "Plots", string(pkg))
fn = "ref$idx.png" fn = "ref$idx.png"
reffn = reference_file(pkg, idx, _current_plots_version)
# firgure out version info newfn = joinpath(reference_path(pkg, _current_plots_version), fn)
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
# test function # test function
func = (fn, idx) -> begin func = (fn, idx) -> begin
@ -78,13 +23,6 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
png(fn) png(fn)
end end
# try
# run(`mkdir -p $newdir`)
# catch err
# display(err)
# end
# # reffn = joinpath(refdir, "ref$idx.png")
# the test # the test
vtest = VisualTest(func, reffn, idx) vtest = VisualTest(func, reffn, idx)
test_images(vtest, popup=popup, sigma=sigma, tol=tol, newfn = newfn) 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) tol = 1e-2) # acceptable error (percent)
for i in 1:length(Plots._examples) for i in 1:length(Plots._examples)
i in skip && continue 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 @test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, tol=tol) |> success == true
end end
end end

View File

@ -1,16 +1,49 @@
import ImageMagick
using VisualRegressionTests using VisualRegressionTests
using Plots using Plots
using Random using Random
using BinaryProvider
using Test using Test
using FileIO using FileIO
using Gtk
using LibGit2
using GeometryTypes 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") include("imgcomp.jl")
# don't actually show the plots # don't actually show the plots
Random.seed!(1234) Random.seed!(1234)
default(show=false, reuse=true) 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 "Backends" begin
@testset "GR" begin @testset "GR" begin
ENV["PLOTS_TEST"] = "true" ENV["PLOTS_TEST"] = "true"
@ -19,11 +52,10 @@ img_tol = isinteractive() ? 1e-2 : 10e-2
@test backend() == Plots.GRBackend() @test backend() == Plots.GRBackend()
@static if Sys.islinux() @static if Sys.islinux()
image_comparison_facts(:gr, tol=img_tol, skip = [25, 30]) image_comparison_facts(:gr, tol=img_tol, skip = Plots._backend_skips[:gr])
end end
end end
@testset "UnicodePlots" begin @testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend() @test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend() @test backend() == Plots.UnicodePlotsBackend()
@ -37,6 +69,8 @@ end
@test isa(display(p), Nothing) == true @test isa(display(p), Nothing) == true
end end
end
@testset "Axes" begin @testset "Axes" begin
p = plot() p = plot()
axis = p.subplots[1][:xaxis] axis = p.subplots[1][:xaxis]
@ -61,6 +95,14 @@ end
for plt in plots for plt in plots
display(plt) display(plt)
end 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 end
@testset "Segments" begin @testset "Segments" begin
@ -90,6 +132,6 @@ end
[(missing,missing)], [(missing,missing,missing),("a","b","c")]) [(missing,missing)], [(missing,missing,missing),("a","b","c")])
for z in zipped for z in zipped
@test isequal(collect(zip(Plots.unzip(z)...)), z) @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
end end

166
test/test_pgfplotsx.jl Normal file
View File

@ -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