Compare commits

..

2 Commits

Author SHA1 Message Date
SimonDanisch 5b6d7d10d4 use correct revision 2019-01-31 18:50:20 +01:00
SimonDanisch 71cf37cc16 use name 2019-01-31 18:27:54 +01:00
50 changed files with 1851 additions and 5210 deletions
-24
View File
@@ -1,24 +0,0 @@
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()'
-11
View File
@@ -1,11 +0,0 @@
name: TagBot
on:
schedule:
- cron: 0 * * * *
jobs:
TagBot:
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
-1
View File
@@ -7,4 +7,3 @@ examples/meetup/.ipynb_checkpoints/*
deps/plotly-latest.min.js
deps/build.log
deps/deps.jl
Manifest.toml
+43 -17
View File
@@ -4,31 +4,57 @@ os:
- linux
# - osx
julia:
- 1
- 1.3
# - 1.0
- nightly
# matrix:
# allow_failures:
# - julia: nightly
matrix:
allow_failures:
- julia: nightly
# # before install:
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install wkhtmltopdf; fi
addons:
apt:
packages:
- at-spi2-core
- libgtk-3-dev
- xauth
- xvfb
# ref: http://askubuntu.com/a/556672 for the wkhtmltopdf apt repository info
sudo: required
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./test/install_wkhtmltoimage.sh ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:pov/wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltopdf -V ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltoimage -V ; fi
# echo 'exec xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@"' | sudo tee /usr/local/bin/wkhtmltopdf.sh >/dev/null
# sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh
# # borrowed from Blink.jl's travis file
# matrix:
# include:
# - os: linux
# julia: 0.4
# env: TESTCMD="xvfb-run julia"
# - os: osx
# julia: 0.4
# env: TESTCMD="julia"
notifications:
email: true
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)'
# uncomment the following lines to override the default test script
# script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'import Pkg; Pkg.add(Pkg.PackageSpec(path=pwd())); Pkg.build("Plots")'
# - julia test/travis_commands.jl
# - julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("GR"); Pkg.build("GR")'
# # - julia -e 'Pkg.clone("https://github.com/tbreloff/ImageMagick.jl.git"); Pkg.checkout("ImageMagick","tb_write"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");'
# # - julia -e 'Pkg.clone("https://github.com/JunoLab/Blink.jl.git"); Pkg.build("Blink"); import Blink; Blink.AtomShell.install()'
# # - julia -e 'Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")'
# - julia -e 'ENV["PYTHON"] = ""; Pkg.add("PyPlot"); Pkg.build("PyPlot")'
#
# # - $TESTCMD -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'Pkg.test("Plots"; coverage=false)'
# # - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'
+6 -107
View File
@@ -3,115 +3,14 @@
#### notes on release changes, ongoing development, and future planned work
- Minor version 0.17 is the last one to support Julia 0.6!!
- Minor version 0.11 is the last one to support Julia 0.5!!
- Critical bugfixes only
- `backports` branch is for Julia 0.5
---
## (current master)
## 0.28.3
- support generalized array interface
- save to pdf, svg and eps in plotlyjs
- fix for clims in line_z
- optimize heatmap logic in gr
## 0.26.3
- fix `vline` with dates
- fix PyPlot logscale bug
- avoid annotation clipping for PyPlot
- allow plotting of Any vectors and 3D plotting again in convertToAnyVector
- specify legend title font in GR and PyPlot
- delete `pushtomaster.sh`
- use `=== nothing`
## 0.26.2
- improve empty animation build error
- fix GR axis flip for heatmaps and images
- fix ribbons specified as tuples
- add Char recipe
- fix Plotly plots with single-element series
- rewrite PlotlyJS backend
## 0.26.1
- handle `Char`s as input data
- fix html saving for Plotly
- expand ~ in paths on UNIX systems
- convertToAnyVector clean-up
- fix color_palette grouping issue
## 0.26.0
- use FFMPEG.jl
- add missing method for convertToAnyVector
## 0.25.3
- add areaplot
- allow missing in z_color arguments
- more general tuple recipe
- stephist logscale improvements
## 0.25.2
- improvements to handle missings
- pyplot: allow setting the color gradient for z values
- document :colorbar_entry
- limit number of automatic bins
- fix ENV['PLOTS_DEFAULT_BACKEND']
- don't let aspect_ratio impact subplot size
- implement arrowstyle for GR
- fix bug in plotly_convert_to_datetime
- improve missing support
- gr: polar heatmaps
- make sure show returns nothing
## 0.25.1
- fix gr_display
## 0.25.0
- Replace StaticArrays with GeometryTypes
- Contour fixes for GR
## 0.24.0
- Update to the new PyCall and PyPlot API
- fix drawing of ticks
- fix y label position with GR
## 0.23.2
- pyplot fixes
- Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend.
- fix ticks
- support plotly json mime
- fix image axis limits
- default to radius 0 at center for polar plots
## 0.23.1
- slightly faster load time
- fixed errant MethodError
- fix bar plots with unicodeplots
- better colorbars for contour
- add volume seriestype for GR
- fix passing a tuple to custom ticks
- add vline to pgfplots
- add tex output for pyplot
- better 3d axis labels for GR
## 0.23.0
- compatible with StatPlots -> StatsPlots name shift
- fix histograms for vectors with NaN and Inf
- change gif behaviour (remove cache-busting)
- improved docstrings for shorthands functions
- fix font rotation for pyplot
- fix greyscale images for pyplot
- clamp greyscale images with values outside 0,1
- support keyword argument for font options
- allow vector of markers for pyplot scatter
## 0.22.5
- improve behaviour of plotlyjs backend
## 0.22.4
- Add support for discrete contourf plots with GR
## 0.22.3
- Fix the `showtheme` function
## 0.22.2
- Allow annotations to accept a Tuple instead of the result of a text call (making it possible to specify font characteristics in recipes). E.g. `annotations = (2, 4, ("test", :right, 8, :red))` is the same as `annotations = (2, 4, text("test", :right, 8, :red))`
## 0.22.1
- push PlotsDisplay just after REPLDisplay
-69
View File
@@ -1,69 +0,0 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.29.1"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
Contour = "0.5"
FFMPEG = "0.2"
FixedPointNumbers = "0.6, 0.7, 0.8"
GR = "0.46"
GeometryTypes = "0.7"
JSON = "0.21"
Measures = "0.3"
NaNMath = "0.3"
PGFPlotsX = "1.2.0"
PlotThemes = "1"
PlotUtils = "0.6.1"
RecipesBase = "0.8"
Reexport = "0.2"
Requires = "0.5, 1.0"
Showoff = "0.3.1"
StatsBase = "0.32"
julia = "1"
[extras]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925"
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
[targets]
test = ["FileIO", "GeometryTypes", "Gtk", "ImageMagick", "Images", "LaTeXStrings", "LibGit2", "PGFPlotsX", "Random", "RDatasets", "StatsPlots", "Test", "UnicodePlots", "VisualRegressionTests"]
+1 -1
View File
@@ -11,7 +11,7 @@
#### Created by Tom Breloff (@tbreloff)
#### Maintained by the [JuliaPlots members](https://github.com/orgs/JuliaPlots/people)
#### Maintained by the [JuliaPlot members](https://github.com/orgs/JuliaPlots/people)
Plots is a plotting API and toolset. My goals with the package are:
+16
View File
@@ -0,0 +1,16 @@
julia 1.0
RecipesBase 0.6.0
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
StaticArrays 0.5
FixedPointNumbers 0.3
Measures
Showoff
StatsBase 0.14.0
JSON
NaNMath
Requires
Contour
GR 0.37.0
-1
View File
@@ -2,7 +2,6 @@ environment:
matrix:
# - julia_version: 0.7
- julia_version: 1
- julia_version: 1.3
- julia_version: nightly
platform:
-51
View File
@@ -1,51 +0,0 @@
# 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)
+4
View File
@@ -0,0 +1,4 @@
git checkout master
git merge --ff-only dev
git push origin master
git checkout dev
+4 -9
View File
@@ -1,17 +1,15 @@
module Plots
const _current_plots_version = VersionNumber(split(first(filter(line -> occursin("version", line), readlines(normpath(@__DIR__, "..", "Project.toml")))), "\"")[2])
_current_plots_version = v"0.20.6"
using Reexport
import GeometryTypes
import StaticArrays
using Dates, Printf, Statistics, Base64, LinearAlgebra, Random
import SparseArrays: findnz
using FFMPEG
@reexport using RecipesBase
import RecipesBase: plot, plot!, animate, is_explicit
import RecipesBase: plot, plot!, animate
using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
@@ -189,7 +187,7 @@ include("backends/plotly.jl")
include("backends/gr.jl")
include("backends/web.jl")
include("shorthands.jl")
include("shorthands.jl")
let PlotOrSubplot = Union{Plot, Subplot}
global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
@@ -222,7 +220,4 @@ end
const CURRENT_BACKEND = CurrentBackend(:none)
include("precompile.jl")
_precompile_()
end # module
+14 -36
View File
@@ -60,39 +60,31 @@ end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim, fn, false; kw...)
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
ffmpeg_framerate(fps) = "$fps"
ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)"
function buildanimation(anim::Animation, fn::AbstractString,
function buildanimation(animdir::AbstractString, fn::AbstractString,
is_animated_gif::Bool=true;
fps::Real = 20, loop::Integer = 0,
fps::Integer = 20, loop::Integer = 0,
variable_palette::Bool=false,
show_msg::Bool=true)
if length(anim.frames) == 0
throw(ArgumentError("Cannot build empty animations"))
end
fn = abspath(expanduser(fn))
animdir = anim.dir
framerate = ffmpeg_framerate(fps)
fn = abspath(fn)
if is_animated_gif
if variable_palette
# generate a colorpalette for each frame for highest quality, but larger filesize
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1"
ffmpeg_exe(`-v 0 -framerate $framerate -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
else
# generate a colorpalette first so ffmpeg does not have to guess it
ffmpeg_exe(`-v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
run(`ffmpeg -v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
# then apply the palette to get better results
ffmpeg_exe(` -v 0 -framerate $framerate -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
end
else
ffmpeg_exe(`-v 0 -framerate $framerate -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
end
show_msg && @info("Saved animation to ", fn)
@@ -104,27 +96,13 @@ end
# write out html to view the gif
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
ext = file_extension(agif.filename)
if ext == "gif"
html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />"
write(io, if ext == "gif"
"<img src=\"$(relpath(agif.filename))\" />"
elseif ext in ("mov", "mp4")
mimetype = ext == "mov" ? "video/quicktime" : "video/mp4"
html = "<video controls><source src=\"data:$mimetype;base64," *
base64encode(read(agif.filename)) *
"\" type = \"$mimetype\"></video>"
"<video controls><source src=\"$(relpath(agif.filename)) type=\"video/$ext\"></video>"
else
error("Cannot show animation with extension $ext: $agif")
end
write(io, html)
return nothing
end
# Only gifs can be shown via image/gif
Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif"
function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif)
open(fio-> write(io, fio), agif.filename)
end)
end
-11
View File
@@ -42,7 +42,6 @@ const _arg_desc = KW(
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).",
:weights => "AbstractVector. Used in histogram types for weighted counts.",
:show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default).",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:contour_labels => "Bool. Show labels at the contour lines?",
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
@@ -50,7 +49,6 @@ const _arg_desc = KW(
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
:colorbar_entry => "Bool. Include this series in the color bar? Set to `false` to exclude.",
# plot args
:plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)",
@@ -65,7 +63,6 @@ const _arg_desc = KW(
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
:tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.",
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
:dpi => "Number. Dots Per Inch of output figures",
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
@@ -96,16 +93,9 @@ const _arg_desc = KW(
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
:legendtitlefontsize => "Integer. Font pointsize the legend title.",
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
:legendtitlefontrotation => "Real. Font rotation of the legend title",
:legendtitlefontcolor => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.",
:legendtitlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
:projection => "Symbol or String. '3d' or 'polar'",
:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.",
@@ -159,5 +149,4 @@ const _arg_desc = KW(
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`",
:widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.",
:draw_arrow => "Bool. Draw arrow at the end of the axis.",
)
+148 -185
View File
@@ -90,7 +90,7 @@ like_surface(seriestype::Symbol) = seriestype in _surface_like
is3d(seriestype::Symbol) = seriestype in _3dTypes
is3d(series::Series) = is3d(series.plotattributes)
is3d(plotattributes::AKW) = trueOrAllTrue(is3d, Symbol(plotattributes[:seriestype]))
is3d(plotattributes::KW) = trueOrAllTrue(is3d, Symbol(plotattributes[:seriestype]))
is3d(sp::Subplot) = string(sp.attr[:projection]) == "3d"
ispolar(sp::Subplot) = string(sp.attr[:projection]) == "polar"
@@ -232,7 +232,6 @@ const _bar_width = 0.8
const _series_defaults = KW(
:label => "AUTO",
:colorbar_entry => true,
:seriescolor => :auto,
:seriesalpha => nothing,
:seriestype => :path,
@@ -272,7 +271,6 @@ const _series_defaults = KW(
:arrow => nothing, # allows for adding arrows to line/path... call `arrow(args...)`
:normalize => false, # do we want a normalized histogram?
:weights => nothing, # optional weights for histograms (1D and 2D)
:show_empty_bins => false, # should empty bins in 2D histogram be colored as zero (otherwise they are transparent)
:contours => false, # add contours to 3d surface and wireframe plots
:contour_labels => false,
:match_dimensions => false, # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196
@@ -300,7 +298,6 @@ const _plot_defaults = KW(
:link => :none,
:overwrite_figure => true,
:html_output_format => :auto,
:tex_output_standalone => false,
:inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are
# the parent layout and the relative bounding box of inset subplots
:dpi => DPI, # dots per inch for images, etc
@@ -337,12 +334,6 @@ const _subplot_defaults = KW(
:legendfontvalign => :vcenter,
:legendfontrotation => 0.0,
:legendfontcolor => :match,
:legendtitlefontfamily => :match,
:legendtitlefontsize => 11,
:legendtitlefonthalign => :hcenter,
:legendtitlefontvalign => :vcenter,
:legendtitlefontrotation => 0.0,
:legendtitlefontcolor => :match,
:annotations => [], # annotation tuples... list of (x,y,annotation)
:projection => :none, # can also be :polar or :3d
:aspect_ratio => :none, # choose from :none or :equal
@@ -399,7 +390,6 @@ const _axis_defaults = KW(
:minorgrid => false,
:showaxis => true,
:widen => true,
:draw_arrow => false,
)
const _suppress_warnings = Set{Symbol}([
@@ -418,26 +408,37 @@ const _suppress_warnings = Set{Symbol}([
# add defaults for the letter versions
const _axis_defaults_byletter = KW()
for letter in (:x,:y,:z)
for k in keys(_axis_defaults)
# for k in (
# :guide,
# :lims,
# :ticks,
# :scale,
# :rotation,
# :flip,
# :link,
# :tickfont,
# :guidefont,
# :foreground_color_axis,
# :foreground_color_border,
# :foreground_color_text,
# :foreground_color_guide,
# :discrete_values,
# :formatter,
# )
_axis_defaults_byletter[Symbol(letter,k)] = :match
function reset_axis_defaults_byletter!()
for letter in (:x,:y,:z)
_axis_defaults_byletter[letter] = KW()
for (k,v) in _axis_defaults
_axis_defaults_byletter[letter][k] = v
end
# allow the underscore version too: xguide or x_guide
add_aliases(Symbol(letter, k), Symbol(letter, "_", k))
end
end
reset_axis_defaults_byletter!()
for letter in (:x,:y,:z), k in keys(_axis_defaults)
# allow the underscore version too: xguide or x_guide
add_aliases(Symbol(letter, k), Symbol(letter, "_", k))
end
const _all_defaults = KW[
_series_defaults,
_plot_defaults,
_subplot_defaults
_subplot_defaults,
_axis_defaults_byletter
]
const _initial_defaults = deepcopy(_all_defaults)
@@ -446,18 +447,11 @@ const _initial_axis_defaults = deepcopy(_axis_defaults)
# to be able to reset font sizes to initial values
const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize],
:legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize])
const _all_args = sort(collect(union(map(keys, _all_defaults)...)))
is_subplot_attr(k) = haskey(_subplot_defaults, k)
is_series_attr(k) = haskey(_series_defaults, k)
#is_axis_attr(k) = haskey(_axis_defaults_byletter, k)
is_axis_attr(k) = haskey(_axis_defaults, Symbol(chop(string(k); head=1, tail=0)))
is_axis_attr_noletter(k) = haskey(_axis_defaults, k)
RecipesBase.is_key_supported(k::Symbol) = is_attr_supported(k)
# -----------------------------------------------------------------------------
@@ -470,7 +464,7 @@ autopick(notarr, idx::Integer) = notarr
autopick_ignore_none_auto(arr::AVec, idx::Integer) = autopick(setdiff(arr, [:none, :auto]), idx)
autopick_ignore_none_auto(notarr, idx::Integer) = notarr
function aliasesAndAutopick(plotattributes::AKW, sym::Symbol, aliases::Dict{Symbol,Symbol}, options::AVec, plotIndex::Int)
function aliasesAndAutopick(plotattributes::KW, sym::Symbol, aliases::Dict{Symbol,Symbol}, options::AVec, plotIndex::Int)
if plotattributes[sym] == :auto
plotattributes[sym] = autopick_ignore_none_auto(options, plotIndex)
elseif haskey(aliases, plotattributes[sym])
@@ -577,7 +571,6 @@ add_aliases(:xerror, :xerr, :xerrorbar)
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized)
add_aliases(:show_empty_bins, :showemptybins, :showempty, :show_empty)
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
add_aliases(:match_dimensions, :transpose, :transpose_z)
add_aliases(:subplot, :sp, :subplt, :splt)
@@ -606,16 +599,6 @@ end
# -----------------------------------------------------------------------------
function parse_axis_kw(s::Symbol)
s = string(s)
for letter in ('x', 'y', 'z')
if startswith(s, letter)
return (Symbol(letter), Symbol(chop(s, head=1, tail=0)))
end
end
return nothing
end
# update the defaults globally
"""
@@ -634,10 +617,6 @@ function default(k::Symbol)
if haskey(_axis_defaults, k)
return _axis_defaults[k]
end
if (axis_k = parse_axis_kw(k)) !== nothing
letter, key = axis_k
return _axis_defaults_byletter[letter][key]
end
k in _suppress_warnings || error("Unknown key: ", k)
end
@@ -653,11 +632,6 @@ function default(k::Symbol, v)
_axis_defaults[k] = v
return v
end
if (axis_k = parse_axis_kw(k)) !== nothing
letter, key = axis_k
_axis_defaults_byletter[letter][key] = v
return v
end
k in _suppress_warnings || error("Unknown key: ", k)
end
@@ -669,20 +643,19 @@ function default(; kw...)
end
end
function default(plotattributes::AKW, k::Symbol)
function default(plotattributes::KW, k::Symbol)
get(plotattributes, k, default(k))
end
function reset_defaults()
foreach(merge!, _all_defaults, _initial_defaults)
merge!(_axis_defaults, _initial_axis_defaults)
reset_axis_defaults_byletter!()
end
# -----------------------------------------------------------------------------
# if arg is a valid color value, then set plotattributes[csym] and return true
function handleColors!(plotattributes::AKW, arg, csym::Symbol)
function handleColors!(plotattributes::KW, arg, csym::Symbol)
try
if arg == :auto
plotattributes[csym] = :auto
@@ -699,7 +672,7 @@ end
function processLineArg(plotattributes::AKW, arg)
function processLineArg(plotattributes::KW, arg)
# seriestype
if allLineTypes(arg)
plotattributes[:seriestype] = arg
@@ -709,15 +682,15 @@ function processLineArg(plotattributes::AKW, arg)
plotattributes[:linestyle] = arg
elseif typeof(arg) <: Stroke
arg.width === nothing || (plotattributes[:linewidth] = arg.width)
arg.color === nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:linealpha] = arg.alpha)
arg.style === nothing || (plotattributes[:linestyle] = arg.style)
arg.width == nothing || (plotattributes[:linewidth] = arg.width)
arg.color == nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:linealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:linestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
arg.size == nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows)
plotattributes[:arrow] = arg
@@ -738,7 +711,7 @@ function processLineArg(plotattributes::AKW, arg)
end
function processMarkerArg(plotattributes::AKW, arg)
function processMarkerArg(plotattributes::KW, arg)
# markershape
if allShapes(arg)
plotattributes[:markershape] = arg
@@ -748,24 +721,20 @@ function processMarkerArg(plotattributes::AKW, arg)
plotattributes[:markerstrokestyle] = arg
elseif typeof(arg) <: Stroke
arg.width === nothing || (plotattributes[:markerstrokewidth] = arg.width)
arg.color === nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
arg.style === nothing || (plotattributes[:markerstrokestyle] = arg.style)
arg.width == nothing || (plotattributes[:markerstrokewidth] = arg.width)
arg.color == nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:markerstrokestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size === nothing || (plotattributes[:markersize] = arg.size)
arg.color === nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:markeralpha] = arg.alpha)
arg.size == nothing || (plotattributes[:markersize] = arg.size)
arg.color == nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markeralpha] = arg.alpha)
# linealpha
elseif allAlphas(arg)
plotattributes[:markeralpha] = arg
# bool
elseif typeof(arg) <: Bool
plotattributes[:markershape] = arg ? :circle : :none
# markersize
elseif allReals(arg)
plotattributes[:markersize] = arg
@@ -778,12 +747,12 @@ function processMarkerArg(plotattributes::AKW, arg)
end
function processFillArg(plotattributes::AKW, arg)
function processFillArg(plotattributes::KW, arg)
# fr = get(plotattributes, :fillrange, 0)
if typeof(arg) <: Brush
arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
arg.size == nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Bool
plotattributes[:fillrange] = arg ? 0 : nothing
@@ -801,6 +770,7 @@ function processFillArg(plotattributes::AKW, arg)
plotattributes[:fillrange] = arg
elseif !handleColors!(plotattributes, arg, :fillcolor)
plotattributes[:fillrange] = arg
end
# plotattributes[:fillrange] = fr
@@ -808,7 +778,7 @@ function processFillArg(plotattributes::AKW, arg)
end
function processGridArg!(plotattributes::AKW, arg, letter)
function processGridArg!(plotattributes::KW, arg, letter)
if arg in _allGridArgs || isa(arg, Bool)
plotattributes[Symbol(letter, :grid)] = hasgrid(arg, letter)
@@ -816,10 +786,10 @@ function processGridArg!(plotattributes::AKW, arg, letter)
plotattributes[Symbol(letter, :gridstyle)] = arg
elseif typeof(arg) <: Stroke
arg.width === nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style === nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
arg.width == nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
# linealpha
elseif allAlphas(arg)
@@ -836,7 +806,7 @@ function processGridArg!(plotattributes::AKW, arg, letter)
end
end
function processMinorGridArg!(plotattributes::AKW, arg, letter)
function processMinorGridArg!(plotattributes::KW, arg, letter)
if arg in _allGridArgs || isa(arg, Bool)
plotattributes[Symbol(letter, :minorgrid)] = hasgrid(arg, letter)
@@ -845,10 +815,10 @@ function processMinorGridArg!(plotattributes::AKW, arg, letter)
plotattributes[Symbol(letter, :minorgrid)] = true
elseif typeof(arg) <: Stroke
arg.width === nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
arg.style === nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
arg.width == nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
plotattributes[Symbol(letter, :minorgrid)] = true
# linealpha
@@ -869,7 +839,7 @@ function processMinorGridArg!(plotattributes::AKW, arg, letter)
end
end
function processFontArg!(plotattributes::AKW, fontname::Symbol, arg)
function processFontArg!(plotattributes::KW, fontname::Symbol, arg)
T = typeof(arg)
if T <: Font
plotattributes[Symbol(fontname, :family)] = arg.family
@@ -906,7 +876,7 @@ _replace_markershape(shape::Symbol) = get(_markerAliases, shape, shape)
_replace_markershape(shapes::AVec) = map(_replace_markershape, shapes)
_replace_markershape(shape) = shape
function _add_markershape(plotattributes::AKW)
function _add_markershape(plotattributes::KW)
# add the markershape if it needs to be added... hack to allow "m=10" to add a shape,
# and still allow overriding in _apply_recipe
ms = pop!(plotattributes, :markershape_to_add, :none)
@@ -916,7 +886,7 @@ function _add_markershape(plotattributes::AKW)
end
"Handle all preprocessing of args... break out colors/sizes/etc and replace aliases."
function preprocessArgs!(plotattributes::AKW)
function preprocessArgs!(plotattributes::KW)
replaceAliases!(plotattributes, _keyAliases)
# clear all axis stuff
@@ -936,7 +906,7 @@ function preprocessArgs!(plotattributes::AKW)
# end
# handle axis args common to all axis
args = pop_kw!(plotattributes, :axis, ())
args = pop!(plotattributes, :axis, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
process_axis_arg!(plotattributes, arg, letter)
@@ -945,7 +915,7 @@ function preprocessArgs!(plotattributes::AKW)
# handle axis args
for letter in (:x, :y, :z)
asym = Symbol(letter, :axis)
args = pop_kw!(plotattributes, asym, ())
args = pop!(plotattributes, asym, ())
if !(typeof(args) <: Axis)
for arg in wraptuple(args)
process_axis_arg!(plotattributes, arg, letter)
@@ -953,17 +923,8 @@ function preprocessArgs!(plotattributes::AKW)
end
end
# vline accesses the y argument but actually maps it to the x axis.
# Hence, we have to swap formatters
if get(plotattributes, :seriestype, :path) == :vline
xformatter = get(plotattributes, :xformatter, :auto)
yformatter = get(plotattributes, :yformatter, :auto)
plotattributes[:xformatter] = yformatter
plotattributes[:yformatter] = xformatter
end
# handle grid args common to all axes
args = pop_kw!(plotattributes, :grid, ())
args = pop!(plotattributes, :grid, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
processGridArg!(plotattributes, arg, letter)
@@ -972,13 +933,13 @@ function preprocessArgs!(plotattributes::AKW)
# handle individual axes grid args
for letter in (:x, :y, :z)
gridsym = Symbol(letter, :grid)
args = pop_kw!(plotattributes, gridsym, ())
args = pop!(plotattributes, gridsym, ())
for arg in wraptuple(args)
processGridArg!(plotattributes, arg, letter)
end
end
# handle minor grid args common to all axes
args = pop_kw!(plotattributes, :minorgrid, ())
args = pop!(plotattributes, :minorgrid, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
processMinorGridArg!(plotattributes, arg, letter)
@@ -987,21 +948,21 @@ function preprocessArgs!(plotattributes::AKW)
# handle individual axes grid args
for letter in (:x, :y, :z)
gridsym = Symbol(letter, :minorgrid)
args = pop_kw!(plotattributes, gridsym, ())
args = pop!(plotattributes, gridsym, ())
for arg in wraptuple(args)
processMinorGridArg!(plotattributes, arg, letter)
end
end
# fonts
for fontname in (:titlefont, :legendfont, :legendtitlefont)
args = pop_kw!(plotattributes, fontname, ())
for fontname in (:titlefont, :legendfont)
args = pop!(plotattributes, fontname, ())
for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg)
end
end
# handle font args common to all axes
for fontname in (:tickfont, :guidefont)
args = pop_kw!(plotattributes, fontname, ())
args = pop!(plotattributes, fontname, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
processFontArg!(plotattributes, Symbol(letter, fontname), arg)
@@ -1011,7 +972,7 @@ function preprocessArgs!(plotattributes::AKW)
# handle individual axes font args
for letter in (:x, :y, :z)
for fontname in (:tickfont, :guidefont)
args = pop_kw!(plotattributes, Symbol(letter, fontname), ())
args = pop!(plotattributes, Symbol(letter, fontname), ())
for arg in wraptuple(args)
processFontArg!(plotattributes, Symbol(letter, fontname), arg)
end
@@ -1019,7 +980,7 @@ function preprocessArgs!(plotattributes::AKW)
end
# handle line args
for arg in wraptuple(pop_kw!(plotattributes, :line, ()))
for arg in wraptuple(pop!(plotattributes, :line, ()))
processLineArg(plotattributes, arg)
end
@@ -1033,7 +994,7 @@ function preprocessArgs!(plotattributes::AKW)
processMarkerArg(plotattributes, arg)
anymarker = true
end
reset_kw!(plotattributes, :marker)
delete!(plotattributes, :marker)
if haskey(plotattributes, :markershape)
plotattributes[:markershape] = _replace_markershape(plotattributes[:markershape])
if plotattributes[:markershape] == :none && plotattributes[:seriestype] in (:scatter, :scatterbins, :scatterhist, :scatter3d) #the default should be :auto, not :none, so that :none can be set explicitly and would be respected
@@ -1047,7 +1008,7 @@ function preprocessArgs!(plotattributes::AKW)
for arg in wraptuple(get(plotattributes, :fill, ()))
processFillArg(plotattributes, arg)
end
reset_kw!(plotattributes, :fill)
delete!(plotattributes, :fill)
# handle series annotations
if haskey(plotattributes, :series_annotations)
@@ -1062,7 +1023,7 @@ function preprocessArgs!(plotattributes::AKW)
arrow()
elseif a in (false, nothing, :none)
nothing
elseif !(typeof(a) <: Arrow || typeof(a) <: AbstractArray{Arrow})
elseif !(typeof(a) <: Arrow)
arrow(wraptuple(a)...)
else
a
@@ -1112,7 +1073,7 @@ function extractGroupArgs(v::AVec, args...; legendEntry = string)
if n > 100
@warn("You created n=$n groups... Is that intended?")
end
groupIds = Vector{Int}[filter(i -> v[i] == glab, eachindex(v)) for glab in groupLabels]
groupIds = Vector{Int}[filter(i -> v[i] == glab, 1:length(v)) for glab in groupLabels]
GroupBy(map(legendEntry, groupLabels), groupIds)
end
@@ -1120,7 +1081,7 @@ legendEntryFromTuple(ns::Tuple) = join(ns, ' ')
# this is when given a tuple of vectors of values to group by
function extractGroupArgs(vs::Tuple, args...)
isempty(vs) && return GroupBy([""], [axes(args[1],1)])
isempty(vs) && return GroupBy([""], [1:size(args[1],1)])
v = map(tuple, vs...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end
@@ -1130,7 +1091,7 @@ legendEntryFromTuple(ns::NamedTuple) =
join(["$k = $v" for (k, v) in pairs(ns)], ", ")
function extractGroupArgs(vs::NamedTuple, args...)
isempty(vs) && return GroupBy([""], [axes(args[1],1)])
isempty(vs) && return GroupBy([""], [1:size(args[1],1)])
v = map(NamedTuple{keys(vs)}tuple, values(vs)...)
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end
@@ -1145,15 +1106,15 @@ end
filter_data(v::AVec, idxfilter::AVec{Int}) = v[idxfilter]
filter_data(v, idxfilter) = v
function filter_data!(plotattributes::AKW, idxfilter)
function filter_data!(plotattributes::KW, idxfilter)
for s in (:x, :y, :z)
plotattributes[s] = filter_data(get(plotattributes, s, nothing), idxfilter)
end
end
function _filter_input_data!(plotattributes::AKW)
function _filter_input_data!(plotattributes::KW)
idxfilter = pop!(plotattributes, :idxfilter, nothing)
if idxfilter !== nothing
if idxfilter != nothing
filter_data!(plotattributes, idxfilter)
end
end
@@ -1164,7 +1125,7 @@ end
const _already_warned = Dict{Symbol,Set{Symbol}}()
const _to_warn = Set{Symbol}()
function warnOnUnsupported_args(pkg::AbstractBackend, plotattributes)
function warnOnUnsupported_args(pkg::AbstractBackend, plotattributes::KW)
empty!(_to_warn)
bend = backend_name(pkg)
already_warned = get!(_already_warned, bend, Set{Symbol}())
@@ -1188,7 +1149,7 @@ end
# _markershape_supported(pkg::AbstractBackend, shape::Shape) = Shape in supported_markers(pkg)
# _markershape_supported(pkg::AbstractBackend, shapes::AVec) = all([_markershape_supported(pkg, shape) for shape in shapes])
function warnOnUnsupported(pkg::AbstractBackend, plotattributes)
function warnOnUnsupported(pkg::AbstractBackend, plotattributes::KW)
if !is_seriestype_supported(pkg, plotattributes[:seriestype])
@warn("seriestype $(plotattributes[:seriestype]) is unsupported with $pkg. Choose from: $(supported_seriestypes(pkg))")
end
@@ -1200,7 +1161,7 @@ function warnOnUnsupported(pkg::AbstractBackend, plotattributes)
end
end
function warnOnUnsupported_scales(pkg::AbstractBackend, plotattributes::AKW)
function warnOnUnsupported_scales(pkg::AbstractBackend, plotattributes::KW)
for k in (:xscale, :yscale, :zscale, :scale)
if haskey(plotattributes, k)
v = plotattributes[k]
@@ -1219,7 +1180,7 @@ function convertLegendValue(val::Symbol)
:best
elseif val in (:no, :none)
:none
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright, :outertopleft, :outertop, :outerright, :outerleft, :outerbottomright, :outerbottomleft, :outerbottom)
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright)
val
else
error("Invalid symbol for legend: $val")
@@ -1239,26 +1200,24 @@ convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
# anything else is returned as-is
function slice_arg(v::AMat, idx::Int)
c = mod1(idx, size(v,2))
m,n = axes(v)
size(v,1) == 1 ? v[first(m),n[c]] : v[:,n[c]]
size(v,1) == 1 ? v[1,c] : v[:,c]
end
slice_arg(wrapper::InputWrapper, idx) = wrapper.obj
slice_arg(v, idx) = v
# given an argument key (k), extract the argument value for this index,
# and set into plotattributes[k]. Matrices are sliced by column.
# if nothing is set (or container is empty), return the existing value.
function slice_arg!(plotattributes_in, plotattributes_out,
k::Symbol, idx::Int, remove_pair::Bool)
v = get(plotattributes_in, k, plotattributes_out[k])
plotattributes_out[k] = if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v)
# given an argument key (k), we want to extract the argument value for this index.
# matrices are sliced by column, otherwise we
# if nothing is set (or container is empty), return the default or the existing value.
function slice_arg!(plotattributes_in::KW,plotattributes_out::KW, k::Symbol, default_value, idx::Int, remove_pair::Bool)
v = get(plotattributes_in, k, get(plotattributes_out, k, default_value))
plotattributes_out[k] = if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v)
slice_arg(v, idx)
else
v
end
if remove_pair
reset_kw!(plotattributes_in, k)
delete!(plotattributes_in, k)
end
return
end
@@ -1267,20 +1226,26 @@ end
# # if the value is `:match` then we take whatever match_color is.
# # this is mainly used for cascading defaults for foreground and background colors
# function color_or_match!(plotattributes::AKW, k::Symbol, match_color)
# function color_or_match!(plotattributes::KW, k::Symbol, match_color)
# v = plotattributes[k]
# plotattributes[k] = if v == :match
# match_color
# elseif v === nothing
# elseif v == nothing
# plot_color(RGBA(0,0,0,0))
# else
# v
# end
# end
function color_or_nothing!(plotattributes, k::Symbol)
function color_or_nothing!(plotattributes::KW, k::Symbol)
v = plotattributes[k]
plotattributes[k] = v == :match ? v : plot_color(v)
plotattributes[k] = if v == nothing || v == false
RGBA{Float64}(0,0,0,0)
elseif v != :match
plot_color(v)
else
v
end
return
end
@@ -1299,10 +1264,8 @@ const _match_map = KW(
:bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot,
:legendfontfamily => :fontfamily_subplot,
:legendtitlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot,
:legendfontcolor => :foreground_color_subplot,
:legendtitlefontcolor => :foreground_color_subplot,
:tickfontcolor => :foreground_color_text,
:guidefontcolor => :foreground_color_guide,
)
@@ -1379,18 +1342,18 @@ Base.get(series::Series, k::Symbol, v) = get(series.plotattributes, k, v)
# -----------------------------------------------------------------------------
function fg_color(plotattributes::AKW)
fg = get(plotattributes, :foreground_color, :auto)
function fg_color(plotattributes::KW)
fg = default(plotattributes, :foreground_color)
if fg == :auto
bg = plot_color(get(plotattributes, :background_color, :white))
bg = plot_color(default(plotattributes, :background_color))
fg = isdark(bg) ? colorant"white" : colorant"black"
else
plot_color(fg)
end
end
function fg_color_sp(plotattributes::AKW)
fgsp = get(plotattributes, :foreground_color_subplot, :match)
function fg_color_sp(plotattributes::KW)
fgsp = default(plotattributes, :foreground_color_subplot)
if fg == :match
fg_color(plotattributes)
else
@@ -1401,13 +1364,13 @@ end
# update attr from an input dictionary
function _update_plot_args(plt::Plot, plotattributes_in::AKW)
function _update_plot_args(plt::Plot, plotattributes_in::KW)
for (k,v) in _plot_defaults
slice_arg!(plotattributes_in, plt.attr, k, 1, true)
slice_arg!(plotattributes_in, plt.attr, k, v, 1, true)
end
# handle colors
plotattributes= plt.attr
plotattributes= plt.attr
plt[:background_color] = plot_color(plotattributes[:background_color])
plt[:foreground_color] = fg_color(plotattributes)
# bg = plot_color(plt.attr[:background_color])
@@ -1454,7 +1417,7 @@ function _update_subplot_colors(sp::Subplot)
return
end
function _update_axis(plt::Plot, sp::Subplot, plotattributes_in::AKW, letter::Symbol, subplot_index::Int)
function _update_axis(plt::Plot, sp::Subplot, plotattributes_in::KW, letter::Symbol, subplot_index::Int)
# get (maybe initialize) the axis
axis = get_axis(sp, letter)
@@ -1470,13 +1433,13 @@ function _update_axis(plt::Plot, sp::Subplot, plotattributes_in::AKW, letter::Sy
return
end
function _update_axis(axis::Axis, plotattributes_in::AKW, letter::Symbol, subplot_index::Int)
function _update_axis(axis::Axis, plotattributes_in::KW, letter::Symbol, subplot_index::Int)
# grab magic args (for example `xaxis = (:flip, :log)`)
args = wraptuple(get(plotattributes_in, Symbol(letter, :axis), ()))
# build the KW of arguments from the letter version (i.e. xticks --> ticks)
kw = KW()
for k in keys(_axis_defaults)
for (k,v) in _axis_defaults
# first get the args without the letter: `tickfont = font(10)`
# note: we don't pop because we want this to apply to all axes! (delete after all have finished)
if haskey(plotattributes_in, k)
@@ -1521,12 +1484,12 @@ function _update_axis_links(plt::Plot, axis::Axis, letter::Symbol)
end
# update a subplots args and axes
function _update_subplot_args(plt::Plot, sp::Subplot, plotattributes_in, subplot_index::Int, remove_pair::Bool)
anns = pop_kw!(sp.attr, :annotations)
function _update_subplot_args(plt::Plot, sp::Subplot, plotattributes_in::KW, subplot_index::Int, remove_pair::Bool)
anns = pop!(sp.attr, :annotations, [])
# # grab those args which apply to this subplot
for k in keys(_subplot_defaults)
slice_arg!(plotattributes_in, sp.attr, k, subplot_index, remove_pair)
# grab those args which apply to this subplot
for (k,v) in _subplot_defaults
slice_arg!(plotattributes_in, sp.attr, k, v, subplot_index, remove_pair)
end
_update_subplot_periphery(sp, anns)
@@ -1545,42 +1508,45 @@ function has_black_border_for_default(st::Symbol)
like_histogram(st) || st in (:hexbin, :bar, :shape)
end
# converts a symbol or string into a Colorant or ColorGradient
# and assigns a color automatically
function get_series_color(c, sp::Subplot, n::Int, seriestype)
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
function getSeriesRGBColor(c, sp::Subplot, n::Int)
if c == :auto
c = like_surface(seriestype) ? cgrad() : autopick(sp[:color_palette], n)
c = autopick(sp[:color_palette], n)
elseif isa(c, Int)
c = autopick(sp[:color_palette], c)
end
plot_color(c)
end
function get_series_color(c::AbstractArray, sp::Subplot, n::Int, seriestype)
map(x->get_series_color(x, sp, n, seriestype), c)
function getSeriesRGBColor(c::AbstractArray, sp::Subplot, n::Int)
map(x->getSeriesRGBColor(x, sp, n), c)
end
function ensure_gradient!(plotattributes::AKW, csym::Symbol, asym::Symbol)
function ensure_gradient!(plotattributes::KW, csym::Symbol, asym::Symbol)
if !isa(plotattributes[csym], ColorGradient)
plotattributes[csym] = typeof(plotattributes[asym]) <: AbstractVector ? cgrad() : cgrad(alpha = plotattributes[asym])
end
end
function _replace_linewidth(plotattributes::AKW)
function _replace_linewidth(plotattributes::KW)
# get a good default linewidth... 0 for surface and heatmaps
if plotattributes[:linewidth] == :auto
if get(plotattributes, :linewidth, :auto) == :auto
plotattributes[:linewidth] = (get(plotattributes, :seriestype, :path) in (:surface,:heatmap,:image) ? 0 : 1)
end
end
function _slice_series_args!(plotattributes::AKW, plt::Plot, sp::Subplot, commandIndex::Int)
for k in keys(_series_defaults)
haskey(plotattributes, k) && slice_arg!(plotattributes, plotattributes, k, commandIndex, false)
function _add_defaults!(plotattributes::KW, plt::Plot, sp::Subplot, commandIndex::Int)
# add default values to our dictionary, being careful not to delete what we just added!
for (k,v) in _series_defaults
slice_arg!(plotattributes, plotattributes, k, v, commandIndex, false)
end
return plotattributes
end
function _update_series_attributes!(plotattributes::AKW, plt::Plot, sp::Subplot)
function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
pkg = plt.backend
globalIndex = plotattributes[:series_plotindex]
plotIndex = _series_index(plotattributes, sp)
@@ -1590,32 +1556,30 @@ function _update_series_attributes!(plotattributes::AKW, plt::Plot, sp::Subplot)
# update alphas
for asym in (:linealpha, :markeralpha, :fillalpha)
if plotattributes[asym] === nothing
if plotattributes[asym] == nothing
plotattributes[asym] = plotattributes[:seriesalpha]
end
end
if plotattributes[:markerstrokealpha] === nothing
if plotattributes[:markerstrokealpha] == nothing
plotattributes[:markerstrokealpha] = plotattributes[:markeralpha]
end
# update series color
scolor = plotattributes[:seriescolor]
stype = plotattributes[:seriestype]
plotattributes[:seriescolor] = scolor = get_series_color(scolor, sp, plotIndex, stype)
plotattributes[:seriescolor] = getSeriesRGBColor(plotattributes[:seriescolor], sp, plotIndex)
# update other colors
for s in (:line, :marker, :fill)
csym, asym = Symbol(s,:color), Symbol(s,:alpha)
plotattributes[csym] = if plotattributes[csym] == :auto
plot_color(if has_black_border_for_default(stype) && s == :line
plot_color(if has_black_border_for_default(plotattributes[:seriestype]) && s == :line
sp[:foreground_color_subplot]
else
scolor
plotattributes[:seriescolor]
end)
elseif plotattributes[csym] == :match
plot_color(scolor)
plot_color(plotattributes[:seriescolor])
else
get_series_color(plotattributes[csym], sp, plotIndex, stype)
getSeriesRGBColor(plotattributes[csym], sp, plotIndex)
end
end
@@ -1623,19 +1587,19 @@ function _update_series_attributes!(plotattributes::AKW, plt::Plot, sp::Subplot)
plotattributes[:markerstrokecolor] = if plotattributes[:markerstrokecolor] == :match
plot_color(sp[:foreground_color_subplot])
elseif plotattributes[:markerstrokecolor] == :auto
get_series_color(plotattributes[:markercolor], sp, plotIndex, stype)
getSeriesRGBColor(plotattributes[:markercolor], sp, plotIndex)
else
get_series_color(plotattributes[:markerstrokecolor], sp, plotIndex, stype)
getSeriesRGBColor(plotattributes[:markerstrokecolor], sp, plotIndex)
end
# if marker_z, fill_z or line_z are set, ensure we have a gradient
if plotattributes[:marker_z] !== nothing
if plotattributes[:marker_z] != nothing
ensure_gradient!(plotattributes, :markercolor, :markeralpha)
end
if plotattributes[:line_z] !== nothing
if plotattributes[:line_z] != nothing
ensure_gradient!(plotattributes, :linecolor, :linealpha)
end
if plotattributes[:fill_z] !== nothing
if plotattributes[:fill_z] != nothing
ensure_gradient!(plotattributes, :fillcolor, :fillalpha)
end
@@ -1650,7 +1614,6 @@ function _update_series_attributes!(plotattributes::AKW, plt::Plot, sp::Subplot)
# set label
label = plotattributes[:label]
label = (label == "AUTO" ? "y$globalIndex" : label)
label = label in (:none, nothing, false) ? "" : label
plotattributes[:label] = label
_replace_linewidth(plotattributes)
+121 -388
View File
@@ -7,20 +7,29 @@
# -------------------------------------------------------------------------
function Axis(sp::Subplot, letter::Symbol, args...; kw...)
explicit = KW(
# init with values from _plot_defaults
plotattributes = KW(
:letter => letter,
# :extrema => (Inf, -Inf),
:extrema => Extrema(),
:discrete_map => Dict(), # map discrete values to discrete indices
:continuous_values => zeros(0),
:discrete_values => [],
:use_minor => false,
:show => true, # show or hide the axis? (useful for linked subplots)
)
attr = Attr(explicit, _axis_defaults_byletter[letter])
# get defaults from letter version, unless match
for (k,v) in _axis_defaults
lk = Symbol(letter, k)
lv = _axis_defaults_byletter[lk]
plotattributes[k] = (lv == :match ? v : lv)
end
# merge!(plotattributes, _axis_defaults)
plotattributes[:discrete_values] = []
# update the defaults
attr!(Axis([sp], attr), args...; kw...)
attr!(Axis([sp], plotattributes), args...; kw...)
end
function get_axis(sp::Subplot, letter::Symbol)
@@ -32,7 +41,7 @@ function get_axis(sp::Subplot, letter::Symbol)
end::Axis
end
function process_axis_arg!(plotattributes::AKW, arg, letter = "")
function process_axis_arg!(plotattributes::KW, arg, letter = "")
T = typeof(arg)
arg = get(_scaleAliases, arg, arg)
@@ -58,7 +67,7 @@ function process_axis_arg!(plotattributes::AKW, arg, letter = "")
elseif T <: AVec
plotattributes[Symbol(letter,:ticks)] = arg
elseif arg === nothing
elseif arg == nothing
plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs
@@ -108,7 +117,7 @@ end
# -------------------------------------------------------------------------
Base.show(io::IO, axis::Axis) = dumpdict(io, axis.plotattributes, "Axis", true)
Base.show(io::IO, axis::Axis) = dumpdict(axis.plotattributes, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.plotattributes, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.plotattributes, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k)
@@ -143,8 +152,8 @@ scalefunc(scale::Symbol) = x -> get(_scale_funcs, scale, identity)(Float64(x))
invscalefunc(scale::Symbol) = x -> get(_inv_scale_funcs, scale, identity)(Float64(x))
labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string)
function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
amin, amax = axis_limits(sp, axis[:letter])
function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
amin,amax = axis_limits(axis)
# scale the limits
scale = axis[:scale]
@@ -157,7 +166,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
# or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
if ticks === nothing && scale == :identity
if ticks == nothing && scale == :identity
if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes
@@ -175,7 +184,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
end
# get a list of well-laid-out ticks
if ticks === nothing
if ticks == nothing
scaled_ticks = optimize_ticks(
sf(amin),
sf(amax);
@@ -209,8 +218,6 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :plain))
elseif formatter == :scientific
Showoff.showoff(unscaled_ticks, :scientific)
elseif formatter == :latex
map(x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"), Showoff.showoff(unscaled_ticks, :auto))
else
# there was an override for the formatter... use that on the unscaled ticks
map(formatter, unscaled_ticks)
@@ -231,9 +238,9 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
end
# return (continuous_values, discrete_values) for the ticks on this axis
function get_ticks(sp::Subplot, axis::Axis)
function get_ticks(axis::Axis)
ticks = _transform_ticks(axis[:ticks])
ticks in (:none, nothing, false) && return nothing
ticks in (nothing, false) && return nothing
# treat :native ticks as :auto
ticks = ticks == :native ? :auto : ticks
@@ -244,7 +251,7 @@ function get_ticks(sp::Subplot, axis::Axis)
# discrete ticks...
n = length(dvals)
rng = if ticks == :auto
Int[round(Int,i) for i in range(1, stop=n, length=min(n,15))]
Int[round(Int,i) for i in range(1, stop=n, length=15)]
else # if ticks == :all
1:n
end
@@ -254,7 +261,7 @@ function get_ticks(sp::Subplot, axis::Axis)
(collect(0:pi/4:7pi/4), string.(0:45:315))
else
# compute optimal ticks and labels
optimal_ticks_and_labels(sp, axis)
optimal_ticks_and_labels(axis)
end
elseif typeof(ticks) <: Union{AVec, Int}
if !isempty(dvals) && typeof(ticks) <: Int
@@ -262,7 +269,7 @@ function get_ticks(sp::Subplot, axis::Axis)
axis[:continuous_values][rng], dvals[rng]
else
# override ticks, but get the labels
optimal_ticks_and_labels(sp, axis, ticks)
optimal_ticks_and_labels(axis, ticks)
end
elseif typeof(ticks) <: NTuple{2, Any}
# assuming we're passed (ticks, labels)
@@ -279,16 +286,16 @@ _transform_ticks(ticks) = ticks
_transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.value.(ticks)
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2])
function get_minor_ticks(sp, axis, ticks)
axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing
function get_minor_ticks(axis,ticks)
axis[:minorticks] in (nothing, false) && !axis[:minorgrid] && return nothing
ticks = ticks[1]
length(ticks) < 2 && return nothing
amin, amax = axis_limits(sp, axis[:letter])
amin, amax = axis_limits(axis)
#Add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits
if length(ticks) > 2
ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1])
elseif axis[:scale] in (:none, :identity)
elseif axis[:scale] == :none
ratio = 1
else
return nothing
@@ -302,9 +309,7 @@ function get_minor_ticks(sp, axis, ticks)
minorticks = typeof(ticks[1])[]
for (i,hi) in enumerate(ticks[2:end])
lo = ticks[i]
if isfinite(lo) && hi > lo
append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
end
append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
end
minorticks[amin .<= minorticks .<= amax]
end
@@ -352,7 +357,7 @@ function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
end
function expand_extrema!(sp::Subplot, plotattributes::AKW)
function expand_extrema!(sp::Subplot, plotattributes::KW)
vert = isvertical(plotattributes)
# first expand for the data
@@ -377,7 +382,7 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
end
expand_extrema!(axis, data)
elseif data !== nothing
elseif data != nothing
# TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value)
@@ -394,10 +399,10 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
# expand for fillrange
fr = plotattributes[:fillrange]
if fr === nothing && plotattributes[:seriestype] == :bar
if fr == nothing && plotattributes[:seriestype] == :bar
fr = 0.0
end
if fr !== nothing && !all3D(plotattributes)
if fr != nothing && !all3D(plotattributes)
axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple
for fri in fr
@@ -414,7 +419,7 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
data = plotattributes[dsym]
bw = plotattributes[:bar_width]
if bw === nothing
if bw == nothing
bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end
axis = sp.attr[Symbol(dsym, :axis)]
@@ -474,13 +479,11 @@ function round_limits(amin,amax)
end
# using the axis extrema and limit overrides, return the min/max value for this axis
function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(letter, :axis)]), consider_aspect = true)
axis = sp[Symbol(letter, :axis)]
function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis))
ex = axis[:extrema]
amin, amax = ex.emin, ex.emax
lims = axis[:lims]
has_user_lims = (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2
if has_user_lims
if (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2
if isfinite(lims[1])
amin = lims[1]
end
@@ -494,12 +497,12 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l
if !isfinite(amin) && !isfinite(amax)
amin, amax = 0.0, 1.0
end
amin, amax = if ispolar(axis.sps[1])
if ispolar(axis.sps[1])
if axis[:letter] == :x
amin, amax = 0, 2pi
elseif lims == :auto
#widen max radius so ticks dont overlap with theta axis
0, amax + 0.1 * abs(amax - amin)
amin, amax + 0.1 * abs(amax - amin)
else
amin, amax
end
@@ -510,32 +513,6 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l
else
amin, amax
end
if !has_user_lims && consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || is3d(:sp))
aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1
plot_ratio = height(plotarea(sp)) / width(plotarea(sp))
dist = amax - amin
if letter == :x
yamin, yamax = axis_limits(sp, :y, default_should_widen(sp[:yaxis]), false)
ydist = yamax - yamin
axis_ratio = aspect_ratio * ydist / dist
factor = axis_ratio / plot_ratio
else
xamin, xamax = axis_limits(sp, :x, default_should_widen(sp[:xaxis]), false)
xdist = xamax - xamin
axis_ratio = aspect_ratio * dist / xdist
factor = plot_ratio / axis_ratio
end
if factor > 1
center = (amin + amax) / 2
amin = center + factor * (amin - center)
amax = center + factor * (amax - center)
end
end
return amin, amax
end
# -------------------------------------------------------------------------
@@ -568,10 +545,10 @@ end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AVec)
n = eachindex(v)
cvec = zeros(axes(v))
discrete_indices = similar(Array{Int}, axes(v))
for i in n
n = length(v)
cvec = zeros(n)
discrete_indices = zeros(Int, n)
for i=1:n
cvec[i], discrete_indices[i] = discrete_value!(axis, v[i])
end
cvec, discrete_indices
@@ -579,10 +556,10 @@ end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AMat)
n,m = axes(v)
cmat = zeros(axes(v))
discrete_indices = similar(Array{Int}, axes(v))
for i in n, j in m
n,m = size(v)
cmat = zeros(n,m)
discrete_indices = zeros(Int, n, m)
for i=1:n, j=1:m
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j])
end
cmat, discrete_indices
@@ -609,12 +586,12 @@ end
# compute the line segments which should be drawn for this axis
function axis_drawing_info(sp::Subplot)
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
xmin, xmax = axis_limits(sp, :x)
ymin, ymax = axis_limits(sp, :y)
xticks = get_ticks(sp, xaxis)
yticks = get_ticks(sp, yaxis)
xminorticks = get_minor_ticks(sp, xaxis, xticks)
yminorticks = get_minor_ticks(sp, yaxis, yticks)
xmin, xmax = axis_limits(xaxis)
ymin, ymax = axis_limits(yaxis)
xticks = get_ticks(xaxis)
yticks = get_ticks(yaxis)
xminorticks = get_minor_ticks(xaxis,xticks)
yminorticks = get_minor_ticks(yaxis,yticks)
xaxis_segs = Segments(2)
yaxis_segs = Segments(2)
xtick_segs = Segments(2)
@@ -628,370 +605,126 @@ function axis_drawing_info(sp::Subplot)
if sp[:framestyle] != :none
# xaxis
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
push!(xaxis_segs, (xmin, y1), (xmax, y1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
if sp[:framestyle] == :origin && !(xticks in (nothing,false)) && length(xticks) > 1
showticks = xticks[1] .!= 0
xticks = (xticks[1][showticks], xticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine
end
if !(xaxis[:ticks] in (:none, nothing, false))
if !(xaxis[:ticks] in (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
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(ymin) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t2 = invf(f(ymax) - 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
for xtick in xticks[1]
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
end
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
end
if !(xaxis[:minorticks] in (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)
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xminorticks
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
for xminortick in xminorticks
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
end
xaxis[:minorgrid] && push!(xminorgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
push!(xtick_segs, (xminortick, tick_start), (xminortick, tick_stop)) # bottom tick
end
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:minorgrid] && push!(xminorgrid_segs, (xminortick, ymin), (xminortick, ymax)) # vertical grid
end
end
# yaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
push!(yaxis_segs, (x1, ymin), (x1, ymax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
if sp[:framestyle] == :origin && !(yticks in (nothing,false)) && length(yticks) > 1
showticks = yticks[1] .!= 0
yticks = (yticks[1][showticks], yticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine
end
if !(yaxis[:ticks] in (:none, nothing, false))
if !(yaxis[:ticks] in (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
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(xmin) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t2 = invf(f(xmax) - 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
for ytick in yticks[1]
if yaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
end
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
if !(yaxis[:minorticks] in (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
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
for ytick in yminorticks
if yaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
end
yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
end
xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xminorgrid_segs, yminorgrid_segs, xborder_segs, yborder_segs
end
function axis_drawing_info_3d(sp::Subplot)
xaxis, yaxis, zaxis = sp[:xaxis], sp[:yaxis], sp[:zaxis]
xmin, xmax = axis_limits(sp, :x)
ymin, ymax = axis_limits(sp, :y)
zmin, zmax = axis_limits(sp, :z)
xticks = get_ticks(sp, xaxis)
yticks = get_ticks(sp, yaxis)
zticks = get_ticks(sp, zaxis)
xminorticks = get_minor_ticks(sp, xaxis, xticks)
yminorticks = get_minor_ticks(sp, yaxis, yticks)
zminorticks = get_minor_ticks(sp, zaxis, zticks)
xaxis_segs = Segments(3)
yaxis_segs = Segments(3)
zaxis_segs = Segments(3)
xtick_segs = Segments(3)
ytick_segs = Segments(3)
ztick_segs = Segments(3)
xgrid_segs = Segments(3)
ygrid_segs = Segments(3)
zgrid_segs = Segments(3)
xminorgrid_segs = Segments(3)
yminorgrid_segs = Segments(3)
zminorgrid_segs = Segments(3)
xborder_segs = Segments(3)
yborder_segs = Segments(3)
zborder_segs = Segments(3)
if sp[:framestyle] != :none
# xaxis
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
push!(xaxis_segs, (xmin, y1, z1), (xmax, y1, z1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
showticks = xticks[1] .!= 0
xticks = (xticks[1][showticks], xticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2, z2), (xmax, y2, z2)) # top spine
end
if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
(-t, t)
else
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xticks[1]
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
end
if xaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(xgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
push!(xgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
else
push!(xgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
push!(xgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
end
end
end
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xminorticks
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
end
if xaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(xminorgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
push!(xminorgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
else
push!(xminorgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
push!(xminorgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
end
end
end
end
end
# yaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmin, xmax) : (xmax, xmin)
end
z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
push!(yaxis_segs, (x1, ymin, z1), (x1, ymax, z1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
showticks = yticks[1] .!= 0
yticks = (yticks[1][showticks], yticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin, z2), (x2, ymax, z2)) # right spine
end
if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(xmax) - f(xmin)))
(-t, t)
else
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yticks[1]
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
end
if yaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(ygrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
push!(ygrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
else
push!(ygrid_segs, (x1, ytick, z1), (x2, ytick, z1))
push!(ygrid_segs, (x2, ytick, z1), (x2, ytick, z2))
end
end
end
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(xmax) - f(xmin)))
(-t, t)
else
t = invf(f(x1) + 0.006 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yminorticks
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
end
if yaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(yminorgrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
push!(yminorgrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
else
push!(yminorgrid_segs, (x1, ytick, z1), (x2, ytick, z1))
push!(yminorgrid_segs, (x2, ytick, z1), (x2, ytick, z2))
end
end
end
end
end
# zaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(zaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(zaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
if zaxis[:showaxis]
if sp[:framestyle] != :grid
push!(zaxis_segs, (x1, y1, zmin), (x1, y1, zmax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(zticks in (:none, nothing,false)) && length(zticks) > 1
showticks = zticks[1] .!= 0
zticks = (zticks[1][showticks], zticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(zborder_segs, (x2, y2, zmin), (x2, y2, zmax))
end
if !(zaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
(-t, t)
else
ticks_in = zaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for ztick in zticks[1]
if zaxis[:showaxis]
push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
end
if zaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(zgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
push!(ygrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
else
push!(ygrid_segs, (x1, y1, ztick), (x1, y2, ztick))
push!(ygrid_segs, (x1, y2, ztick), (x2, y2, ztick))
end
end
end
if !(zaxis[:minorticks] in (:none, nothing, false)) || zaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for ztick in zminorticks
if zaxis[:showaxis]
push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
end
if zaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(zminorgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
push!(zminorgrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
else
push!(zminorgrid_segs, (x1, y1, ztick), (x1, y2, ztick))
push!(zminorgrid_segs, (x1, y2, ztick), (x2, y2, ztick))
end
end
end
end
end
end
xticks, yticks, zticks, xaxis_segs, yaxis_segs, zaxis_segs, xtick_segs, ytick_segs, ztick_segs, xgrid_segs, ygrid_segs, zgrid_segs, xminorgrid_segs, yminorgrid_segs, zminorgrid_segs, xborder_segs, yborder_segs, zborder_segs
end
+22 -79
View File
@@ -37,6 +37,7 @@ macro init_backend(s)
_backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str)
_backend_packages[Symbol($str)] = Symbol($package_str)
# include("backends/" * $str * ".jl")
end)
end
@@ -74,9 +75,9 @@ end
text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(lab), sz, rot)
# account for the size/length/rotation of tick labels
function tick_padding(sp::Subplot, axis::Axis)
ticks = get_ticks(sp, axis)
if ticks === nothing
function tick_padding(axis::Axis)
ticks = get_ticks(axis)
if ticks == nothing
0mm
else
vals, labs = ticks
@@ -105,10 +106,10 @@ end
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot)
# TODO: something different when `is3d(sp) == true`
leftpad = tick_padding(sp, sp[:yaxis]) + sp[:left_margin] + guide_padding(sp[:yaxis])
leftpad = tick_padding(sp[:yaxis]) + sp[:left_margin] + guide_padding(sp[:yaxis])
toppad = sp[:top_margin] + title_padding(sp)
rightpad = sp[:right_margin]
bottompad = tick_padding(sp, sp[:xaxis]) + sp[:bottom_margin] + guide_padding(sp[:xaxis])
bottompad = tick_padding(sp[:xaxis]) + sp[:bottom_margin] + guide_padding(sp[:xaxis])
# switch them?
if sp[:xaxis][:mirror]
@@ -142,7 +143,12 @@ function _pick_default_backend()
if env_default != ""
sym = Symbol(lowercase(env_default))
if sym in _backends
backend(sym)
if sym in _initialized_backends
backend(sym)
else
@warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.")
_fallback_default_backend()
end
else
@warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" *
join(sort(_backends), "\n\t"))
@@ -228,7 +234,7 @@ const _base_supported_args = [
:subplot_index,
:discrete_values,
:projection,
:show_empty_bins
]
function merge_with_base_supported(v::AVec)
@@ -251,7 +257,6 @@ end
@init_backend PlotlyJS
@init_backend GR
@init_backend PGFPlots
@init_backend PGFPlotsX
@init_backend InspectDR
@init_backend HDF5
@@ -296,6 +301,9 @@ end
_initialize_backend(pkg::GRBackend) = nothing
_initialize_backend(pkg::PlotlyBackend) = nothing
# ------------------------------------------------------------------------------
# gr
@@ -324,7 +332,7 @@ const _gr_attr = merge_with_base_supported([
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
:guidefontrotation, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:legend, :legendtitle, :colorbar, :colorbar_title,
:fill_z, :line_z, :marker_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -343,7 +351,7 @@ const _gr_attr = merge_with_base_supported([
const _gr_seriestype = [
:path, :scatter, :straightline,
:heatmap, :pie, :image,
:contour, :path3d, :scatter3d, :surface, :wireframe, :volume,
:contour, :path3d, :scatter3d, :surface, :wireframe,
:shape
]
const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
@@ -354,16 +362,6 @@ is_marker_supported(::GRBackend, shape::Shape) = true
# ------------------------------------------------------------------------------
# plotly
function _initialize_backend(pkg::PlotlyBackend)
try
@eval Main begin
import ORCA
end
catch
@info "For saving to png with the Plotly backend ORCA has to be installed."
end
end
const _plotly_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
@@ -388,7 +386,7 @@ const _plotly_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridlinewidth,
:legend, :colorbar, :colorbar_title, :colorbar_entry,
:legend, :colorbar, :colorbar_title,
:marker_z, :fill_z, :line_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -419,8 +417,6 @@ const _plotly_marker = [
]
const _plotly_scale = [:identity, :log10]
defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html"
# ------------------------------------------------------------------------------
# pgfplots
@@ -461,7 +457,7 @@ const _pgfplots_attr = merge_with_base_supported([
])
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline] #vcat(_allMarkers, Shape)
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
# ------------------------------------------------------------------------------
@@ -513,7 +509,7 @@ const _pyplot_attr = merge_with_base_supported([
:tickfontfamily, :tickfontsize, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:legend, :legendtitle, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
@@ -526,6 +522,7 @@ const _pyplot_attr = merge_with_base_supported([
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
:stride,
:framestyle,
:tick_direction,
@@ -668,57 +665,3 @@ const _inspectdr_marker = Symbol[
]
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
# ------------------------------------------------------------------------------
# pgfplotsx
const _pgfplotsx_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
:foreground_color_text, :foreground_color_border,
:label,
:seriescolor, :seriesalpha,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha,
:bins,
:layout,
:title, :window_title,
:guide, :lims, :ticks, :scale, :flip,
:match_dimensions,
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
:titlefontrotation, :titlefontcolor,
:legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign,
:legendfontrotation, :legendfontcolor,
:tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign,
:tickfontrotation, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
:guidefontrotation, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:fill_z, :line_z, :marker_z, :levels,
:ribbon, :quiver,
:orientation,
:overwrite_figure,
:polar,
:aspect_ratio,
:normalize, :weights,
:inset_subplots,
:bar_width,
:arrow,
:framestyle,
:tick_direction,
:camera,
:contour_labels,
])
const _pgfplotsx_seriestype =
[:path, :scatter, :straightline,
:path3d, :scatter3d, :surface, :wireframe,
:heatmap, :contour, :contour3d,
:shape,
:steppre, :stepmid, :steppost, :ysticks, :xsticks]
const _pgfplotsx_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
const _pgfplotsx_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :ltriangle, :rtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline, Shape]
const _pgfplotsx_scale = [:identity, :ln, :log2, :log10]
is_marker_supported(::PGFPlotsXBackend, shape::Shape) = true
+315 -900
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -121,9 +121,9 @@ function _create_backend_figure(plt::Plot{InspectDRBackend})
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot !== nothing
if plt[:overwrite_figure] && mplot != nothing
mplot.subplots = [] #Reset
if gplot !== nothing #Ensure still references current plot
if gplot != nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
@@ -294,8 +294,8 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
plot.xscale = _inspectdr_getscale(xaxis[:scale], false)
strip.yscale = _inspectdr_getscale(yaxis[:scale], true)
xmin, xmax = axis_limits(sp, :x)
ymin, ymax = axis_limits(sp, :y)
xmin, xmax = axis_limits(xaxis)
ymin, ymax = axis_limits(yaxis)
if ispolar(sp)
#Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax)
rmax = NaNMath.max(abs(ymin), abs(ymax))
-24
View File
@@ -1,24 +0,0 @@
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
+28 -45
View File
@@ -26,8 +26,7 @@ const _pgfplots_markers = KW(
:star6 => "asterisk",
:diamond => "diamond*",
:pentagon => "pentagon*",
:hline => "-",
:vline => "|"
:hline => "-"
)
const _pgfplots_legend_pos = KW(
@@ -96,7 +95,7 @@ pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(plotattributes, i)
if fa !== nothing
if fa != nothing
a = fa
end
"fill = $cstr, fill opacity=$a"
@@ -128,18 +127,16 @@ function pgf_marker(plotattributes, i = 1)
shape = _cycle(plotattributes[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i)))
cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i)))
return string(
"mark = $(get(_pgfplots_markers, shape, "*")),\n",
"mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),\n",
plotattributes[:seriestype] == :scatter ? "only marks,\n" : "",
"mark options = {
color = $cstr_stroke, draw opacity = $a_stroke,
fill = $cstr, fill opacity = $a,
line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
}"
)
"""
mark = $(get(_pgfplots_markers, shape, "*")),
mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),
mark options = {
color = $cstr_stroke, draw opacity = $a_stroke,
fill = $cstr, fill opacity = $a,
line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
}"""
end
function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1)
@@ -173,18 +170,18 @@ function pgf_series(sp::Subplot, series::Series)
elseif st == :shape
shape_data(series)
elseif ispolar(sp)
theta, r = plotattributes[:x], plotattributes[:y]
theta, r = filter_radial_data(plotattributes[:x], plotattributes[:y], axis_limits(sp[:yaxis]))
rad2deg.(theta), r
else
plotattributes[:x], plotattributes[:y]
end
# PGFPlots can't handle non-Vector?
# args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
# collect(a)
# else
# a
# end, args)
args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
collect(a)
else
a
end, args)
if st in (:contour, :histogram2d)
style = []
@@ -218,12 +215,12 @@ function pgf_series(sp::Subplot, series::Series)
# add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if plotattributes[:fillrange] !== nothing
if plotattributes[:fillrange] != nothing
push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
else
kw[:legendentry] = plotattributes[:label]
if st == :shape # || plotattributes[:fillrange] !== nothing
if st == :shape # || plotattributes[:fillrange] != nothing
push!(style, "area legend")
end
end
@@ -240,7 +237,7 @@ function pgf_series(sp::Subplot, series::Series)
kw[:style] = join(style, ',')
# add fillrange
if series[:fillrange] !== nothing && st != :shape
if series[:fillrange] != nothing && st != :shape
push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
end
@@ -363,13 +360,13 @@ function pgf_axis(sp::Subplot, letter)
# limits
# TODO: support zlims
if letter != :z
lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, letter)
lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(axis)) : axis_limits(axis)
kw[Symbol(letter,:min)] = lims[1]
kw[Symbol(letter,:max)] = lims[2]
end
if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none
ticks = get_ticks(sp, axis)
ticks = get_ticks(axis)
#pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values
tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1]
push!(style, string(letter, "tick = {", join(tick_values,","), "}"))
@@ -401,12 +398,8 @@ function pgf_axis(sp::Subplot, letter)
# framestyle
if framestyle in (:axes, :origin)
axispos = framestyle == :axes ? "left" : "middle"
if axis[:draw_arrow]
push!(style, string("axis ", letter, " line = ", axispos))
else
# the * after line disables the arrow at the axis
push!(style, string("axis ", letter, " line* = ", axispos))
end
# the * after lines disables the arrows at the axes
push!(style, string("axis lines* = ", axispos))
end
if framestyle == :zerolines
@@ -478,18 +471,8 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos]
end
cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend]))
fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
push!(style, string(
"legend style = {",
pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], fg_alpha, "solid", ), ",",
"fill = $cstr,",
"fill opacity = $bg_alpha,",
"text opacity = $(alpha(plot_color(sp[:legendfontcolor]))),",
"font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)),
"}",
))
cstr, a = pgf_color(plot_color(sp[:background_color_legend]))
push!(style, string("legend style = {", pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], 1.0, "solid"), ",", "fill = $cstr,", "font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)), "}"))
if any(s[:seriestype] == :contour for s in series_list(sp))
kw[:view] = "{0}{90}"
@@ -580,7 +563,7 @@ end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone])
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
write(io, read(open(fn), String))
end
File diff suppressed because it is too large Load Diff
+50 -63
View File
@@ -26,6 +26,7 @@ const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js"
# end
using UUIDs
push!(_initialized_backends, :plotly)
# ----------------------------------------------------------------
const _plotly_legend_pos = KW(
@@ -113,8 +114,8 @@ function plotly_apply_aspect_ratio(sp::Subplot, plotarea, pcts)
if aspect_ratio == :equal
aspect_ratio = 1.0
end
xmin,xmax = axis_limits(sp, :x)
ymin,ymax = axis_limits(sp, :y)
xmin,xmax = axis_limits(sp[:xaxis])
ymin,ymax = axis_limits(sp[:yaxis])
want_ratio = ((xmax-xmin) / (ymax-ymin)) / aspect_ratio
parea_ratio = width(plotarea) / height(plotarea)
if want_ratio > parea_ratio
@@ -173,7 +174,7 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
ax[:tickangle] = -axis[:rotation]
ax[:type] = plotly_scale(axis[:scale])
lims = axis_limits(sp, letter)
lims = axis_limits(axis)
if axis[:ticks] != :native || axis[:lims] != :auto
ax[:range] = map(scalefunc(axis[:scale]), lims)
@@ -185,9 +186,14 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
# flip
if axis[:flip]
ax[:range] = reverse(ax[:range])
end
# ticks
if axis[:ticks] != :native
ticks = get_ticks(sp, axis)
ticks = get_ticks(axis)
ttype = ticksType(ticks)
if ttype == :ticks
ax[:tickmode] = "array"
@@ -202,24 +208,20 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
ax[:showgrid] = false
end
# flip
if axis[:flip]
ax[:range] = reverse(ax[:range])
end
ax
end
function plotly_polaraxis(sp::Subplot, axis::Axis)
function plotly_polaraxis(axis::Axis)
ax = KW(
:visible => axis[:showaxis],
:showline => axis[:grid],
)
if axis[:letter] == :x
ax[:range] = rad2deg.(axis_limits(sp, :x))
ax[:range] = rad2deg.(axis_limits(axis))
else
ax[:range] = axis_limits(sp, :y)
ax[:range] = axis_limits(axis)
ax[:orientation] = -90
end
@@ -282,8 +284,8 @@ function plotly_layout(plt::Plot)
),
)
elseif ispolar(sp)
plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis])
plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis])
plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis])
plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis])
else
plotattributes_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp)
# don't allow yaxis to be reupdated/reanchored in a linked subplot
@@ -346,14 +348,14 @@ function plotly_layout(plt::Plot)
end
function plotly_layout_json(plt::Plot)
JSON.json(plotly_layout(plt), 4)
JSON.json(plotly_layout(plt))
end
function plotly_colorscale(grad::ColorGradient, α)
[[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in eachindex(grad.colors)]
[[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)]
end
plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α)
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α)
if length(c) == 1
return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]]
@@ -392,7 +394,7 @@ end
# we split by NaNs and then construct/destruct the shapes to get the closed coords
function plotly_close_shapes(x, y)
xs, ys = nansplit(x), nansplit(y)
for i=eachindex(xs)
for i=1:length(xs)
shape = Shape(xs[i], ys[i])
xs[i], ys[i] = coords(shape)
end
@@ -402,7 +404,7 @@ end
function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)]
data = if axis[:ticks] == :native && data !== nothing
data = if axis[:ticks] == :native && data != nothing
plotly_native_data(axis, data)
else
data
@@ -414,8 +416,7 @@ function plotly_data(series::Series, letter::Symbol, data)
plotly_data(data)
end
end
plotly_data(v) = v !== nothing ? collect(v) : v
plotly_data(v::AbstractArray) = v
plotly_data(v) = v != nothing ? collect(v) : v
plotly_data(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
@@ -436,7 +437,7 @@ plotly_native_data(axis::Axis, a::Surface) = Surface(plotly_native_data(axis, a.
function plotly_convert_to_datetime(x::AbstractArray, formatter::Function)
if formatter == datetimeformatter
map(xi -> replace(formatter(xi), "T" => " "), x)
map(xi -> replace(formatter(xi), "T", " "), x)
elseif formatter == dateformatter
map(xi -> string(formatter(xi), " 00:00:00"), x)
elseif formatter == timeformatter
@@ -454,7 +455,7 @@ function plotly_series(plt::Plot, series::Series)
st = series[:seriestype]
sp = series[:subplot]
clims = get_clims(sp, series)
clims = get_clims(sp)
if st == :shape
return plotly_series_shapes(plt, series, clims)
@@ -469,7 +470,7 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showlegend] = should_add_to_legend(series)
if st == :straightline
x, y = straightline_data(series, 100)
x, y = straightline_data(series)
z = series[:z]
else
x, y, z = series[:x], series[:y], series[:z]
@@ -506,13 +507,13 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showscale] = hascolorbar(sp)
elseif st == :contour
filled = isfilledcontour(series)
plotattributes_out[:type] = "contour"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
plotattributes_out[:ncontours] = series[:levels] + 2
plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
# plotattributes_out[:showscale] = series[:colorbar] != :none
plotattributes_out[:ncontours] = series[:levels]
plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series)
plotattributes_out[:showscale] = hascolorbar(sp)
elseif st in (:surface, :wireframe)
plotattributes_out[:type] = "surface"
@@ -529,7 +530,7 @@ function plotly_series(plt::Plot, series::Series)
else
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] !== nothing
if series[:fill_z] != nothing
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
plotattributes_out[:showscale] = hascolorbar(sp)
@@ -584,7 +585,7 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
)
x, y = (plotly_data(series, letter, data)
for (letter, data) in zip((:x, :y), shape_data(series, 100))
for (letter, data) in zip((:x, :y), shape_data(series))
)
for (i,rng) in enumerate(segments)
@@ -611,11 +612,11 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[i] = plotattributes_out
end
if series[:fill_z] !== nothing
if series[:fill_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:line_z] !== nothing
elseif series[:line_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:marker_z] !== nothing
elseif series[:marker_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
plotattributes_outs
@@ -631,9 +632,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series)
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
plotattributes_outs = Vector{KW}(undef, (hasfillrange ? 2 : 1 ) * length(segments))
for (i,rng) in enumerate(segments)
!isscatter && length(rng) < 2 && continue
plotattributes_out = deepcopy(plotattributes_base)
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotattributes_out[:legendgroup] = series[:label]
@@ -733,11 +736,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
end
end
if series[:line_z] !== nothing
if series[:line_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:fill_z] !== nothing
elseif series[:fill_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:marker_z] !== nothing
elseif series[:marker_z] != nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
@@ -772,7 +775,7 @@ end
function plotly_polar!(plotattributes_out::KW, series::Series)
# convert polar plots x/y to theta/radius
if ispolar(series[:subplot])
theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
theta, r = filter_radial_data(pop!(plotattributes_out, :x), pop!(plotattributes_out, :y), axis_limits(series[:subplot][:yaxis]))
plotattributes_out[:t] = rad2deg.(theta)
plotattributes_out[:r] = r
end
@@ -780,9 +783,9 @@ end
function plotly_hover!(plotattributes_out::KW, hover)
# hover text
if hover === nothing || all(in([:none, false]), hover)
if hover in (:none, false)
plotattributes_out[:hoverinfo] = "none"
elseif any(!isnothing, hover)
elseif hover != nothing
plotattributes_out[:hoverinfo] = "text"
plotattributes_out[:text] = hover
end
@@ -798,16 +801,13 @@ function plotly_series(plt::Plot)
end
# get json string for a list of dictionaries, each representing the series params
plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt), 4)
plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt))
# ----------------------------------------------------------------
html_head(plt::Plot{PlotlyBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
const ijulia_initialized = Ref(false)
function plotly_html_head(plt::Plot)
function html_head(plt::Plot{PlotlyBackend})
local_file = ("file://" * plotly_local_file_path)
plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path
if isijulia() && !ijulia_initialized[]
@@ -823,11 +823,13 @@ function plotly_html_head(plt::Plot)
""")
ijulia_initialized[] = true
end
# IJulia just needs one initialization
isijulia() && return ""
return "<script src=$(repr(plotly))></script>"
end
function plotly_html_body(plt, style = nothing)
if style === nothing
function html_body(plt::Plot{PlotlyBackend}, style = nothing)
if style == nothing
w, h = plt[:size]
style = "width:$(w)px;height:$(h)px;"
end
@@ -842,36 +844,21 @@ function plotly_html_body(plt, style = nothing)
html
end
function js_body(plt::Plot, uuid)
function js_body(plt::Plot{PlotlyBackend}, uuid)
js = """
PLOT = document.getElementById('$(uuid)');
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
"""
end
function plotly_show_js(io::IO, plot::Plot)
data = []
for series in plot.series_list
append!(data, plotly_series(plot, series))
end
layout = plotly_layout(plot)
JSON.print(io, Dict(:data => data, :layout => layout))
end
# ----------------------------------------------------------------
Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot{PlotlyBackend}) = true
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))
write(io, html_head(plt) * html_body(plt))
end
function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt)
end
+58 -31
View File
@@ -1,44 +1,73 @@
# https://github.com/sglyon/PlotlyJS.jl
# ------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------
function plotlyjs_syncplot(plt::Plot{PlotlyJSBackend})
plt[:overwrite_figure] && closeall()
plt.o = PlotlyJS.plot()
traces = PlotlyJS.GenericTrace[]
for series_dict in plotly_series(plt)
plotly_type = pop!(series_dict, :type)
push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...))
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options)
else
PlotlyJS.plot()
end
PlotlyJS.addtraces!(plt.o, traces...)
layout = plotly_layout(plt)
w, h = plt[:size]
PlotlyJS.relayout!(plt.o, layout, width = w, height = h)
return plt.o
end
# ------------------------------------------------------------------------------
const _plotlyjs_mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"image/svg+xml" => "svg",
"image/eps" => "eps",
)
for (mime, fmt) in _plotlyjs_mimeformats
@eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
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
# 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 _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
html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt)
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, standalone_html(plt))
# ----------------------------------------------------------------
_display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt))
function _update_plot_object(plt::Plot{PlotlyJSBackend})
pdict = plotly_layout(plt)
syncplot = plt.o
w,h = plt[:size]
PlotlyJS.relayout!(syncplot, pdict, width = w, height = h)
end
# ----------------------------------------------------------------
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o)
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="svg")
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="png")
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf")
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps")
function write_temp_html(plt::Plot{PlotlyJSBackend})
filename = string(tempname(), ".html")
savefig(plt, filename)
filename
end
function _display(plt::Plot{PlotlyJSBackend})
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
display(plt.o)
else
standalone_html_window(plt)
end
end
@require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin
function WebIO.render(plt::Plot{PlotlyJSBackend})
@@ -52,5 +81,3 @@ function closeall(::PlotlyJSBackend)
close(current().o)
end
end
Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot{PlotlyJSBackend}) = true
+181 -239
View File
@@ -21,7 +21,7 @@ pyfont = PyPlot.pyimport("matplotlib.font_manager")
pyticker = PyPlot.pyimport("matplotlib.ticker")
pycmap = PyPlot.pyimport("matplotlib.cm")
pynp = PyPlot.pyimport("numpy")
pynp."seterr"(invalid="ignore")
pynp["seterr"](invalid="ignore")
pytransforms = PyPlot.pyimport("matplotlib.transforms")
pycollections = PyPlot.pyimport("matplotlib.collections")
pyart3d = PyPlot.art3D
@@ -34,11 +34,6 @@ else
:set_facecolor
end
# PyCall API changes in v1.90.0
if !isdefined(PyCall, :_setproperty!)
@warn "Plots no longer supports PyCall < 1.90.0 and PyPlot < 2.8.0. Either update PyCall and PyPlot or pin Plots to a version <= 0.23.2."
end
# # convert colorant to 4-tuple RGBA
# py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha))
@@ -69,17 +64,17 @@ py_color(c::Colorant, α) = py_color(plot_color(c, α))
function py_colormap(grad::ColorGradient)
pyvals = [(z, py_color(grad[z])) for z in grad.values]
cm = pycolors."LinearSegmentedColormap"."from_list"("tmp", pyvals)
cm."set_bad"(color=(0,0,0,0.0), alpha=0.0)
cm = pycolors["LinearSegmentedColormap"][:from_list]("tmp", pyvals)
cm[:set_bad](color=(0,0,0,0.0), alpha=0.0)
cm
end
py_colormap(c::Colorant) = py_colormap(_as_gradient(c))
py_colormap(c) = py_colormap(cgrad())
function py_shading(c, z)
cmap = py_colormap(c)
ls = pycolors."LightSource"(270,45)
ls."shade"(z, cmap, vert_exag=0.1, blend_mode="soft")
ls = pycolors["LightSource"](270,45)
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
end
# get the style (solid, dashed, etc)
@@ -102,7 +97,7 @@ function py_marker(marker::Shape)
mat[i,2] = y[i]
end
mat[n+1,:] = mat[1,:]
pypath."Path"(mat)
pypath["Path"](mat)
end
const _path_MOVETO = UInt8(1)
@@ -187,7 +182,7 @@ end
# end
function get_locator_and_formatter(vals::AVec)
pyticker."FixedLocator"(eachindex(vals)), pyticker."FixedFormatter"(vals)
pyticker["FixedLocator"](1:length(vals)), pyticker["FixedFormatter"](vals)
end
function add_pyfixedformatter(cbar, vals::AVec)
@@ -209,22 +204,20 @@ end
function py_mask_nans(z)
# pynp["ma"][:masked_invalid](z)))
PyCall.pycall(pynp."ma"."masked_invalid", Any, z)
PyCall.pycall(pynp["ma"][:masked_invalid], Any, z)
# pynp["ma"][:masked_where](pynp["isnan"](z),z)
end
# ---------------------------------------------------------------------------
function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
if series[:x] !== nothing
x, y = series[:x], series[:y]
nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
else
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end
x, y = series[:x], series[:y]
nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
else
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end
end
end
@@ -255,28 +248,26 @@ py_fillcolormap(series::Series) = py_colormap(series[:fillcolor])
# Figure utils -- F*** matplotlib for making me work so hard to figure this crap out
# the drawing surface
py_canvas(fig) = fig."canvas"
py_canvas(fig) = fig[:canvas]
# the object controlling draw commands
py_renderer(fig) = py_canvas(fig)."get_renderer"()
py_renderer(fig) = py_canvas(fig)[:get_renderer]()
# draw commands... paint the screen (probably updating internals too)
py_drawfig(fig) = fig."draw"(py_renderer(fig))
py_drawfig(fig) = fig[:draw](py_renderer(fig))
# py_drawax(ax) = ax[:draw](py_renderer(ax[:get_figure]()))
# get a vector [left, right, bottom, top] in PyPlot coords (origin is bottom-left!)
py_extents(obj) = obj."get_window_extent"()."get_points"()
py_extents(obj) = obj[:get_window_extent]()[:get_points]()
# compute a bounding box (with origin top-left), however pyplot gives coords with origin bottom-left
function py_bbox(obj)
fl, fr, fb, ft = py_extents(obj."get_figure"())
fl, fr, fb, ft = py_extents(obj[:get_figure]())
l, r, b, t = py_extents(obj)
BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px)
end
py_bbox(::Nothing) = BoundingBox(0mm, 0mm)
# get the bounding box of the union of the objects
function py_bbox(v::AVec)
bbox_union = defaultbox
@@ -288,13 +279,13 @@ end
# bounding box: union of axis tick labels
function py_bbox_ticks(ax, letter)
labels = getproperty(ax, Symbol("get_"*letter*"ticklabels"))()
labels = ax[Symbol("get_"*letter*"ticklabels")]()
py_bbox(labels)
end
# bounding box: axis guide
function py_bbox_axislabel(ax, letter)
pyaxis_label = getproperty(ax, Symbol("get_"*letter*"axis"))().label
pyaxis_label = ax[Symbol("get_"*letter*"axis")]()[:label]
py_bbox(pyaxis_label)
end
@@ -310,14 +301,11 @@ end
function py_bbox_title(ax)
bb = defaultbox
for s in (:title, :_left_title, :_right_title)
bb = bb + py_bbox(getproperty(ax, s))
bb = bb + py_bbox(ax[s])
end
bb
end
# bounding box: legend
py_bbox_legend(ax) = py_bbox(ax."get_legend"())
function py_thickness_scale(plt::Plot{PyPlotBackend}, ptsz)
ptsz * plt[:thickness_scaling]
end
@@ -351,7 +339,7 @@ function py_init_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
proj = (proj in (nothing,:none) ? nothing : string(proj))
# add a new axis, and force it to create a new one by setting a distinct label
ax = fig."add_axes"(
ax = fig[:add_axes](
[0,0,1,1],
label = string(gensym()),
projection = proj
@@ -383,23 +371,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
elseif st == :shape
x, y = shape_data(series)
end
if ispolar(series)
# make negative radii positive and flip the angle
# (PyPlot ignores negative radii)
for i in eachindex(y)
if y[i] < 0
y[i] = -y[i]
x[i] -= π
end
end
end
xyargs = (st in _3dTypes ? (x,y,z) : (x,y))
# handle zcolor and get c/cmap
needs_colorbar = hascolorbar(sp)
vmin, vmax = clims = get_clims(sp, series)
vmin, vmax = clims = get_clims(sp)
# Dict to store extra kwargs
if st == :wireframe
@@ -434,7 +410,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if maximum(series[:linewidth]) > 0
segments = iter_segments(series)
# TODO: check LineCollection alternative for speed
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] !== nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] != nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
# # multicolored line segments
# n = length(segments)
# # segments = Array(Any,n)
@@ -464,10 +440,10 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# push!(handles, handle)
# else
for (i, rng) in enumerate(iter_segments(series))
handle = ax."plot"((arg[rng] for arg in xyargs)...;
handle = ax[:plot]((arg[rng] for arg in xyargs)...;
label = i == 1 ? series[:label] : "",
zorder = series[:series_plotindex],
color = py_color(single_color(get_linecolor(series, clims, i)), get_linealpha(series, i)),
color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
linewidth = py_thickness_scale(plt, get_linewidth(series, i)),
linestyle = py_linestyle(st, get_linestyle(series, i)),
solid_capstyle = "round",
@@ -478,7 +454,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# end
a = series[:arrow]
if a !== nothing && !is3d(st) # TODO: handle 3d later
if a != nothing && !is3d(st) # TODO: handle 3d later
if typeof(a) != Arrow
@warn("Unexpected type for arrow: $(typeof(a))")
else
@@ -492,7 +468,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
:linestyle => py_linestyle(st, get_linestyle(series)),
)
add_arrows(x, y) do xyprev, xy
ax."annotate"("",
ax[:annotate]("",
xytext = (0.001xyprev[1] + 0.999xy[1], 0.001xyprev[2] + 0.999xy[2]),
xy = xy,
arrowprops = arrowprops,
@@ -508,7 +484,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:markershape] != :none && st in (:path, :scatter, :path3d,
:scatter3d, :steppre, :steppost,
:bar)
markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] !== nothing
markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] != nothing
# py_color(plot_color.(get_markercolor.(series, clims, eachindex(x)), get_markeralpha.(series, eachindex(x))))
[py_color(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) for i in eachindex(x)]
else
@@ -535,10 +511,10 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
shapes = series[:markershape]
msc = py_markerstrokecolor(series)
lw = py_thickness_scale(plt, series[:markerstrokewidth])
for i=eachindex(y)
for i=1:length(y)
extrakw[:c] = _cycle(markercolor, i)
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i);
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(_cycle(shapes,i)),
@@ -564,7 +540,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
delete!(extrakw, :c)
for i=eachindex(y)
for i=1:length(y)
cur_marker = py_marker(_cycle(shapes,i))
if ( cur_marker == prev_marker )
@@ -577,7 +553,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
continue
end
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
push!(handle, ax[:scatter](cur_x_list, cur_y_list;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = prev_marker,
@@ -598,7 +574,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if !isempty(cur_color_list)
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
push!(handle, ax[:scatter](cur_x_list, cur_y_list;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = prev_marker,
@@ -613,7 +589,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
else
# do a normal scatter plot
handle = ax."scatter"(xyargs...;
handle = ax[:scatter](xyargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(series[:markershape]),
@@ -627,7 +603,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if st == :hexbin
handle = ax."hexbin"(x, y;
handle = ax[:hexbin](x, y;
label = series[:label],
zorder = series[:series_plotindex],
gridsize = series[:bins],
@@ -659,7 +635,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
# contour lines
handle = ax."contour"(x, y, z, levelargs...;
handle = ax[:contour](x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex],
linewidths = py_thickness_scale(plt, series[:linewidth]),
@@ -667,13 +643,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw...
)
if series[:contour_labels] == true
PyPlot."clabel"(handle, handle.levels)
PyPlot.clabel(handle, handle[:levels])
end
push!(handles, handle)
# contour fills
if series[:fillrange] !== nothing
handle = ax."contourf"(x, y, z, levelargs...;
if series[:fillrange] != nothing
handle = ax[:contourf](x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
extrakw...
@@ -691,7 +667,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
z = transpose_z(series, z)
if st == :surface
if series[:fill_z] !== nothing
if series[:fill_z] != nothing
# the surface colors are different than z-value
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
extrakw[:shade] = false
@@ -699,7 +675,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:cmap] = py_fillcolormap(series)
end
end
handle = getproperty(ax, st == :surface ? :plot_surface : :plot_wireframe)(x, y, z;
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
label = series[:label],
zorder = series[:series_plotindex],
rstride = series[:stride][1],
@@ -714,7 +690,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:contours]
for (zdir,mat) in (("x",x), ("y",y), ("z",z))
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat)
handle = ax."contourf"(x, y, z, levelargs...;
handle = ax[:contourf](x, y, z, levelargs...;
zdir = zdir,
cmap = py_fillcolormap(series),
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane
@@ -726,7 +702,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
elseif typeof(z) <: AbstractVector
# tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots)
handle = ax."plot_trisurf"(x, y, z;
handle = ax[:plot_trisurf](x, y, z;
label = series[:label],
zorder = series[:series_plotindex],
cmap = py_fillcolormap(series),
@@ -751,17 +727,17 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
else
z # hopefully it's in a data format that will "just work" with imshow
end
handle = ax."imshow"(z;
handle = ax[:imshow](z;
zorder = series[:series_plotindex],
cmap = py_colormap(cgrad([:black, :white])),
vmin = 0.0,
vmax = 1.0,
extent = (xmin-0.5, xmax+0.5, ymax+0.5, ymin-0.5)
extent = (xmin, xmax, ymax, ymin)
)
push!(handles, handle)
# expand extrema... handle is AxesImage object
xmin, xmax, ymax, ymin = handle."get_extent"()
xmin, xmax, ymax, ymin = handle[:get_extent]()
expand_extrema!(sp, xmin, xmax, ymin, ymax)
# sp[:yaxis].series[:flip] = true
end
@@ -776,7 +752,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
discrete_colorbar_values = dvals
end
handle = ax."pcolormesh"(x, y, py_mask_nans(z);
handle = ax[:pcolormesh](x, y, py_mask_nans(z);
label = series[:label],
zorder = series[:series_plotindex],
cmap = py_fillcolormap(series),
@@ -791,8 +767,8 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
handle = []
for (i, rng) in enumerate(iter_segments(series))
if length(rng) > 1
path = pypath."Path"(hcat(x[rng], y[rng]))
patches = pypatches."PathPatch"(
path = pypath["Path"](hcat(x[rng], y[rng]))
patches = pypatches["PathPatch"](
path;
label = series[:label],
zorder = series[:series_plotindex],
@@ -802,14 +778,14 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
linestyle = py_linestyle(st, get_linestyle(series, i)),
fill = true
)
push!(handle, ax."add_patch"(patches))
push!(handle, ax[:add_patch](patches))
end
end
push!(handles, handle)
end
if st == :pie
handle = ax."pie"(y;
handle = ax[:pie](y;
# colors = # a vector of colors?
labels = pie_labels(sp, series)
)[1]
@@ -830,7 +806,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# handle area filling
fillrange = series[:fillrange]
if fillrange !== nothing && st != :contour
if fillrange != nothing && st != :contour
for (i, rng) in enumerate(iter_segments(series))
f, dim1, dim2 = if isvertical(series)
:fill_between, x[rng], y[rng]
@@ -844,7 +820,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
dim1, _cycle(fillrange[1], rng), _cycle(fillrange[2], rng)
end
handle = getproperty(ax, f)(args..., trues(n), false, py_fillstepstyle(st);
handle = ax[f](args..., trues(n), false, py_fillstepstyle(st);
zorder = series[:series_plotindex],
facecolor = py_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
linewidths = 0
@@ -862,36 +838,36 @@ end
# --------------------------------------------------------------------------
function py_set_lims(ax, sp::Subplot, axis::Axis)
function py_set_lims(ax, axis::Axis)
letter = axis[:letter]
lfrom, lto = axis_limits(sp, letter)
getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto)
lfrom, lto = axis_limits(axis)
ax[Symbol("set_", letter, "lim")](lfrom, lto)
end
function py_set_ticks(ax, ticks, letter)
ticks == :auto && return
axis = getproperty(ax, Symbol(letter,"axis"))
if ticks == :none || ticks === nothing || ticks == false
axis = ax[Symbol(letter,"axis")]
if ticks == :none || ticks == nothing || ticks == false
kw = KW()
for dir in (:top,:bottom,:left,:right)
kw[dir] = kw[Symbol(:label,dir)] = false
end
axis."set_tick_params"(;which="both", kw...)
axis[:set_tick_params](;which="both", kw...)
return
end
ttype = ticksType(ticks)
if ttype == :ticks
axis."set_ticks"(ticks)
axis[:set_ticks](ticks)
elseif ttype == :ticks_and_labels
axis."set_ticks"(ticks[1])
axis."set_ticklabels"(ticks[2])
axis[:set_ticks](ticks[1])
axis[:set_ticklabels](ticks[2])
else
error("Invalid input for $(letter)ticks: $ticks")
end
end
function py_compute_axis_minval(sp::Subplot, axis::Axis)
function py_compute_axis_minval(axis::Axis)
# compute the smallest absolute value for the log scale's linear threshold
minval = 1.0
sps = axis.sps
@@ -905,17 +881,17 @@ function py_compute_axis_minval(sp::Subplot, axis::Axis)
end
# now if the axis limits go to a smaller abs value, use that instead
vmin, vmax = axis_limits(sp, axis[:letter])
vmin, vmax = axis_limits(axis)
minval = NaNMath.min(minval, abs(vmin), abs(vmax))
minval
end
function py_set_scale(ax, sp::Subplot, axis::Axis)
function py_set_scale(ax, axis::Axis)
scale = axis[:scale]
letter = axis[:letter]
scale in supported_scales() || return @warn("Unhandled scale value in pyplot: $scale")
func = getproperty(ax, Symbol("set_", letter, "scale"))
func = ax[Symbol("set_", letter, "scale")]
kw = KW()
arg = if scale == :identity
"linear"
@@ -927,7 +903,7 @@ function py_set_scale(ax, sp::Subplot, axis::Axis)
elseif scale == :log10
10
end
kw[Symbol(:linthresh,letter)] = NaNMath.max(1e-16, py_compute_axis_minval(sp, axis))
kw[Symbol(:linthresh,letter)] = NaNMath.min(1e-16, py_compute_axis_minval(axis))
"symlog"
end
func(arg; kw...)
@@ -935,16 +911,16 @@ end
function py_set_axis_colors(sp, ax, a::Axis)
for (loc, spine) in ax.spines
spine."set_color"(py_color(a[:foreground_color_border]))
for (loc, spine) in ax[:spines]
spine[:set_color](py_color(a[:foreground_color_border]))
end
axissym = Symbol(a[:letter], :axis)
if PyCall.hasproperty(ax, axissym)
if haskey(ax, axissym)
tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis])
ax."tick_params"(axis=string(a[:letter]), which="both",
ax[:tick_params](axis=string(a[:letter]), which="both",
colors=tickcolor,
labelcolor=py_color(a[:tickfontcolor]))
getproperty(ax, axissym).label.set_color(py_color(a[:guidefontcolor]))
ax[axissym][:label][:set_color](py_color(a[:guidefontcolor]))
end
end
@@ -956,14 +932,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update the fig
w, h = plt[:size]
fig = plt.o
fig."clear"()
fig[:clear]()
dpi = plt[:dpi]
fig."set_size_inches"(w/DPI, h/DPI, forward = true)
getproperty(fig, set_facecolor_sym)(py_color(plt[:background_color_outside]))
fig."set_dpi"(plt[:dpi])
fig[:set_size_inches](w/DPI, h/DPI, forward = true)
fig[set_facecolor_sym](py_color(plt[:background_color_outside]))
fig[:set_dpi](plt[:dpi])
# resize the window
PyPlot.plt."get_current_fig_manager"().resize(w, h)
PyPlot.plt[:get_current_fig_manager]()[:resize](w, h)
# initialize subplots
for sp in plt.subplots
@@ -978,7 +954,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update subplots
for sp in plt.subplots
ax = sp.o
if ax === nothing
if ax == nothing
continue
end
@@ -997,10 +973,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
else
:title
end
getproperty(ax, func)."set_text"(sp[:title])
getproperty(ax, func)."set_fontsize"(py_thickness_scale(plt, sp[:titlefontsize]))
getproperty(ax, func)."set_family"(sp[:titlefontfamily])
getproperty(ax, func)."set_color"(py_color(sp[:titlefontcolor]))
ax[func][:set_text](sp[:title])
ax[func][:set_fontsize](py_thickness_scale(plt, sp[:titlefontsize]))
ax[func][:set_family](sp[:titlefontfamily])
ax[func][:set_color](py_color(sp[:titlefontcolor]))
# ax[:set_title](sp[:title], loc = loc)
end
@@ -1013,37 +989,36 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw = KW()
if !isempty(sp[:zaxis][:discrete_values]) && colorbar_series[:seriestype] == :heatmap
locator, formatter = get_locator_and_formatter(sp[:zaxis][:discrete_values])
# kw[:values] = eachindex(sp[:zaxis][:discrete_values])
# kw[:values] = 1:length(sp[:zaxis][:discrete_values])
kw[:values] = sp[:zaxis][:continuous_values]
kw[:ticks] = locator
kw[:format] = formatter
kw[:boundaries] = vcat(0, kw[:values] + 0.5)
elseif any(colorbar_series[attr] !== nothing for attr in (:line_z, :fill_z, :marker_z))
elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z))
cmin, cmax = get_clims(sp)
norm = pycolors."Normalize"(vmin = cmin, vmax = cmax)
f = if colorbar_series[:line_z] !== nothing
norm = pycolors[:Normalize](vmin = cmin, vmax = cmax)
f = if colorbar_series[:line_z] != nothing
py_linecolormap
elseif colorbar_series[:fill_z] !== nothing
elseif colorbar_series[:fill_z] != nothing
py_fillcolormap
else
py_markercolormap
end
cmap = pycmap."ScalarMappable"(norm = norm, cmap = f(colorbar_series))
cmap."set_array"([])
cmap = pycmap[:ScalarMappable](norm = norm, cmap = f(colorbar_series))
cmap[:set_array]([])
handle = cmap
end
kw[:spacing] = "proportional"
# create and store the colorbar object (handle) and the axis that it is drawn on.
# note: the colorbar axis is positioned independently from the subplot axis
fig = plt.o
cbax = fig."add_axes"([0.8,0.1,0.03,0.8], label = string(gensym()))
cb = fig."colorbar"(handle; cax = cbax, kw...)
cb."set_label"(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
for lab in cb."ax"."yaxis"."get_ticklabels"()
lab."set_fontsize"(py_thickness_scale(plt, sp[:yaxis][:tickfontsize]))
lab."set_family"(sp[:yaxis][:tickfontfamily])
lab."set_color"(py_color(sp[:yaxis][:tickfontcolor]))
cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym()))
cb = fig[:colorbar](handle; cax = cbax, kw...)
cb[:set_label](sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
for lab in cb[:ax][:yaxis][:get_ticklabels]()
lab[:set_fontsize](py_thickness_scale(plt, sp[:yaxis][:tickfontsize]))
lab[:set_family](sp[:yaxis][:tickfontfamily])
lab[:set_color](py_color(sp[:yaxis][:tickfontcolor]))
end
sp.attr[:cbar_handle] = cb
sp.attr[:cbar_ax] = cbax
@@ -1051,28 +1026,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# framestyle
if !ispolar(sp) && !is3d(sp)
ax.spines["left"]."set_linewidth"(py_thickness_scale(plt, 1))
ax.spines["bottom"]."set_linewidth"(py_thickness_scale(plt, 1))
ax[:spines]["left"][:set_linewidth](py_thickness_scale(plt, 1))
ax[:spines]["bottom"][:set_linewidth](py_thickness_scale(plt, 1))
if sp[:framestyle] == :semi
intensity = 0.5
ax.spines["right"]."set_alpha"(intensity)
ax.spines["top"]."set_alpha"(intensity)
ax.spines["right"]."set_linewidth"(py_thickness_scale(plt, intensity))
ax.spines["top"]."set_linewidth"(py_thickness_scale(plt, intensity))
ax[:spines]["right"][:set_alpha](intensity)
ax[:spines]["top"][:set_alpha](intensity)
ax[:spines]["right"][:set_linewidth](py_thickness_scale(plt, intensity))
ax[:spines]["top"][:set_linewidth](py_thickness_scale(plt, intensity))
elseif sp[:framestyle] in (:axes, :origin)
ax.spines["right"]."set_visible"(false)
ax.spines["top"]."set_visible"(false)
ax[:spines]["right"][:set_visible](false)
ax[:spines]["top"][:set_visible](false)
if sp[:framestyle] == :origin
ax.spines["bottom"]."set_position"("zero")
ax.spines["left"]."set_position"("zero")
ax[:spines]["bottom"][:set_position]("zero")
ax[:spines]["left"][:set_position]("zero")
end
elseif sp[:framestyle] in (:grid, :none, :zerolines)
for (loc, spine) in ax.spines
spine."set_visible"(false)
for (loc, spine) in ax[:spines]
spine[:set_visible](false)
end
if sp[:framestyle] == :zerolines
ax."axhline"(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax."axvline"(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax[:axhline](y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax[:axvline](x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
end
end
end
@@ -1080,51 +1055,51 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# axis attributes
for letter in (:x, :y, :z)
axissym = Symbol(letter, :axis)
PyCall.hasproperty(ax, axissym) || continue
haskey(ax, axissym) || continue
axis = sp[axissym]
pyaxis = getproperty(ax, axissym)
pyaxis = ax[axissym]
if axis[:mirror] && letter != :z
pos = letter == :x ? "top" : "right"
pyaxis."set_label_position"(pos) # the guides
pyaxis."set_ticks_position"("both") # the hash marks
getproperty(pyaxis, Symbol(:tick_, pos))() # the tick labels
pyaxis[:set_label_position](pos) # the guides
pyaxis[:set_ticks_position]("both") # the hash marks
pyaxis[Symbol(:tick_, pos)]() # the tick labels
end
if axis[:guide_position] != :auto && letter != :z
pyaxis."set_label_position"(axis[:guide_position])
pyaxis[:set_label_position](axis[:guide_position])
end
py_set_scale(ax, sp, axis)
axis[:ticks] != :native ? py_set_lims(ax, sp, axis) : nothing
py_set_scale(ax, axis)
axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing
if ispolar(sp) && letter == :y
ax."set_rlabel_position"(90)
ax[:set_rlabel_position](90)
end
ticks = sp[:framestyle] == :none ? nothing : get_ticks(sp, axis)
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && length(ticks) > 1
ticks[2][ticks[1] .== 0] .= ""
end
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in")
getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide])
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
ax[Symbol("set_", letter, "label")](axis[:guide])
if get(axis.plotattributes, :flip, false)
getproperty(ax, Symbol("invert_", letter, "axis"))()
ax[Symbol("invert_", letter, "axis")]()
end
pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize]))
pyaxis."label"."set_family"(axis[:guidefontfamily])
for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))()
lab."set_fontsize"(py_thickness_scale(plt, axis[:tickfontsize]))
lab."set_family"(axis[:tickfontfamily])
lab."set_rotation"(axis[:rotation])
pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize]))
pyaxis[:label][:set_family](axis[:guidefontfamily])
for lab in ax[Symbol("get_", letter, "ticklabels")]()
lab[:set_fontsize](py_thickness_scale(plt, axis[:tickfontsize]))
lab[:set_family](axis[:tickfontfamily])
lab[:set_rotation](axis[:rotation])
end
if axis[:grid] && !(ticks in (:none, nothing, false))
fgcolor = py_color(axis[:foreground_color_grid])
pyaxis."grid"(true,
pyaxis[:grid](true,
color = fgcolor,
linestyle = py_linestyle(:line, axis[:gridstyle]),
linewidth = py_thickness_scale(plt, axis[:gridlinewidth]),
alpha = axis[:gridalpha])
ax."set_axisbelow"(true)
ax[:set_axisbelow](true)
else
pyaxis."grid"(false)
pyaxis[:grid](false)
end
py_set_axis_colors(sp, ax, axis)
end
@@ -1132,51 +1107,50 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# showaxis
if !sp[:xaxis][:showaxis]
kw = KW()
if ispolar(sp)
ax.spines["polar"].set_visible(false)
end
for dir in (:top, :bottom)
if !ispolar(sp)
ax.spines[string(dir)].set_visible(false)
if ispolar(sp)
ax[:spines]["polar"][:set_visible](false)
else
ax[:spines][string(dir)][:set_visible](false)
end
kw[dir] = kw[Symbol(:label,dir)] = false
end
ax."xaxis"."set_tick_params"(; which="both", kw...)
ax[:xaxis][:set_tick_params](; which="both", kw...)
end
if !sp[:yaxis][:showaxis]
kw = KW()
for dir in (:left, :right)
if !ispolar(sp)
ax.spines[string(dir)].set_visible(false)
ax[:spines][string(dir)][:set_visible](false)
end
kw[dir] = kw[Symbol(:label,dir)] = false
end
ax."yaxis"."set_tick_params"(; which="both", kw...)
ax[:yaxis][:set_tick_params](; which="both", kw...)
end
# aspect ratio
aratio = sp[:aspect_ratio]
if aratio != :none
ax."set_aspect"(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
end
#camera/view angle
if is3d(sp)
#convert azimuthal to match GR behaviour
#view_init(elevation, azimuthal) so reverse :camera args
ax."view_init"((sp[:camera].-(90,0))[end:-1:1]...)
ax[:view_init]((sp[:camera].-(90,0))[end:-1:1]...)
end
# legend
py_add_legend(plt, sp, ax)
# this sets the bg color inside the grid
getproperty(ax, set_facecolor_sym)(py_color(sp[:background_color_inside]))
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
# link axes
x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o
ax != x_ax_link && ax."get_shared_x_axes"()."join"(ax, sp[:xaxis].sps[1].o)
ax != y_ax_link && ax."get_shared_y_axes"()."join"(ax, sp[:yaxis].sps[1].o)
ax != x_ax_link && ax[:get_shared_x_axes]()[:join](ax, sp[:xaxis].sps[1].o)
ax != y_ax_link && ax[:get_shared_y_axes]()[:join](ax, sp[:yaxis].sps[1].o)
end
py_drawfig(fig)
end
@@ -1186,7 +1160,7 @@ end
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PyPlotBackend})
ax = sp.o
ax === nothing && return sp.minpad
ax == nothing && return sp.minpad
plotbb = py_bbox(ax)
# TODO: this should initialize to the margin from sp.attr
@@ -1196,7 +1170,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
toppad = 0mm
rightpad = 0mm
bottompad = 0mm
for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax), py_bbox_legend(ax))
for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax))
if ispositive(width(bb)) && ispositive(height(bb))
leftpad = max(leftpad, left(plotbb) - left(bb))
toppad = max(toppad, top(plotbb) - top(bb))
@@ -1207,7 +1181,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
# optionally add the width of colorbar labels and colorbar to rightpad
if haskey(sp.attr, :cbar_ax)
bb = py_bbox(sp.attr[:cbar_handle]."ax"."get_yticklabels"())
bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]())
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
rightpad = rightpad + sp.attr[:cbar_width]
end
@@ -1228,13 +1202,13 @@ end
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val)
ax = sp.o
ax."annotate"(val, xy = (x,y), zorder = 999, annotation_clip = false)
ax[:annotate](val, xy = (x,y), zorder = 999)
end
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
ax = sp.o
ax."annotate"(val.str,
ax[:annotate](val.str,
xy = (x,y),
family = val.font.family,
color = py_color(val.font.color),
@@ -1242,8 +1216,7 @@ function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
rotation = val.font.rotation,
size = py_thickness_scale(sp.plt, val.font.pointsize),
zorder = 999,
annotation_clip = false
zorder = 999
)
end
@@ -1260,59 +1233,31 @@ const _pyplot_legend_pos = KW(
:topleft => "upper left"
)
const _pyplot_legend_pos_outer = KW(
:outerright => "center left",
:outerleft => "right",
:outertop => "lower center",
:outerbottom => "upper center",
:outerbottomleft => "lower right",
:outerbottomright => "lower left",
:outertopright => "upper left",
:outertopleft => "upper right"
)
py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, get(_pyplot_legend_pos_outer, pos, "best"))
py_legend_pos(pos) = "lower left"
const _pyplot_legend_bbox_outer = KW(
:outerright => (1.0, 0.5, 0.0, 0.0),
:outerleft => (-0.15, 0.5, 0.0, 0.0),
:outertop => (0.5, 1.0, 0.0, 0.0),
:outerbottom => (0.5, -0.15, 0.0, 0.0),
:outerbottomleft => (-0.15, 0.0, 0.0, 0.0),
:outerbottomright => (1.0, 0.0, 0.0, 0.0),
:outertopright => (1.0, 1.0, 0.0, 0.0),
:outertopleft => (-0.15, 1.0, 0.0, 0.0)
)
py_legend_bbox(pos::Symbol) = get(_pyplot_legend_bbox_outer, pos, (0.0, 0.0, 1.0, 1.0))
py_legend_bbox(pos) = pos
function py_add_legend(plt::Plot, sp::Subplot, ax)
leg = sp[:legend]
clims = get_clims(sp)
if leg != :none
# gotta do this to ensure both axes are included
labels = []
handles = []
for series in series_list(sp)
if should_add_to_legend(series)
clims = get_clims(sp, series)
# add a line/marker and a label
push!(handles, if series[:seriestype] == :shape || series[:fillrange] !== nothing
pypatches."Patch"(
edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
facecolor = py_color(single_color(get_fillcolor(series, clims)), get_fillalpha(series)),
push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
pypatches[:Patch](
edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)),
facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)),
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(series[:seriestype], get_linestyle(series))
)
elseif series[:seriestype] in (:path, :straightline, :scatter)
PyPlot.plt."Line2D"((0,1),(0,0),
color = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
PyPlot.plt[:Line2D]((0,1),(0,0),
color = py_color(get_linecolor(series, clims), get_linealpha(series)),
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(:path, get_linestyle(series)),
marker = py_marker(first(series[:markershape])),
markeredgecolor = py_color(single_color(get_markerstrokecolor(series)), get_markerstrokealpha(series)),
markerfacecolor = py_color(single_color(get_markercolor(series, clims)), get_markeralpha(series))
markeredgecolor = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
markerfacecolor = series[:marker_z] == nothing ? py_color(get_markercolor(series, clims), get_markeralpha(series)) : py_color(series[:markercolor][0.5])
)
else
series[:serieshandle][1]
@@ -1323,26 +1268,22 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# if anything was added, call ax.legend and set the colors
if !isempty(handles)
leg = ax."legend"(handles,
leg = ax[:legend](handles,
labels,
loc = py_legend_pos(leg),
bbox_to_anchor = py_legend_bbox(leg),
loc = get(_pyplot_legend_pos, leg, "best"),
scatterpoints = 1,
fontsize = py_thickness_scale(plt, sp[:legendfontsize]),
facecolor = py_color(sp[:background_color_legend]),
edgecolor = py_color(sp[:foreground_color_legend]),
framealpha = alpha(plot_color(sp[:background_color_legend])),
)
frame = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000)
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
frame = leg[:get_frame]()
frame[:set_linewidth](py_thickness_scale(plt, 1))
leg[:set_zorder](1000)
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
for txt in leg."get_texts"()
PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily], fontsize = py_thickness_scale(plt, sp[:legendfontsize]))
for txt in leg[:get_texts]()
PyPlot.plt[:setp](txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
end
end
end
@@ -1356,11 +1297,11 @@ end
function _update_plot_object(plt::Plot{PyPlotBackend})
for sp in plt.subplots
ax = sp.o
ax === nothing && return
ax == nothing && return
figw, figh = sp.plt[:size]
figw, figh = figw*px, figh*px
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
ax."set_position"(pcts)
ax[:set_position](pcts)
# set the cbar position if there is one
if haskey(sp.attr, :cbar_ax)
@@ -1370,7 +1311,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7)
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm))
pcts = bbox_to_pcts(cb_bbox, figw, figh)
sp.attr[:cbar_ax]."set_position"(pcts)
sp.attr[:cbar_ax][:set_position](pcts)
end
end
PyPlot.draw()
@@ -1379,7 +1320,9 @@ end
# -----------------------------------------------------------------
# display/output
_display(plt::Plot{PyPlotBackend}) = plt.o."show"()
function _display(plt::Plot{PyPlotBackend})
plt.o[:show]()
end
@@ -1389,24 +1332,23 @@ const _pyplot_mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"application/postscript" => "ps",
"image/svg+xml" => "svg",
"application/x-tex" => "pgf"
"image/svg+xml" => "svg"
)
for (mime, fmt) in _pyplot_mimeformats
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend})
fig = plt.o
fig."canvas"."print_figure"(
fig[:canvas][:print_figure](
io,
format=$fmt,
# bbox_inches = "tight",
# figsize = map(px2inch, plt[:size]),
facecolor = fig."get_facecolor"(),
facecolor = fig[:get_facecolor](),
edgecolor = "none",
dpi = plt[:dpi]
)
end
end
closeall(::PyPlotBackend) = PyPlot.plt."close"("all")
closeall(::PyPlotBackend) = PyPlot.plt[:close]("all")
+4 -4
View File
@@ -27,8 +27,8 @@ function rebuildUnicodePlot!(plt::Plot, width, height)
for sp in plt.subplots
xaxis = sp[:xaxis]
yaxis = sp[:yaxis]
xlim = axis_limits(sp, :x)
ylim = axis_limits(sp, :y)
xlim = axis_limits(xaxis)
ylim = axis_limits(yaxis)
# make vectors
xlim = [xlim[1], xlim[2]]
@@ -92,7 +92,7 @@ end
# add a single series
function addUnicodeSeries!(o, plotattributes, addlegend::Bool, xlim, ylim)
function addUnicodeSeries!(o, plotattributes::KW, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
st = plotattributes[:seriestype]
if st == :histogram2d
@@ -116,7 +116,7 @@ function addUnicodeSeries!(o, plotattributes, addlegend::Bool, xlim, ylim)
x, y = if st == :straightline
straightline_data(plotattributes)
elseif st == :shape
shape_data(plotattributes)
shape_data(series)
else
[collect(float(plotattributes[s])) for s in (:x, :y)]
end
+17 -16
View File
@@ -1,7 +1,7 @@
const P2 = GeometryTypes.Point2{Float64}
const P3 = GeometryTypes.Point3{Float64}
const P2 = StaticArrays.SVector{2,Float64}
const P3 = StaticArrays.SVector{3,Float64}
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
@@ -187,7 +187,7 @@ end
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = coords(shape)
cx, cy = c
for i=eachindex(sx)
for i=1:length(sx)
sx[i] = (sx[i] - cx) * x + cx
sy[i] = (sy[i] - cy) * y + cy
end
@@ -202,7 +202,7 @@ end
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape)
for i=eachindex(sx)
for i=1:length(sx)
sx[i] += x
sy[i] += y
end
@@ -230,7 +230,7 @@ end
function rotate!(shape::Shape, Θ::Real, c = center(shape))
x, y = coords(shape)
cx, cy = c
for i=eachindex(x)
for i=1:length(x)
xi = rotate_x(x[i], y[i], Θ, cx, cy)
yi = rotate_y(x[i], y[i], Θ, cx, cy)
x[i], y[i] = xi, yi
@@ -261,13 +261,13 @@ end
Create a Font from a list of features. Values may be specified either as
arguments (which are distinguished by type/value) or as keyword arguments.
# Arguments
- `family`: AbstractString. "serif" or "sans-serif" or "monospace"
- `family`: AbstractString. "serif" or "sans-serif" or "monospace"
- `pointsize`: Integer. Size of font in points
- `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right)
- `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom)
- `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type)
- `color`: Colorant or Symbol
# Examples
# Examples
```julia-repl
julia> font(8)
julia> font(family="serif",halign=:center,rotation=45.0)
@@ -388,8 +388,8 @@ PlotText(str) = PlotText(string(str), font())
"""
text(string, args...; kw...)
Create a PlotText object wrapping a string with font info, for plot annotations.
`args` and `kw` are passed to `font`.
Create a PlotText object wrapping a string with font info, for plot annotations.
`args` and `kw` are passed to `font`.
"""
text(t::PlotText) = t
text(t::PlotText, font::Font) = PlotText(t.str, font)
@@ -529,7 +529,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# end
# @show msw msh
if anns !== nothing && anns.baseshape !== nothing
if anns != nothing && anns.baseshape != nothing
# we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each
msw,msh = anns.scalefactor
@@ -568,7 +568,7 @@ mutable struct EachAnn
end
function Base.iterate(ea::EachAnn, i = 1)
if ea.anns === nothing || isempty(ea.anns.strs) || i > length(ea.y)
if ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
return nothing
end
@@ -591,9 +591,7 @@ annotations(sa::SeriesAnnotations) = sa
function process_annotation(sp::Subplot, xs, ys, labs, font = font())
anns = []
labs = makevec(labs)
xlength = length(methods(length, (typeof(xs),))) == 0 ? 1 : length(xs)
ylength = length(methods(length, (typeof(ys),))) == 0 ? 1 : length(ys)
for i in 1:max(xlength, ylength, length(labs))
for i in 1:max(length(xs), length(ys), length(labs))
x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i)
if lab == :auto
alphabet = "abcdefghijklmnopqrstuvwxyz"
@@ -781,7 +779,7 @@ end
# -----------------------------------------------------------------------
"create a BezierCurve for plotting"
mutable struct BezierCurve{T <: GeometryTypes.Point}
mutable struct BezierCurve{T <: StaticArrays.SVector}
control_points::Vector{T}
end
@@ -794,9 +792,12 @@ function (bc::BezierCurve)(t::Real)
p
end
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
# mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
@deprecate curve_points coords
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, Base.range(range..., length=n))
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50))
# 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]
+14 -65
View File
@@ -86,9 +86,8 @@ yaxis!("YLABEL", :log10)
PlotExample("Images",
"Plot an image. y-axis is set to flipped",
[:(begin
import FileIO
path = download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png")
img = FileIO.load(path)
import FileIO, PlotReferenceImages
img = FileIO.load(joinpath(dirname(pathof(PlotReferenceImages)), "..", "Plots","pyplot","0.7.0","ref1.png"))
plot(img)
end)]
),
@@ -165,7 +164,7 @@ PlotExample("Marker types",
),
PlotExample("Bar",
"`x` is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[:(begin
bar(randn(99))
end)]
@@ -238,12 +237,12 @@ build with the method `text(string, attr...)`, which wraps font and color attrib
""",
[:(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"))])
plot(y, annotations = (3,y[3],text("this is #3",:left)), leg=false)
annotate!([(5, y[5], text("this is #5",16,:red,:center)),
(10, y[10], text("this is #10",:right,20,"courier"))])
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)])
text("data",:green)])
end)]
),
@@ -305,8 +304,7 @@ PlotExample("3D",
PlotExample("DataFrames",
"Plot using DataFrame column symbols.",
[:(using StatsPlots), # can't be inside begin block because @df gets expanded first
:(begin
[:(begin
import RDatasets
iris = RDatasets.dataset("datasets", "iris")
@df iris scatter(:SepalLength, :SepalWidth, group=:Species,
@@ -355,8 +353,7 @@ PlotExample("Layouts, margins, label rotation, title location",
PlotExample("Boxplot and Violin series recipes",
"",
[:(using StatsPlots), # can't be inside begin block because @df gets expanded first
:(begin
[:(begin
import RDatasets
singers = RDatasets.dataset("lattice", "singer")
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue))
@@ -456,49 +453,6 @@ see: http://stackoverflow.com/a/37732384/5075246
end)]
),
PlotExample("Ribbons",
"""
Ribbons can be added to lines via the `ribbon` keyword;
you can pass a tuple of arrays (upper and lower bounds),
a single Array (for symmetric ribbons), a Function, or a number.
""",
[:(begin
plot(
plot(0:10; ribbon = (LinRange(0, 2, 10), LinRange(0, 1, 10))),
plot(0:10; ribbon = 0:0.5:5),
plot(0:10; ribbon = sqrt),
plot(0:10; ribbon = 1),
)
end)]
),
PlotExample("Histogram2D (complex values)",
"",
[:(begin
n = 10_000
x = exp.(0.1randn(n) .+ randn(n).*(im))
histogram2d(x, nbins=(20,40), show_empty_bins=true,
normed=true, aspect_ratio=1)
end)]
),
PlotExample("Unconnected lines using `missing` or `NaN`",
"""
Missing values and non-finite values, including `NaN`, are not plotted.
Instead, lines are separated into segments at these values.
""",
[:(begin
x,y = [1,2,2,1,1], [1,2,1,2,1]
plot(
plot([rand(5); NaN; rand(5); NaN; rand(5)]),
plot([1,missing,2,3], marker=true),
plot([x; NaN; x.+2], [y; NaN; y.+1], arrow=2),
plot([1, 2+3im, Inf, 4im, 3, -Inf*im, 0, 3+3im], marker=true),
legend=false
)
end)]
),
]
# Some constants for PlotDocs and PlotReferenceImages
@@ -506,7 +460,7 @@ _animation_examples = [2, 30]
_backend_skips = Dict(
:gr => [25, 30],
:pyplot => [25, 30],
:plotlyjs => [2, 21, 24, 25, 30, 31],
:plotlyjs => [2, 21, 25, 30, 31],
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30],
)
@@ -520,12 +474,7 @@ function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
@info("Testing plot: $pkgname:$idx:$(_examples[idx].header)")
backend(pkgname)
backend()
# 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)
map(eval, _examples[idx].exprs)
plt = current()
if disp
gui(plt)
@@ -545,8 +494,8 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
skip = [], only = nothing)
Plots._debugMode.on = debug
plts = Dict()
for i in eachindex(_examples)
only !== nothing && !(i in only) && continue
for i in 1:length(_examples)
only != nothing && !(i in only) && continue
i in skip && continue
try
plt = test_examples(pkgname, i, debug=debug, disp=disp)
@@ -555,7 +504,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
# TODO: put error info into markdown?
@warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
end
if sleep !== nothing
if sleep != nothing
Base.sleep(sleep)
end
end
+1 -4
View File
@@ -20,10 +20,7 @@ frontends like jupyterlab and nteract.
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict(
:data => plotly_series(plt),
:layout => plotly_layout(plt)
)
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
out
end
+7 -48
View File
@@ -3,7 +3,7 @@ using REPL
function _plots_defaults()
if isdefined(Main, :PLOTS_DEFAULTS)
Dict{Symbol,Any}(Main.PLOTS_DEFAULTS)
Main.PLOTS_DEFAULTS::Dict{Symbol,Any}
else
Dict{Symbol,Any}()
end
@@ -28,53 +28,12 @@ function __init__()
insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
end)
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin
fn = joinpath(@__DIR__, "backends", "hdf5.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" begin
fn = joinpath(@__DIR__, "backends", "inspectdr.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" begin
fn = joinpath(@__DIR__, "backends", "pgfplots.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require ORCA = "47be7bcc-f1a6-5447-8b36-7eeeff7534fd" begin
fn = joinpath(@__DIR__, "backends", "orca.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925" begin
fn = joinpath(@__DIR__, "backends", "pgfplotsx.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" begin
fn = joinpath(@__DIR__, "backends", "plotlyjs.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" begin
fn = joinpath(@__DIR__, "backends", "pyplot.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" begin
fn = joinpath(@__DIR__, "backends", "unicodeplots.jl")
include(fn)
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
end
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl"))
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" include(joinpath(@__DIR__, "backends", "inspectdr.jl"))
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" include(joinpath(@__DIR__, "backends", "pgfplots.jl"))
@require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" include(joinpath(@__DIR__, "backends", "plotlyjs.jl"))
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" include(joinpath(@__DIR__, "backends", "pyplot.jl"))
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" include(joinpath(@__DIR__, "backends", "unicodeplots.jl"))
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited
+10 -27
View File
@@ -107,10 +107,11 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
if mix.len != 0mm
f = (letter == :x ? width : height)
totlen = f(plotarea(sp))
@show totlen
pct += mix.len / totlen
end
if pct != 0
amin, amax = axis_limits(sp, letter)
amin, amax = axis_limits(sp[Symbol(letter,:axis)])
xy += pct * (amax-amin)
end
xy
@@ -217,7 +218,6 @@ bottompad(layout::AbstractLayout) = 0mm
# this is the parent of the top-level layout
struct RootLayout <: AbstractLayout end
Base.show(io::IO, layout::RootLayout) = Base.show_default(io, layout)
Base.parent(::RootLayout) = nothing
parent_bbox(::RootLayout) = defaultbox
bbox(::RootLayout) = defaultbox
@@ -464,12 +464,12 @@ end
# constructors
# pass the layout arg through
function layout_args(plotattributes::AKW)
layout_args(plotattributes[:layout])
function layout_args(plotattributes::KW)
layout_args(get(plotattributes, :layout, default(:layout)))
end
function layout_args(plotattributes::AKW, n_override::Integer)
layout, n = layout_args(n_override, get(plotattributes, :layout, n_override))
function layout_args(plotattributes::KW, n_override::Integer)
layout, n = layout_args(get(plotattributes, :layout, n_override))
if n != n_override
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end
@@ -481,27 +481,12 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n
end
function layout_args(sztup::NTuple{2, Integer})
function layout_args(sztup::NTuple{2,I}) where I<:Integer
nr, nc = sztup
GridLayout(nr, nc), nr*nc
end
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})
function layout_args(sztup::NTuple{3,I}) where I<:Integer
n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n
@@ -514,8 +499,6 @@ function layout_args(layout::GridLayout)
layout, n
end
layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
@@ -616,7 +599,7 @@ end
# ----------------------------------------------------------------------
# @layout macro
function add_layout_pct!(kw::AKW, v::Expr, idx::Integer, nidx::Integer)
function add_layout_pct!(kw::KW, v::Expr, idx::Integer, nidx::Integer)
# dump(v)
# something like {0.2w}?
if v.head == :call && v.args[1] == :*
@@ -637,7 +620,7 @@ function add_layout_pct!(kw::AKW, v::Expr, idx::Integer, nidx::Integer)
error("Couldn't match layout curly (idx=$idx): $v")
end
function add_layout_pct!(kw::AKW, v::Number, idx::Integer)
function add_layout_pct!(kw::KW, v::Number, idx::Integer)
# kw[idx == 1 ? :w : :h] = v*pct
idx == 1 && (kw[:w] = v*pct)
(idx == 2 || nidx == 1) && (kw[:h] = v*pct)
+7 -12
View File
@@ -55,7 +55,9 @@ tex(fn::AbstractString) = tex(current(), fn)
function html(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "html")
io = open(fn, "w")
_use_remote[] = true
show(io, MIME("text/html"), plt)
_use_remote[] = false
close(io)
end
html(fn::AbstractString) = html(current(), fn)
@@ -72,7 +74,6 @@ const _savemap = Dict(
"eps" => eps,
"tex" => tex,
"html" => html,
"tikz" => tex,
)
function getExtension(fn::AbstractString)
@@ -104,7 +105,7 @@ type is inferred from the file extension. All backends support png and pdf
file types, some also support svg, ps, eps, html and tex.
"""
function savefig(plt::Plot, fn::AbstractString)
fn = abspath(expanduser(fn))
# get the extension
local ext
try
@@ -190,7 +191,7 @@ end
# for writing to io streams... first prepare, then callback
for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml",
"application/eps", "application/pdf", "application/postscript",
"application/x-tex", "application/vnd.plotly.v1+json")
"application/x-tex")
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
if haskey(io, :juno_plotsize)
showjuno(io, m, plt)
@@ -198,12 +199,9 @@ for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml
prepare_output(plt)
_show(io, m, plt)
end
return nothing
end
end
Base.show(io::IO, m::MIME"application/prs.juno.plotpane+html", plt::Plot) = showjuno(io, MIME("text/html"), plt)
# default text/plain for all backends
_show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt)
@@ -232,16 +230,15 @@ closeall() = closeall(backend())
# Atom PlotPane
# ---------------------------------------------------------
function showjuno(io::IO, m, plt)
sz = collect(plt[:size])
sz = plt[:size]
dpi = plt[:dpi]
thickness_scaling = plt[:thickness_scaling]
jsize = get(io, :juno_plotsize, [400, 500])
jratio = get(io, :juno_dpi_ratio, 1)
scale = minimum(jsize[i] / sz[i] for i in 1:2)
plt[:size] = [s * scale for s in sz]
plt[:dpi] = jratio*Plots.DPI
plt[:size] = (s * scale for s in sz)
plt[:dpi] = Plots.DPI
plt[:thickness_scaling] *= scale
prepare_output(plt)
@@ -262,6 +259,4 @@ function _showjuno(io::IO, m::MIME"image/svg+xml", plt)
end
end
Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot) = false
_showjuno(io::IO, m, plt) = _show(io, m, plt)
+25 -28
View File
@@ -3,16 +3,16 @@
# ------------------------------------------------------------------
# preprocessing
function series_idx(kw_list::AVec{KW}, kw::AKW)
function command_idx(kw_list::AVec{KW}, kw::KW)
Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1
end
function _expand_seriestype_array(plotattributes::AKW, args)
function _expand_seriestype_array(plotattributes::KW, args)
sts = get(plotattributes, :seriestype, :path)
if typeof(sts) <: AbstractArray
reset_kw!(plotattributes, :seriestype)
delete!(plotattributes, :seriestype)
rd = Vector{RecipeData}(undef, size(sts, 1))
for r in axes(sts, 1)
for r in 1:size(sts, 1)
dc = copy(plotattributes)
dc[:seriestype] = sts[r:r,:]
rd[r] = RecipeData(dc, args)
@@ -23,7 +23,7 @@ function _expand_seriestype_array(plotattributes::AKW, args)
end
end
function _preprocess_args(plotattributes::AKW, args, still_to_process::Vector{RecipeData})
function _preprocess_args(plotattributes::KW, args, still_to_process::Vector{RecipeData})
# the grouping mechanism is a recipe on a GroupBy object
# we simply add the GroupBy object to the front of the args list to allow
# the recipe to be applied
@@ -42,11 +42,9 @@ function _preprocess_args(plotattributes::AKW, args, still_to_process::Vector{Re
for (k,v) in plotattributes
for defdict in (_subplot_defaults,
_axis_defaults,
_axis_defaults_byletter[:x],
_axis_defaults_byletter[:y],
_axis_defaults_byletter[:z])
_axis_defaults_byletter)
if haskey(defdict, k)
reset_kw!(plotattributes, k)
delete!(plotattributes, k)
end
end
end
@@ -59,7 +57,7 @@ end
# user recipes
function _process_userrecipes(plt::Plot, plotattributes::AKW, args)
function _process_userrecipes(plt::Plot, plotattributes::KW, args)
still_to_process = RecipeData[]
args = _preprocess_args(plotattributes, args, still_to_process)
@@ -110,7 +108,7 @@ function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeD
return
end
function _preprocess_userrecipe(kw::AKW)
function _preprocess_userrecipe(kw::KW)
_add_markershape(kw)
# if there was a grouping, filter the data here
@@ -128,17 +126,17 @@ function _preprocess_userrecipe(kw::AKW)
end
# convert a ribbon into a fillrange
if get(kw, :ribbon, nothing) !== nothing
if get(kw, :ribbon, nothing) != nothing
make_fillrange_from_ribbon(kw)
end
return
end
function _add_errorbar_kw(kw_list::Vector{KW}, kw::AKW)
function _add_errorbar_kw(kw_list::Vector{KW}, kw::KW)
# handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror)
if get(kw, esym, nothing) !== nothing
if get(kw, esym, nothing) != nothing
# we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw)
errkw[:seriestype] = esym
@@ -149,7 +147,7 @@ function _add_errorbar_kw(kw_list::Vector{KW}, kw::AKW)
end
end
function _add_smooth_kw(kw_list::Vector{KW}, kw::AKW)
function _add_smooth_kw(kw_list::Vector{KW}, kw::KW)
# handle smoothing by adding a new series
if get(kw, :smooth, false)
x, y = kw[:x], kw[:y]
@@ -174,7 +172,7 @@ end
# to generate a list of RecipeData objects (data + attributes).
# If we applied a "plot recipe" without error, then add the returned datalist's KWs,
# otherwise we just add the original KW.
function _process_plotrecipe(plt::Plot, kw::AKW, kw_list::Vector{KW}, still_to_process::Vector{KW})
function _process_plotrecipe(plt::Plot, kw::KW, kw_list::Vector{KW}, still_to_process::Vector{KW})
if !isa(get(kw, :seriestype, nothing), Symbol)
# seriestype was never set, or it's not a Symbol, so it can't be a plot recipe
push!(kw_list, kw)
@@ -205,7 +203,7 @@ end
# ------------------------------------------------------------------
# setup plot and subplot
function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
function _plot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# merge in anything meant for the Plot
for kw in kw_list, (k,v) in kw
haskey(_plot_defaults, k) && (plotattributes[k] = pop!(kw, k))
@@ -229,7 +227,7 @@ function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
# handle inset subplots
insets = plt[:inset_subplots]
if insets !== nothing
if insets != nothing
if !(typeof(insets) <: AVec)
insets = [insets]
end
@@ -254,7 +252,7 @@ function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
plt[:inset_subplots] = nothing
end
function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
function _subplot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# we'll keep a map of subplot to an attribute override dict.
# Subplot/Axis attributes set by a user/series recipe apply only to the
# Subplot object which they belong to.
@@ -263,16 +261,16 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
for kw in kw_list
# get the Subplot object to which the series belongs.
sps = get(kw, :subplot, :auto)
sp = get_subplot(plt, _cycle(sps == :auto ? plt.subplots : plt.subplots[sps], series_idx(kw_list,kw)))
sp = get_subplot(plt, _cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
kw[:subplot] = sp
# extract subplot/axis attributes from kw and add to sp_attr
attr = KW()
for (k,v) in collect(kw)
if is_subplot_attr(k) || is_axis_attr(k)
if haskey(_subplot_defaults, k) || haskey(_axis_defaults_byletter, k)
attr[k] = pop!(kw, k)
end
if is_axis_attr_noletter(k)
if haskey(_axis_defaults, k)
v = pop!(kw, k)
for letter in (:x,:y,:z)
attr[Symbol(letter,k)] = v
@@ -305,7 +303,7 @@ end
# getting ready to add the series... last update to subplot from anything
# that might have been added during series recipes
function _prepare_subplot(plt::Plot{T}, plotattributes::AKW) where T
function _prepare_subplot(plt::Plot{T}, plotattributes::KW) where T
st::Symbol = plotattributes[:seriestype]
sp::Subplot{T} = plotattributes[:subplot]
sp_idx = get_subplot_index(plt, sp)
@@ -329,7 +327,7 @@ end
# ------------------------------------------------------------------
# series types
function _override_seriestype_check(plotattributes::AKW, st::Symbol)
function _override_seriestype_check(plotattributes::KW, st::Symbol)
# do we want to override the series type?
if !is3d(st) && !(st in (:contour,:contour3d))
z = plotattributes[:z]
@@ -341,7 +339,7 @@ function _override_seriestype_check(plotattributes::AKW, st::Symbol)
st
end
function _prepare_annotations(sp::Subplot, plotattributes::AKW)
function _prepare_annotations(sp::Subplot, plotattributes::KW)
# strip out series annotations (those which are based on series x/y coords)
# and add them to the subplot attr
sp_anns = annotations(sp[:annotations])
@@ -358,7 +356,7 @@ function _prepare_annotations(sp::Subplot, plotattributes::AKW)
# sp.attr[:annotations] = vcat(sp_anns, series_anns)
end
function _expand_subplot_extrema(sp::Subplot, plotattributes::AKW, st::Symbol)
function _expand_subplot_extrema(sp::Subplot, plotattributes::KW, st::Symbol)
# adjust extrema and discrete info
if st == :image
xmin, xmax = ignorenan_extrema(plotattributes[:x]); ymin, ymax = ignorenan_extrema(plotattributes[:y])
@@ -387,8 +385,7 @@ end
# this method recursively applies series recipes when the seriestype is not supported
# natively by the backend
function _process_seriesrecipe(plt::Plot, plotattributes::AKW)
#println("process $(typeof(plotattributes))")
function _process_seriesrecipe(plt::Plot, plotattributes::KW)
# replace seriestype aliases
st = Symbol(plotattributes[:seriestype])
st = plotattributes[:seriestype] = get(_typeAliases, st, st)
+10 -9
View File
@@ -4,7 +4,7 @@ mutable struct CurrentPlot
end
const CURRENT_PLOT = CurrentPlot(nothing)
isplotnull() = CURRENT_PLOT.nullableplot === nothing
isplotnull() = CURRENT_PLOT.nullableplot == nothing
"""
current()
@@ -96,7 +96,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
series_attr = KW()
for (k,v) in plotattributes
if is_series_attr(k)
if haskey(_series_defaults, k)
series_attr[k] = pop!(plotattributes,k)
end
end
@@ -119,7 +119,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
sp.attr[:subplot_index] = idx
for series in serieslist
merge!(series.plotattributes, series_attr)
_slice_series_args!(series.plotattributes, plt, sp, cmdidx)
_add_defaults!(series.plotattributes, plt, sp, cmdidx)
push!(plt.series_list, series)
_series_added(plt, series)
cmdidx += 1
@@ -163,7 +163,7 @@ end
# this is the core plotting function. recursively apply recipes to build
# a list of series KW dicts.
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
function _plot!(plt::Plot, plotattributes::AKW, args::Tuple)
function _plot!(plt::Plot, plotattributes::KW, args::Tuple)
plotattributes[:plot_object] = plt
if !isempty(args) && !isdefined(Main, :StatsPlots) &&
@@ -217,20 +217,21 @@ function _plot!(plt::Plot, plotattributes::AKW, args::Tuple)
for kw in kw_list
sp::Subplot = kw[:subplot]
# idx = get_subplot_index(plt, sp)
# in series attributes given as vector with one element per series,
# select the value for current series
_slice_series_args!(kw, plt, sp, series_idx(kw_list,kw))
# # we update subplot args in case something like the color palatte is part of the recipe
# _update_subplot_args(plt, sp, kw, idx, true)
# set default values, select from attribute cycles, and generally set the final attributes
_add_defaults!(kw, plt, sp, command_idx(kw_list,kw))
series_attr = Attr(kw, _series_defaults)
# now we have a fully specified series, with colors chosen. we must recursively handle
# series recipes, which dispatch on seriestype. If a backend does not natively support a seriestype,
# we check for a recipe that will convert that series type into one made up of lower-level components.
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
# be able to support step, bar, and histogram plots (and any recipes that use those components).
_process_seriesrecipe(plt, series_attr)
_process_seriesrecipe(plt, kw)
end
# --------------------------------
+2 -7
View File
@@ -50,13 +50,8 @@ function plotattr(attrtype::Symbol, attribute::AbstractString)
desc = get(_arg_desc, attribute, "")
first_period_idx = findfirst(isequal('.'), desc)
if isnothing(first_period_idx)
typedesc = ""
desc = strip(desc)
else
typedesc = desc[1:first_period_idx-1]
desc = strip(desc[first_period_idx+1:end])
end
typedesc = desc[1:first_period_idx-1]
desc = strip(desc[first_period_idx+1:end])
als = keys(filter(x->x[2]==attribute, _keyAliases)) |> collect |> sort
als = join(map(string,als), ", ")
def = _attribute_defaults[attrtype][attribute]
-785
View File
@@ -1,788 +1,3 @@
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
isdefined(Plots, Symbol("#@layout")) && precompile(Tuple{getfield(Plots, Symbol("#@layout")), LineNumberNode, Module, Expr})
isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Array{Int64, 1}}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}}, Symbol})
isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Int64})
isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}, Array{Float64, 1}}, Tuple{Int64, Int64}})
isdefined(Plots, Symbol("#kw##_make_hist")) && precompile(Tuple{getfield(Plots, Symbol("#kw##_make_hist")), NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}}, typeof(Plots._make_hist), Tuple{Array{Float64, 1}}, Symbol})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:flip,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:foreground_color_grid, :grid, :gridalpha, :gridstyle, :gridlinewidth), Tuple{ColorTypes.RGBA{Float64}, Bool, Float64, Symbol, Int64}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:formatter,), Tuple{Symbol}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :lims), Tuple{Bool, Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :lims, :flip), Tuple{Bool, Tuple{Int64, Int64}, Bool}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid, :ticks), Tuple{Bool, Nothing}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:grid,), Tuple{Bool}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:guide,), Tuple{String}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims, :flip, :ticks, :guide), Tuple{Tuple{Int64, Int64}, Bool, Base.StepRange{Int64, Int64}, String}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Float64}}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:lims,), Tuple{Tuple{Int64, Int64}}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:rotation,), Tuple{Int64}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:scale, :guide), Tuple{Symbol, String}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:ticks,), Tuple{Base.UnitRange{Int64}}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##attr!")) && precompile(Tuple{getfield(Plots, Symbol("#kw##attr!")), NamedTuple{(:ticks,), Tuple{Nothing}}, typeof(Plots.attr!), Plots.Axis})
isdefined(Plots, Symbol("#kw##contour")) && precompile(Tuple{getfield(Plots, Symbol("#kw##contour")), NamedTuple{(:fill,), Tuple{Bool}}, typeof(Plots.contour), Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int})
isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Array{Float64, 1}, Array{Float64, 1}})
isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Array{Int64, 1}, Array{Float64, 1}})
isdefined(Plots, Symbol("#kw##gr_polyline")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_polyline")), NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}}, typeof(Plots.gr_polyline), Base.UnitRange{Int64}, Array{Float64, 1}})
isdefined(Plots, Symbol("#kw##gr_set_font")) && precompile(Tuple{getfield(Plots, Symbol("#kw##gr_set_font")), NamedTuple{(:halign, :valign, :rotation), Tuple{Symbol, Symbol, Int64}}, typeof(Plots.gr_set_font), Plots.Font})
isdefined(Plots, Symbol("#kw##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_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}, Plots.Attr})
precompile(Tuple{typeof(Plots._add_the_series), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Plots.Attr})
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{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{Nothing, 1}, String})
precompile(Tuple{typeof(Plots._cbar_unique), Array{PlotUtils.ColorGradient, 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.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.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}, 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.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_subplot_extrema), Plots.Subplot{Plots.GRBackend}, Plots.Attr, Symbol})
precompile(Tuple{typeof(Plots._expand_subplot_extrema), Plots.Subplot{Plots.GRBackend}, Plots.Attr, 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), Plots.Attr, 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_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}, Plots.Attr})
precompile(Tuple{typeof(Plots._prepare_annotations), Plots.Subplot{Plots.GRBackend}, Plots.Attr})
precompile(Tuple{typeof(Plots._prepare_subplot), Plots.Plot{Plots.GRBackend}, Plots.Attr})
precompile(Tuple{typeof(Plots._prepare_subplot), Plots.Plot{Plots.GRBackend}, Plots.Attr})
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_barlike), Plots.Attr, Array{Float64, 1}, Array{Float64, 1}})
precompile(Tuple{typeof(Plots._preprocess_barlike), Plots.Attr, Array{Int64, 1}, Array{Float64, 1}})
precompile(Tuple{typeof(Plots._preprocess_barlike), Plots.Attr, Base.OneTo{Int64}, Array{Float64, 1}})
precompile(Tuple{typeof(Plots._preprocess_binlike), Plots.Attr, 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}, Plots.Attr})
precompile(Tuple{typeof(Plots._process_seriesrecipe), Plots.Plot{Plots.GRBackend}, Plots.Attr})
precompile(Tuple{typeof(Plots._process_seriesrecipe), Plots.Plot{Plots.GRBackend}, Plots.Attr})
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._replace_linewidth), Plots.Attr})
precompile(Tuple{typeof(Plots._replace_linewidth), Plots.Attr})
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), Plots.Attr, 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._slice_series_args!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Int64})
precompile(Tuple{typeof(Plots._slice_series_args!), Base.Dict{Symbol, Any}, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Int64})
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.Axis, Plots.Attr, Symbol, Int64})
precompile(Tuple{typeof(Plots._update_axis), Plots.Axis, Plots.Attr, 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), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Plots.Attr, Symbol, Int64})
precompile(Tuple{typeof(Plots._update_axis), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Plots.Attr, 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.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_plot_args), Plots.Plot{Plots.GRBackend}, Plots.Attr})
precompile(Tuple{typeof(Plots._update_plot_args), Plots.Plot{Plots.GRBackend}, Plots.Attr})
precompile(Tuple{typeof(Plots._update_series_attributes!), Plots.Attr, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
precompile(Tuple{typeof(Plots._update_series_attributes!), Plots.Attr, Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}})
precompile(Tuple{typeof(Plots._update_series_attributes!), Plots.Attr, 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}, Plots.Attr, Int64, Bool})
precompile(Tuple{typeof(Plots._update_subplot_args), Plots.Plot{Plots.GRBackend}, Plots.Subplot{Plots.GRBackend}, Plots.Attr, 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_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), Plots.Attr, Symbol, Base.Dict{Symbol, Symbol}, Array{Symbol, 1}, Int64})
precompile(Tuple{typeof(Plots.aliasesAndAutopick), Plots.Attr, Symbol, Base.Dict{Symbol, Symbol}, Array{Symbol, 1}, Int64})
precompile(Tuple{typeof(Plots.all3D), Base.Dict{Symbol, Any}})
precompile(Tuple{typeof(Plots.all3D), Plots.Attr})
precompile(Tuple{typeof(Plots.allAlphas), Int64})
precompile(Tuple{typeof(Plots.allReals), 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_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})
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), Plots.Attr})
precompile(Tuple{typeof(Plots.build_layout), Plots.Attr})
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!), Plots.Attr, Symbol})
precompile(Tuple{typeof(Plots.color_or_nothing!), Plots.Attr, Symbol})
precompile(Tuple{typeof(Plots.colorbar_style), Plots.Series})
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_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.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!), Plots.Attr, Symbol, Symbol})
precompile(Tuple{typeof(Plots.ensure_gradient!), Plots.Attr, Symbol, Symbol})
precompile(Tuple{typeof(Plots.ensure_gradient!), Plots.Attr, 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, 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}, Plots.Attr})
precompile(Tuple{typeof(Plots.expand_extrema!), Plots.Subplot{Plots.GRBackend}, Plots.Attr})
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), Plots.Attr})
precompile(Tuple{typeof(Plots.fg_color), Plots.Attr})
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), 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.Subplot{Plots.GRBackend}, Plots.Series})
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_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}})
precompile(Tuple{typeof(Plots.get_linestyle), Plots.Series, Int64})
precompile(Tuple{typeof(Plots.get_linewidth), Plots.Series, Int64})
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_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_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), 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_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_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{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, 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_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_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_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_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_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.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})
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})
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.StepRange{Int64, Int64}})
precompile(Tuple{typeof(Plots.ignorenan_extrema), Plots.Axis})
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), Plots.Attr})
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_axis_attr), 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), 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.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), Plots.Attr})
precompile(Tuple{typeof(Plots.isvertical), Plots.Attr})
precompile(Tuple{typeof(Plots.iter_segments), Array{Float64, 1}, 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.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), Int64, Int64})
precompile(Tuple{typeof(Plots.layout_args), Int64, Plots.GridLayout})
precompile(Tuple{typeof(Plots.layout_args), Int64})
precompile(Tuple{typeof(Plots.layout_args), Plots.Attr})
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.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.parse_axis_kw), Symbol})
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.preprocessArgs!), Plots.Attr})
precompile(Tuple{typeof(Plots.preprocessArgs!), Plots.Attr})
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.processGridArg!), Plots.Attr, Bool, 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.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.replaceAlias!), Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Symbol}})
precompile(Tuple{typeof(Plots.replaceAlias!), Plots.Attr, Symbol, Base.Dict{Symbol, Symbol}})
precompile(Tuple{typeof(Plots.replaceAliases!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Symbol}})
precompile(Tuple{typeof(Plots.replaceAliases!), Plots.Attr, Base.Dict{Symbol, Symbol}})
precompile(Tuple{typeof(Plots.reset_axis_defaults_byletter!)})
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), Plots.SeriesAnnotations})
precompile(Tuple{typeof(Plots.series_annotations_shapes!), Plots.Series, Symbol})
precompile(Tuple{typeof(Plots.series_idx), Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any}})
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.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, Int64, Bool})
precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Int64, Bool})
precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Plots.Attr, Symbol, Int64, Bool})
precompile(Tuple{typeof(Plots.slice_arg!), Base.Dict{Symbol, Any}, Plots.Attr, Symbol, Int64, Bool})
precompile(Tuple{typeof(Plots.slice_arg!), Plots.Attr, Plots.Attr, Symbol, Int64, Bool})
precompile(Tuple{typeof(Plots.slice_arg!), Plots.Attr, Plots.Attr, Symbol, 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), Tuple{Int64, Int64}, Tuple{Float64, Float64}, Array{Float64, 1}, Array{Float64, 1}, Int64})
precompile(Tuple{typeof(Plots.stroke), Int64, 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, Plots.Attr})
precompile(Tuple{typeof(Plots.warnOnUnsupported), Plots.GRBackend, Plots.Attr})
precompile(Tuple{typeof(Plots.warnOnUnsupported_args), Plots.GRBackend, Plots.Attr})
precompile(Tuple{typeof(Plots.warnOnUnsupported_args), Plots.GRBackend, Plots.Attr})
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, Symbol, Int64, Float64}})
precompile(Tuple{typeof(Plots.wraptuple), Tuple{}})
precompile(Tuple{typeof(Plots.xlims), Plots.Subplot{Plots.GRBackend}})
precompile(Tuple{typeof(Plots.yaxis!), String, Symbol})
precompile(Tuple{typeof(Plots.ylims), Plots.Subplot{Plots.GRBackend}})
end
+55 -109
View File
@@ -47,47 +47,16 @@ end
num_series(x::AMat) = size(x,2)
num_series(x) = 1
RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T"))
RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T"))
# ---------------------------------------------------------------------------
# for seriestype `line`, need to sort by x values
const POTENTIAL_VECTOR_ARGUMENTS = [
:seriescolor, :seriesalpha,
:linecolor, :linealpha, :linewidth, :linestyle, :line_z,
:fillcolor, :fillalpha, :fill_z,
:markercolor, :markeralpha, :markershape, :marker_z,
:markerstrokecolor, :markerstrokealpha,
:yerror, :yerror,
:series_annotations, :fillrange
]
@recipe function f(::Type{Val{:line}}, x, y, z)
indices = sortperm(x)
x := x[indices]
y := y[indices]
# sort vector arguments
for arg in POTENTIAL_VECTOR_ARGUMENTS
if typeof(plotattributes[arg]) <: AVec
plotattributes[arg] = _cycle(plotattributes[arg], indices)
end
end
# a tuple as fillrange has to be handled differently
if typeof(plotattributes[:fillrange]) <: Tuple
lower, upper = plotattributes[:fillrange]
if typeof(lower) <: AVec
lower = _cycle(lower, indices)
end
if typeof(upper) <: AVec
upper = _cycle(upper, indices)
end
plotattributes[:fillrange] = (lower, upper)
end
if typeof(z) <: AVec
z := z[indices]
end
@@ -96,6 +65,19 @@ const POTENTIAL_VECTOR_ARGUMENTS = [
end
@deps line path
function hvline_limits(axis::Axis)
vmin, vmax = axis_limits(axis)
if vmin >= vmax
if isfinite(vmin)
vmax = vmin + 1
else
vmin, vmax = 0.0, 1.1
end
end
vmin, vmax
end
@recipe function f(::Type{Val{:hline}}, x, y, z)
n = length(y)
newx = repeat(Float64[-1, 1, NaN], n)
@@ -239,13 +221,12 @@ end
@recipe function f(::Type{Val{:sticks}}, x, y, z)
n = length(x)
fr = plotattributes[:fillrange]
if fr === nothing
sp = plotattributes[:subplot]
yaxis = sp[:yaxis]
if fr == nothing
yaxis = plotattributes[:subplot][:yaxis]
fr = if yaxis[:scale] == :identity
0.0
else
NaNMath.min(axis_limits(sp, :y)[1], ignorenan_minimum(y))
NaNMath.min(axis_limits(yaxis)[1], ignorenan_minimum(y))
end
end
newx, newy = zeros(3n), zeros(3n)
@@ -291,13 +272,13 @@ end
# create segmented bezier curves in place of line segments
@recipe function f(::Type{Val{:curves}}, x, y, z; npoints = 30)
args = z !== nothing ? (x,y,z) : (x,y)
args = z != nothing ? (x,y,z) : (x,y)
newx, newy = zeros(0), zeros(0)
fr = plotattributes[:fillrange]
newfr = fr !== nothing ? zeros(0) : nothing
newz = z !== nothing ? zeros(0) : nothing
newfr = fr != nothing ? zeros(0) : nothing
newz = z != nothing ? zeros(0) : nothing
# lz = plotattributes[:line_z]
# newlz = lz !== nothing ? zeros(0) : nothing
# newlz = lz != nothing ? zeros(0) : nothing
# for each line segment (point series with no NaNs), convert it into a bezier curve
# where the points are the control points of the curve
@@ -306,13 +287,13 @@ end
ts = range(0, stop = 1, length = npoints)
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts))
if z !== nothing
if z != nothing
nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
end
if fr !== nothing
if fr != nothing
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
end
# if lz !== nothing
# if lz != nothing
# lzrng = _cycle(lz, rng) # the line_z's for this segment
# push!(newlz, 0.0)
# append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
@@ -321,16 +302,16 @@ end
x := newx
y := newy
if z === nothing
if z == nothing
seriestype := :path
else
seriestype := :path3d
z := newz
end
if fr !== nothing
if fr != nothing
fillrange := newfr
end
# if lz !== nothing
# if lz != nothing
# # line_z := newlz
# linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad())
# end
@@ -357,19 +338,19 @@ end
# compute half-width of bars
bw = plotattributes[:bar_width]
hw = if bw === nothing
hw = if bw == nothing
if nx > 1
0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx)))
else
0.5 * _bar_width
end
else
Float64[0.5_cycle(bw,i) for i=eachindex(procx)]
Float64[0.5_cycle(bw,i) for i=1:length(procx)]
end
# make fillto a vector... default fills to 0
fillto = plotattributes[:fillrange]
if fillto === nothing
if fillto == nothing
fillto = 0
end
if (yscale in _logScales) && !all(_is_positive, fillto)
@@ -491,7 +472,7 @@ end
@recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
if (plotattributes[:bar_width] === nothing)
if (plotattributes[:bar_width] == nothing)
bar_width := diff(edge)
end
x := _bin_centers(edge)
@@ -533,20 +514,18 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S
last_w = eltype(weights)(NaN)
while it_tuple_e !== nothing && it_tuple_w !== nothing
while it_tuple_e != nothing && it_tuple_w != nothing
b, it_state_e = it_tuple_e
w, it_state_w = it_tuple_w
if (log_scale_x && a 0)
a = oftype(a, b/_logScaleBases[xscale]^3)
a = b/_logScaleBases[xscale]^3
end
if isnan(w)
if !isnan(last_w)
push!(x, a)
push!(y, baseline)
push!(x, NaN)
push!(y, NaN)
end
else
if isnan(last_w)
@@ -559,8 +538,8 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S
push!(y, w)
end
a = oftype(a, b)
last_w = oftype(last_w, w)
a = b
last_w = w
it_tuple_e = iterate(edge, it_state_e)
it_tuple_w = iterate(weights, it_state_w)
@@ -610,8 +589,7 @@ Plots.@deps stepbins path
wand_edges(x...) = (@warn("Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto)
function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N
max_bins = 10_000
_cl(x) = min(ceil(Int, max(x, one(x))), max_bins)
_cl(x) = ceil(Int, max(x, one(x)))
_iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1))
_span(v) = maximum(v) - minimum(v)
@@ -638,7 +616,7 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S
elseif mode == :fd # FreedmanDiaconis rule
_cl(_span(v) / (2 * _iqr(v) / nd))
elseif mode == :wand
_cl(wand_edges(v)) # this makes this function not type stable, but the type instability does not propagate
wand_edges(v) # this makes this function not type stable, but the type instability does not propagate
else
error("Unknown auto-binning mode $mode")
end
@@ -667,7 +645,7 @@ end
function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
localvs = _filternans(vs)
edges = _hist_edges(localvs, binning)
h = float( weights === nothing ?
h = float( weights == nothing ?
StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left)
)
@@ -746,14 +724,12 @@ end
edge_x, edge_y, weights = x, y, z.surf
float_weights = float(weights)
if !plotattributes[:show_empty_bins]
if float_weights === weights
float_weights = deepcopy(float_weights)
end
for (i, c) in enumerate(float_weights)
if c == 0
float_weights[i] = NaN
end
if float_weights === weights
float_weights = deepcopy(float_weights)
end
for (i, c) in enumerate(float_weights)
if c == 0
float_weights[i] = NaN
end
end
@@ -813,7 +789,7 @@ end
# ---------------------------------------------------------------------------
# Error Bars
function error_style!(plotattributes::AKW)
function error_style!(plotattributes::KW)
plotattributes[:seriestype] = :path
plotattributes[:linecolor] = plotattributes[:markerstrokecolor]
plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
@@ -874,8 +850,8 @@ end
# ---------------------------------------------------------------------------
# quiver
# function apply_series_recipe(plotattributes::AKW, ::Type{Val{:quiver}})
function quiver_using_arrows(plotattributes::AKW)
# function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
function quiver_using_arrows(plotattributes::KW)
plotattributes[:label] = ""
plotattributes[:seriestype] = :path
if !isa(plotattributes[:arrow], Arrow)
@@ -913,8 +889,8 @@ function quiver_using_arrows(plotattributes::AKW)
# KW[plotattributes]
end
# function apply_series_recipe(plotattributes::AKW, ::Type{Val{:quiver}})
function quiver_using_hack(plotattributes::AKW)
# function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
function quiver_using_hack(plotattributes::KW)
plotattributes[:label] = ""
plotattributes[:seriestype] = :shape
@@ -959,7 +935,7 @@ function quiver_using_hack(plotattributes::AKW)
# KW[plotattributes]
end
# function apply_series_recipe(plotattributes::AKW, ::Type{Val{:quiver}})
# function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
@recipe function f(::Type{Val{:quiver}}, x, y, z)
if :arrow in supported_attrs()
quiver_using_arrows(plotattributes)
@@ -998,7 +974,7 @@ function get_xy(o::OHLC, x, xdiff)
end
# get the joined vector
function get_xy(v::AVec{OHLC}, x = eachindex(v))
function get_xy(v::AVec{OHLC}, x = 1:length(v))
xdiff = 0.3ignorenan_mean(abs.(diff(x)))
x_out, y_out = zeros(0), zeros(0)
for (i,ohlc) in enumerate(v)
@@ -1056,8 +1032,8 @@ end
@assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix
seriestype := :spy
mat = g.args[1]
n,m = axes(mat)
Plots.SliceIt, m, n, Surface(mat)
n,m = size(mat)
Plots.SliceIt, 1:m, 1:n, Surface(mat)
end
@recipe function f(::Type{Val{:spy}}, x,y,z)
@@ -1085,7 +1061,7 @@ end
# -------------------------------------------------
"Adds ax+b... straight line over the current plot, without changing the axis limits"
"Adds a+bx... straight line over the current plot, without changing the axis limits"
abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...)
abline!(args...; kw...) = abline!(current(), args...; kw...)
@@ -1101,12 +1077,6 @@ timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t)))
@recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter)
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter)
@recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter)
@recipe f(::Type{P}, t::P) where P <: Dates.Period = (t -> Dates.value(t), t -> string(P(t)))
# -------------------------------------------------
# Characters
@recipe f(::Type{<:AbstractChar}, ::AbstractChar) = (string, string)
# -------------------------------------------------
# Complex Numbers
@@ -1185,33 +1155,9 @@ end
seriestype := :shape
# create a filled polygon for each item
for c=axes(weights,2)
for c=1:size(weights,2)
sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1]))
sy = vcat(returns, reverse(returns))
@series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx)
end
end
"""
areaplot([x,] y)
areaplot!([x,] y)
Draw a stacked area plot of the matrix y.
# Examples
```julia-repl
julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4])
```
"""
@userplot AreaPlot
@recipe function f(a::AreaPlot)
data = cumsum(a.args[end], dims=2)
x = length(a.args) == 1 ? (axes(data, 1)) : a.args[1]
seriestype := :line
for i in axes(data, 2)
@series begin
fillrange := i > 1 ? data[:,i-1] : 0
x, data[:,i]
end
end
end
+127 -107
View File
@@ -7,77 +7,85 @@
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
const MaybeNumber = Union{Number, Missing}
const MaybeString = Union{AbstractString, Missing}
const DataPoint = Union{MaybeNumber, MaybeString}
prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting")
prepareSeriesData(::Nothing) = nothing
prepareSeriesData(t::Tuple{T, T}) where {T<:Number} = t
prepareSeriesData(f::Function) = f
prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!(
x -> ismissing(x) || isinf(x) ? NaN : x,
map(float,a))
prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image
prepareSeriesData(v::Volume) = Volume(prepareSeriesData(v.v), v.x_extents, v.y_extents, v.z_extents)
all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none))
# default: assume x represents a single series
convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)]
# unknown
convertToAnyVector(x, plotattributes::KW) = error("No user recipe defined for $(typeof(x))")
# missing
convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n]
convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing
# vector of data points is a single series
convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)]
# numeric vector
convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing
convertToAnyVector(v::AVec{Union{Missing, T}}, plotattributes::KW) where {T<:Number} = Any[replace(v, missing => NaN)], nothing
# string vector
convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing
convertToAnyVector(v::AVec{Union{Missing, T}}, plotattributes::KW) where {T<:AbstractString} = Any[replace(v, missing => "")], nothing
function convertToAnyVector(v::AMat, plotattributes::KW)
v = handlemissings(v)
if all3D(plotattributes)
Any[Surface(v)]
else
Any[v[:,i] for i in 1:size(v,2)]
end, nothing
end
handlemissings(v::AMat) = v
handlemissings(v::AMat{T}) where T <: Number = replace(v, missing => NaN)
handlemissings(v::AMat{T}) where T <: String = replace(v, missing => "")
# function
convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing
# surface
convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing
# volume
convertToAnyVector(v::Volume, plotattributes::KW) = Any[v], nothing
# # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing
# # dates
convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
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)
function convertToAnyVector(v::AVec, plotattributes::KW)
if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
else
vcat((convertToAnyVector(vi, plotattributes) for vi in v)...)
# something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing
end
end
# Matrix is split into columns
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
convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing
function convertToAnyVector(args...)
error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))")
end
# --------------------------------------------------------------------
# Fillranges & ribbons
process_fillrange(range::Number, plotattributes) = [range]
process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes)
process_ribbon(ribbon::Number, plotattributes) = [ribbon]
process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes)
# ribbon as a tuple: (lower_ribbons, upper_ribbons)
process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAnyVector(ribbon[1], plotattributes),
convertToAnyVector(ribbon[2], plotattributes)))
# --------------------------------------------------------------------
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
# result in that array being shared. push!, etc will add too many items to that array
compute_x(x::Nothing, y::Nothing, z) = axes(z,1)
compute_x(x::Nothing, y, z) = axes(y,1)
compute_x(x::Nothing, y::Nothing, z) = 1:size(z,1)
compute_x(x::Nothing, y, z) = 1:size(y,1)
compute_x(x::Function, y, z) = map(x, y)
compute_x(x, y, z) = copy(x)
# compute_y(x::Void, y::Function, z) = error()
compute_y(x::Nothing, y::Nothing, z) = axes(z,2)
compute_y(x::Nothing, y::Nothing, z) = 1:size(z,2)
compute_y(x, y::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y)
@@ -127,17 +135,24 @@ struct SliceIt end
z = z.data
end
xs = convertToAnyVector(x, plotattributes)
ys = convertToAnyVector(y, plotattributes)
zs = convertToAnyVector(z, plotattributes)
xs, _ = convertToAnyVector(x, plotattributes)
ys, _ = convertToAnyVector(y, plotattributes)
zs, _ = convertToAnyVector(z, plotattributes)
fr = pop!(plotattributes, :fillrange, nothing)
fillranges = process_fillrange(fr, plotattributes)
fillranges, _ = if typeof(fr) <: Number
([fr],nothing)
else
convertToAnyVector(fr, plotattributes)
end
mf = length(fillranges)
rib = pop!(plotattributes, :ribbon, nothing)
ribbons = process_ribbon(rib, plotattributes)
ribbons, _ = if typeof(rib) <: Number
([fr],nothing)
else
convertToAnyVector(rib, plotattributes)
end
mr = length(ribbons)
# @show zs
@@ -178,9 +193,8 @@ _apply_type_recipe(plotattributes, v) = RecipesBase.apply_recipe(plotattributes,
# This sort of recipe should return a pair of functions... one to convert to number,
# and one to format tick values.
function _apply_type_recipe(plotattributes, v::AbstractArray)
isempty(skipmissing(v)) && return Float64[]
x = first(skipmissing(v))
args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args
isempty(v) && return Float64[]
args = RecipesBase.apply_recipe(plotattributes, typeof(v[1]), v[1])[1].args
if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function
numfunc, formatter = args
Formatted(map(numfunc, v), formatter)
@@ -267,7 +281,7 @@ end
# # --------------------------------------------------------------------
# helper function to ensure relevant attributes are wrapped by Surface
function wrap_surfaces(plotattributes::AKW)
function wrap_surfaces(plotattributes::KW)
if haskey(plotattributes, :fill_z)
v = plotattributes[:fill_z]
if !isa(v, Surface)
@@ -278,14 +292,12 @@ end
@recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing)
all3D(plotattributes) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none))
# return a surface if this is a 3d plot, otherwise let it be sliced up
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing}
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat}
if all3D(plotattributes)
n,m = axes(mat)
n,m = size(mat)
wrap_surfaces(plotattributes)
SliceIt, m, n, Surface(mat)
SliceIt, 1:m, 1:n, Surface(mat)
else
SliceIt, nothing, mat, nothing
end
@@ -295,16 +307,16 @@ end
@recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix
if all3D(plotattributes)
mat = fmt.data
n,m = axes(mat)
n,m = size(mat)
wrap_surfaces(plotattributes)
SliceIt, m, n, Formatted(Surface(mat), fmt.formatter)
SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter)
else
SliceIt, nothing, fmt, nothing
end
end
# assume this is a Volume, so construct one
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Union{Number,Missing}
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Number
seriestype := :volume
SliceIt, nothing, Volume(vol, args...), nothing
end
@@ -320,35 +332,35 @@ function clamp_greys!(mat::AMat{T}) where T<:Gray
end
@recipe function f(mat::AMat{T}) where T<:Gray
n, m = axes(mat)
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
SliceIt, m, n, Surface(clamp_greys!(mat))
SliceIt, 1:m, 1:n, Surface(clamp_greys!(mat))
else
seriestype := :heatmap
yflip --> true
cbar --> false
fillcolor --> ColorGradient([:black, :white])
SliceIt, m, n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.))
SliceIt, 1:m, 1:n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.))
end
end
# # images - colors
@recipe function f(mat::AMat{T}) where T<:Colorant
n, m = axes(mat)
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
SliceIt, m, n, Surface(mat)
SliceIt, 1:m, 1:n, Surface(mat)
else
seriestype := :heatmap
yflip --> true
cbar --> false
z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat)
SliceIt, m, n, Surface(z)
SliceIt, 1:m, 1:n, Surface(z)
end
end
@@ -367,29 +379,23 @@ end
@recipe function f(shapes::AMat{Shape})
seriestype --> :shape
for j in axes(shapes,2)
for j in 1:size(shapes,2)
@series coords(vec(shapes[:,j]))
end
end
# Dicts: each entry is a data point (x,y)=(key,value)
@recipe f(d::AbstractDict) = collect(keys(d)), collect(values(d))
# function without range... use the current range of the x-axis
@recipe function f(f::FuncOrFuncs{F}) where F<:Function
plt = plotattributes[:plot_object]
xmin, xmax = if haskey(plotattributes, :xlims)
plotattributes[:xlims]
else
try
axis_limits(plt[1], :x)
catch
xinv = invscalefunc(get(plotattributes, :xscale, :identity))
xm = tryrange(f, xinv.([-5,-1,0,0.01]))
xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01])))
end
xmin, xmax = try
axis_limits(plt[1][:xaxis])
catch
xinv = invscalefunc(get(plotattributes, :xscale, :identity))
xm = tryrange(f, xinv.([-5,-1,0,0.01]))
xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01])))
end
f, xmin, xmax
@@ -520,25 +526,20 @@ end
# # special handling... xmin/xmax with parametric function(s)
@recipe function f(f::Function, xmin::Number, xmax::Number)
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
_scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
xs = _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
xs, f
end
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
xs = Array{Any}(undef, length(fs))
ys = Array{Any}(undef, length(fs))
for (i, (x, y)) in enumerate(_scaled_adapted_grid(f, xscale, yscale, xmin, xmax) for f in fs)
xs[i] = x
ys[i] = y
end
xs, ys
xs = Any[_scaled_adapted_grid(f, xscale, yscale, xmin, xmax) for f in fs]
xs, fs
end
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = fx, fy, range(umin, stop = umax, length = n)
function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
(xf, xinv), (yf, yinv) = ((scalefunc(s),invscalefunc(s)) for s in (xscale,yscale))
xs, ys = adapted_grid(yf∘f∘xinv, xf.((xmin, xmax)))
xinv.(xs), yinv.(ys)
xinv.(adapted_grid(yf∘f∘xinv, xf.((xmin, xmax))))
end
#
@@ -553,17 +554,36 @@ end
#
#
# # --------------------------------------------------------------------
# # Lists of tuples and GeometryTypes.Points
# # Lists of tuples and StaticArrays
# # --------------------------------------------------------------------
#
# # if we get an unhandled tuple, just splat it in
@recipe f(tup::Tuple) = tup
@recipe f(v::AVec{<:Tuple}) = unzip(v)
@recipe f(v::AVec{<:GeometryTypes.Point}) = unzip(v)
@recipe f(tup::Tuple) = [tup]
@recipe f(p::GeometryTypes.Point) = [p]
#
# # (x,y) tuples
@recipe f(xy::AVec{Tuple{R1,R2}}) where {R1<:Number,R2<:Number} = unzip(xy)
@recipe f(xy::Tuple{R1,R2}) where {R1<:Number,R2<:Number} = [xy[1]], [xy[2]]
# Special case for 4-tuples in :ohlc series
@recipe f(xyuv::AVec{<:Tuple{R1,R2,R3,R4}}) where {R1,R2,R3,R4} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
#
# # (x,y,z) tuples
@recipe f(xyz::AVec{Tuple{R1,R2,R3}}) where {R1<:Number,R2<:Number,R3<:Number} = unzip(xyz)
@recipe f(xyz::Tuple{R1,R2,R3}) where {R1<:Number,R2<:Number,R3<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
# these might be points+velocity, or OHLC or something else
@recipe f(xyuv::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
@recipe f(xyuv::Tuple{R1,R2,R3,R4}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
#
# # 2D StaticArrays
@recipe f(xy::AVec{StaticArrays.SVector{2,T}}) where {T<:Number} = unzip(xy)
@recipe f(xy::StaticArrays.SVector{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
#
# # 3D StaticArrays
@recipe f(xyz::AVec{StaticArrays.SVector{3,T}}) where {T<:Number} = unzip(xyz)
@recipe f(xyz::StaticArrays.SVector{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
#
# # --------------------------------------------------------------------
@@ -584,7 +604,7 @@ end
# end
splittable_kw(key, val, lengthGroup) = false
splittable_kw(key, val::AbstractArray, lengthGroup) = !(key in (:group, :color_palette)) && length(axes(val,1)) == lengthGroup
splittable_kw(key, val::AbstractArray, lengthGroup) = (key != :group) && size(val,1) == lengthGroup
splittable_kw(key, val::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup))
splittable_kw(key, val::SeriesAnnotations, lengthGroup) = splittable_kw(key, val.strs, lengthGroup)
@@ -598,7 +618,7 @@ end
function groupedvec2mat(x_ind, x, y::AbstractArray, groupby, def_val = y[1])
y_mat = Array{promote_type(eltype(y), typeof(def_val))}(undef, length(keys(x_ind)), length(groupby.groupLabels))
fill!(y_mat, def_val)
for i in eachindex(groupby.groupLabels)
for i in 1:length(groupby.groupLabels)
xi = x[groupby.groupIds[i]]
yi = y[groupby.groupIds[i]]
y_mat[getindex.(Ref(x_ind), xi), i] = yi
@@ -631,7 +651,7 @@ group_as_matrix(t) = false
if length(g.args) == 1
x = zeros(Int, lengthGroup)
for indexes in groupby.groupIds
x[indexes] = eachindex(indexes)
x[indexes] = 1:length(indexes)
end
last_args = g.args
else
@@ -639,7 +659,7 @@ group_as_matrix(t) = false
last_args = g.args[2:end]
end
x_u = unique(sort(x))
x_ind = Dict(zip(x_u, eachindex(x_u)))
x_ind = Dict(zip(x_u, 1:length(x_u)))
for (key,val) in plotattributes
if splittable_kw(key, val, lengthGroup)
:($key) := groupedvec2mat(x_ind, x, val, groupby)
+70 -70
View File
@@ -2,10 +2,10 @@
scatter(x,y)
scatter!(x,y)
Make a scatter plot of y vs x.
Make a scatter plot of y vs x.
# Examples
```julia-repl
```julia-repl
julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue])
julia> scatter([(1,4),(2,5),(3,6)])
```
@@ -16,9 +16,9 @@ julia> scatter([(1,4),(2,5),(3,6)])
bar(x,y)
bar!(x,y)
Make a bar plot of y vs x.
Make a bar plot of y vs x.
# Arguments
# Arguments
- $(_document_argument("bar_position"))
- $(_document_argument("bar_width"))
@@ -26,7 +26,7 @@ Make a bar plot of y vs x.
- $(_document_argument("orientation"))
# Examples
```julia-repl
```julia-repl
julia> bar([1,2,3],[4,5,6],fillcolor=[:red,:green,:blue],fillalpha=[0.2,0.4,0.6])
julia> bar([(1,4),(2,5),(3,6)])
```
@@ -41,7 +41,7 @@ julia> bar([(1,4),(2,5),(3,6)])
Plot a histogram.
# Arguments
# Arguments
- `x`: AbstractVector of values to be binned
- $(_document_argument("bins"))
@@ -53,7 +53,7 @@ Plot a histogram.
- $(_document_argument("orientation"))
# Example
```julia-repl
```julia-repl
julia> histogram([1,2,1,1,4,3,8],bins=0:8)
```
"""
@@ -63,7 +63,7 @@ julia> histogram([1,2,1,1,4,3,8],bins=0:8)
barhist(x)
barhist!(x)
Make a histogram bar plot. See `histogram`.
Make a histogram bar plot. See `histogram`.
"""
@shorthands barhist
@@ -72,7 +72,7 @@ Make a histogram bar plot. See `histogram`.
stephist(x)
Make a histogram step plot (bin counts are represented using horizontal lines
instead of bars). See `histogram`.
instead of bars). See `histogram`.
"""
@shorthands stephist
@@ -80,8 +80,8 @@ instead of bars). See `histogram`.
scatterhist(x)
scatterhist!(x)
Make a histogram scatter plot (bin counts are represented using points
instead of bars). See `histogram`.
Make a histogram scatter plot (bin counts are represented using points
instead of bars). See `histogram`.
"""
@shorthands scatterhist
@@ -91,14 +91,14 @@ instead of bars). See `histogram`.
Plot a two-dimensional histogram.
# Arguments
# Arguments
- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`)
- `weights`: Vector of weights for the values in `x`. Each entry of x contributes
its weight to the height of its bin.
- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`)
- `weights`: Vector of weights for the values in `x`. Each entry of x contributes
its weight to the height of its bin.
# Example
```julia-repl
```julia-repl
julia> histogram2d(randn(10_000),randn(10_000))
```
"""
@@ -108,14 +108,14 @@ julia> histogram2d(randn(10_000),randn(10_000))
density(x)
density!(x)
Make a line plot of a kernel density estimate of x.
Make a line plot of a kernel density estimate of x.
# Arguments
- `x`: AbstractVector of samples for probability density estimation
- `x`: AbstractVector of samples for probability density estimation
# Example
```julia-repl
```julia-repl
julia> using StatsPlots
julia> density(randn(100_000))
```
@@ -126,10 +126,10 @@ julia> density(randn(100_000))
heatmap(x,y,z)
heatmap!(x,y,z)
Plot a heatmap of the rectangular array `z`.
Plot a heatmap of the rectangular array `z`.
# Example
```julia-repl
```julia-repl
julia> heatmap(randn(10,10))
```
"""
@@ -140,7 +140,7 @@ julia> heatmap(randn(10,10))
hexbin(x,y)
hexbin!(x,y)
Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])`
Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])`
with hexagonal bins)
# Example
@@ -154,11 +154,11 @@ julia> hexbin(randn(10_000), randn(10_000))
sticks(x,y)
sticks!(x,y)
Draw a stick plot of y vs x.
Draw a stick plot of y vs x.
# Example
```julia-repl
julia> sticks(1:10)
julia> sticks(1:10)
```
"""
@shorthands sticks
@@ -167,11 +167,11 @@ julia> sticks(1:10)
hline(y)
hline!(y)
Draw horizontal lines at positions specified by the values in
Draw horizontal lines at positions specified by the values in
the AbstractVector `y`
# Example
```julia-repl
```julia-repl
julia> hline([-1,0,2])
```
"""
@@ -181,11 +181,11 @@ julia> hline([-1,0,2])
vline(x)
vline!(x)
Draw vertical lines at positions specified by the values in
Draw vertical lines at positions specified by the values in
the AbstractVector `x`
# Example
```julia-repl
```julia-repl
julia> vline([-1,0,2])
```
"""
@@ -194,13 +194,13 @@ julia> vline([-1,0,2])
"""
hspan(y)
Draw a rectangle between the horizontal line at position `y[1]`
and the horizontal line at position `y[2]`. If `length(y) ≥ 4`,
then further rectangles are drawn between `y[3]` and `y[4]`,
`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the
last entry of `y` is ignored.
Draw a rectangle between the horizontal line at position `y[1]`
and the horizontal line at position `y[2]`. If `length(y) ≥ 4`,
then further rectangles are drawn between `y[3]` and `y[4]`,
`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the
last entry of `y` is ignored.
# Example
```julia-repl
```julia-repl
julia> hspan(1:6)
```
"""
@@ -209,13 +209,13 @@ julia> hspan(1:6)
"""
vspan(x)
Draw a rectangle between the vertical line at position `x[1]`
and the vertical line at position `x[2]`. If `length(x) ≥ 4`,
then further rectangles are drawn between `x[3]` and `x[4]`,
`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the
last entry of `x` is ignored.
Draw a rectangle between the vertical line at position `x[1]`
and the vertical line at position `x[2]`. If `length(x) ≥ 4`,
then further rectangles are drawn between `x[3]` and `x[4]`,
`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the
last entry of `x` is ignored.
# Example
```julia-repl
```julia-repl
julia> vspan(1:6)
```
"""
@@ -225,9 +225,9 @@ julia> vspan(1:6)
ohlc(x,y::Vector{OHLC})
ohlc!(x,y::Vector{OHLC})
Make open-high-low-close plot. Each entry of y is represented by a vertical
segment extending from the low value to the high value, with short horizontal
segments on the left and right indicating the open and close values, respectively.
Make open-high-low-close plot. Each entry of y is represented by a vertical
segment extending from the low value to the high value, with short horizontal
segments on the left and right indicating the open and close values, respectively.
# Example
```julia-repl
@@ -240,16 +240,16 @@ julia> ohlc(y)
"""
contour(x,y,z)
contour!(x,y,z)
contour(x,y,z)
contour!(x,y,z)
Draw contour lines of the `Surface` z.
Draw contour lines of the `Surface` z.
# Arguments
- `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`)
- `fill`: Bool. Fill area between contours or draw contours only (false by default)
# Example
# Example
```julia-repl
julia> x = y = range(-20, 20, length = 100)
julia> contour(x, y, (x, y) -> x^2 + y^2)
@@ -267,10 +267,10 @@ julia> contour(x, y, (x, y) -> x^2 + y^2)
surface(x,y,z)
surface!(x,y,z)
Draw a 3D surface plot.
Draw a 3D surface plot.
# Example
```julia-repl
```julia-repl
julia> x = y = range(-3, 3, length = 100)
julia> surface(x, y, (x, y) -> sinc(norm([x, y])))
```
@@ -281,10 +281,10 @@ julia> surface(x, y, (x, y) -> sinc(norm([x, y])))
wireframe(x,y,z)
wireframe!(x,y,z)
Draw a 3D wireframe plot.
Draw a 3D wireframe plot.
# Example
```julia-repl
```julia-repl
julia> wireframe(1:10,1:10,randn(10,10))
```
"""
@@ -295,10 +295,10 @@ julia> wireframe(1:10,1:10,randn(10,10))
path3d!(x,y,z)
Plot a 3D path from `(x[1],y[1],z[1])` to `(x[2],y[2],z[2])`,
..., to `(x[end],y[end],z[end])`.
..., to `(x[end],y[end],z[end])`.
# Example
```julia-repl
```julia-repl
julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
```
"""
@@ -308,10 +308,10 @@ julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
scatter3d(x,y,z)
scatter3d!(x,y,z)
Make a 3D scatter plot.
Make a 3D scatter plot.
# Example
```julia-repl
```julia-repl
julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
```
"""
@@ -321,17 +321,17 @@ julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
boxplot(x, y)
boxplot!(x, y)
Make a box and whisker plot.
Make a box and whisker plot.
# Keyword arguments
- `notch`: Bool. Notch the box plot? (false)
- `range`: Real. Values more than range*IQR below the first quartile
or above the third quartile are shown as outliers (1.5)
- `outliers`: Bool. Show outliers? (true)
- `whisker_width`: Real or Symbol. Length of whiskers (:match)
or above the third quartile are shown as outliers (1.5)
- `outliers`: Bool. Show outliers? (true)
- `whisker_width`: Real or Symbol. Length of whiskers (:match)
# Example
```julia-repl
```julia-repl
julia> using StatsPlots
julia> boxplot(repeat([1,2,3],outer=100),randn(300))
```
@@ -342,10 +342,10 @@ julia> boxplot(repeat([1,2,3],outer=100),randn(300))
violin(x,y,z)
violin!(x,y,z)
Make a violin plot.
Make a violin plot.
# Example
```julia-repl
```julia-repl
julia> violin(repeat([1,2,3],outer=100),randn(300))
```
"""
@@ -355,11 +355,11 @@ julia> violin(repeat([1,2,3],outer=100),randn(300))
quiver(x,y,quiver=(u,v))
quiver!(x,y,quiver=(u,v))
Make a quiver (vector field) plot. The `i`th vector extends
from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`.
Make a quiver (vector field) plot. The `i`th vector extends
from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`.
# Example
```julia-repl
```julia-repl
julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3]))
```
"""
@@ -369,11 +369,11 @@ julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3]))
curves(x,y)
curves!(x,y)
Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])`
Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])`
with control points `(x[2],y[2]), ..., (x[end-1],y[end]-1)`
# Example
```julia-repl
```julia-repl
julia> curves([1,2,3,4],[1,1,2,4])
```
"""
@@ -424,9 +424,9 @@ ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} =
"""
annotate!(anns...)
Add annotations to an existing plot.
Add annotations to an existing plot.
# Arguments
# Arguments
- `anns`: An `AbstractVector` of tuples of the form (x,y,text). The text object
can be an String or PlotText
@@ -449,7 +449,7 @@ yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip
"Specify x axis attributes for an existing plot"
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
"Specify y axis attributes for an existing plot"
"Specify x axis attributes for an existing plot"
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
+1 -1
View File
@@ -7,7 +7,7 @@ function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
(20mm, 5mm, 2mm, 10mm),
defaultbox,
defaultbox,
Attr(KW(), _subplot_defaults),
KW(),
nothing,
nothing
)
+35 -18
View File
@@ -4,19 +4,39 @@
Specify the colour theme for plots.
"""
function theme(s::Symbol; kw...)
defaults = copy(PlotThemes._themes[s].defaults)
defaults = _get_defaults(s)
_theme(s, defaults; kw...)
end
function _theme(s::Symbol, defaults::AKW; kw...)
function _get_defaults(s::Symbol)
thm = PlotThemes._themes[s]
if :defaults in fieldnames(typeof(thm))
return thm.defaults
else # old PlotTheme type
defaults = KW(
:bg => thm.bg_secondary,
:bginside => thm.bg_primary,
:fg => thm.lines,
:fgtext => thm.text,
:fgguide => thm.text,
:fglegend => thm.text,
:palette => thm.palette,
)
if thm.gradient != nothing
push!(defaults, :gradient => thm.gradient)
end
return defaults
end
end
function _theme(s::Symbol, defaults::KW; kw...)
# Reset to defaults to overwrite active theme
reset_defaults()
# Set the theme's gradient as default
if haskey(defaults, :colorgradient)
if haskey(defaults, :gradient)
PlotUtils.clibrary(:misc)
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
pop!(defaults, :colorgradient)
else
PlotUtils.clibrary(:Plots)
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
@@ -24,8 +44,8 @@ function _theme(s::Symbol, defaults::AKW; kw...)
# maybe overwrite the theme's gradient
kw = KW(kw)
if haskey(kw, :colorgradient)
kwgrad = pop!(kw, :colorgradient)
if haskey(kw, :gradient)
kwgrad = pop!(kw, :gradient)
for clib in clibraries()
if kwgrad in cgradients(clib)
PlotUtils.clibrary(clib)
@@ -54,11 +74,11 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
@recipe function showtheme(st::ShowTheme)
thm, cfunc = _get_showtheme_args(st.args...)
defaults = PlotThemes._themes[thm].defaults
defaults = _get_defaults(thm)
# get the gradient
gradient_colors = get(defaults, :colorgradient, cgrad(:inferno).colors)
colorgradient = cgrad(cfunc.(RGB.(gradient_colors)))
gradient_colors = get(defaults, :gradient, cgrad(:inferno).colors)
gradient = cgrad(cfunc.(RGB.(gradient_colors)))
# get the palette
palette = get(defaults, :palette, get_color_palette(:auto, plot_color(:white), 17))
@@ -66,7 +86,7 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
# apply the theme
for k in keys(defaults)
k in (:colorgradient, :palette) && continue
k in (:gradient, :palette) && continue
def = defaults[k]
arg = get(_keyAliases, k, k)
plotattributes[arg] = if typeof(def) <: Colorant
@@ -119,30 +139,27 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
@series begin
subplot := 4
seriestype := :heatmap
seriescolor := colorgradient
xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
seriescolor := gradient
ticks := -5:5:5
x, y, z
end
@series begin
subplot := 5
seriestype := :surface
seriescolor := colorgradient
xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
seriescolor := gradient
x, y, z
end
n = 100
ts = range(0, stop = 10π, length = n)
x = (0.1ts) .* cos.(ts)
x = ts .* cos.(ts)
y = (0.1ts) .* sin.(ts)
z = 1:n
@series begin
subplot := 6
seriescolor := colorgradient
seriescolor := gradient
linewidth := 3
line_z := z
x, y, z
+6 -59
View File
@@ -5,7 +5,6 @@
const AVec = AbstractVector
const AMat = AbstractMatrix
const KW = Dict{Symbol,Any}
const AKW = AbstractDict{Symbol,Any}
const TicksArgs = Union{AVec{T}, Tuple{AVec{T}, AVec{S}}, Symbol} where {T<:Real, S<:AbstractString}
struct PlotsDisplay <: AbstractDisplay end
@@ -19,63 +18,10 @@ wrap(obj::T) where {T} = InputWrapper{T}(obj)
Base.isempty(wrapper::InputWrapper) = false
# -----------------------------------------------------------
struct Attr <: AbstractDict{Symbol,Any}
explicit::KW
defaults::KW
end
Base.getindex(attr::Attr, k) = haskey(attr.explicit,k) ?
attr.explicit[k] : attr.defaults[k]
Base.haskey(attr::Attr, k) = haskey(attr.explicit,k) || haskey(attr.defaults,k)
Base.get(attr::Attr, k, default) = haskey(attr, k) ? attr[k] : default
function Base.get!(attr::Attr, k, default)
v = if haskey(attr, k)
attr[k]
else
attr.defaults[k] = default
end
return v
end
function Base.delete!(attr::Attr, k)
haskey(attr.explicit, k) && delete!(attr.explicit, k)
haskey(attr.defaults, k) && delete!(attr.defaults, k)
end
Base.length(attr::Attr) = length(union(keys(attr.explicit), keys(attr.defaults)))
function Base.iterate(attr::Attr)
exp_keys = keys(attr.explicit)
def_keys = setdiff(keys(attr.defaults), exp_keys)
key_list = collect(Iterators.flatten((exp_keys, def_keys)))
iterate(attr, (key_list, 1))
end
function Base.iterate(attr::Attr, (key_list, i))
i > length(key_list) && return nothing
k = key_list[i]
(k=>attr[k], (key_list, i+1))
end
Base.copy(attr::Attr) = Attr(copy(attr.explicit), attr.defaults)
RecipesBase.is_explicit(attr::Attr, k) = haskey(attr.explicit,k)
isdefault(attr::Attr, k) = !is_explicit(attr,k) && haskey(attr.defaults,k)
Base.setindex!(attr::Attr, v, k) = attr.explicit[k] = v
# Reset to default value and return dict
reset_kw!(attr::Attr, k) = is_explicit(attr, k) ? delete!(attr.explicit, k) : attr
# Reset to default value and return old value
pop_kw!(attr::Attr, k) = is_explicit(attr, k) ? pop!(attr.explicit, k) : attr.defaults[k]
pop_kw!(attr::Attr, k, default) = is_explicit(attr, k) ? pop!(attr.explicit, k) : get(attr.defaults, k, default)
# Fallbacks for dicts without defaults
reset_kw!(d::AKW, k) = delete!(d, k)
pop_kw!(d::AKW, k) = pop!(d, k)
pop_kw!(d::AKW, k, default) = pop!(d, k, default)
# -----------------------------------------------------------
mutable struct Series
plotattributes::Attr
plotattributes::KW
end
attr(series::Series, k::Symbol) = series.plotattributes[k]
@@ -90,7 +36,7 @@ mutable struct Subplot{T<:AbstractBackend} <: AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox # the canvas area which is available to this subplot
plotarea::BoundingBox # the part where the data goes
attr::Attr # args specific to this subplot
attr::KW # args specific to this subplot
o # can store backend-specific data... like a pyplot ax
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
end
@@ -102,7 +48,7 @@ Base.show(io::IO, sp::Subplot) = print(io, "Subplot{$(sp[:subplot_index])}")
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
mutable struct Axis
sps::Vector{Subplot}
plotattributes::Attr
plotattributes::KW
end
mutable struct Extrema
@@ -121,7 +67,8 @@ const SubplotMap = Dict{Any, Subplot}
mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
backend::T # the backend type
n::Int # number of series
attr::Attr # arguments for the whole plot
attr::KW # arguments for the whole plot
user_attr::KW # raw arg inputs (after aliases). these are used as the input dict in `_plot!`
series_list::Vector{Series} # arguments for each series
o # the backend's plot object
subplots::Vector{Subplot}
@@ -132,7 +79,7 @@ mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
end
function Plot()
Plot(backend(), 0, Attr(KW(), _plot_defaults), Series[], nothing,
Plot(backend(), 0, KW(), KW(), Series[], nothing,
Subplot[], SubplotMap(), EmptyLayout(),
Subplot[], false)
end
+149 -187
View File
@@ -26,7 +26,7 @@ function histogramHack(; kw...)
plotattributes[:x] = midpoints
plotattributes[:y] = float(counts)
plotattributes[:seriestype] = :bar
plotattributes[:fillrange] = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
plotattributes[:fillrange] = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
plotattributes
end
@@ -38,12 +38,12 @@ function barHack(; kw...)
plotattributes = KW(kw)
midpoints = plotattributes[:x]
heights = plotattributes[:y]
fillrange = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
fillrange = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
# estimate the edges
dists = diff(midpoints) * 0.5
edges = zeros(length(midpoints)+1)
for i in eachindex(edges)
for i in 1:length(edges)
if i == 1
edge = midpoints[1] - dists[1]
elseif i == length(edges)
@@ -56,7 +56,7 @@ function barHack(; kw...)
x = Float64[]
y = Float64[]
for i in eachindex(heights)
for i in 1:length(heights)
e1, e2 = edges[i:i+1]
append!(x, [e1, e1, e2, e2])
append!(y, [fillrange, heights[i], heights[i], fillrange])
@@ -81,7 +81,7 @@ function sticksHack(; kw...)
# these are the line vertices
x = Float64[]
y = Float64[]
fillrange = plotattributesLine[:fillrange] === nothing ? 0.0 : plotattributesLine[:fillrange]
fillrange = plotattributesLine[:fillrange] == nothing ? 0.0 : plotattributesLine[:fillrange]
# calculate the vertices
yScatter = plotattributesScatter[:y]
@@ -115,6 +115,7 @@ function regressionXY(x, y)
end
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
@show T, size(z)
n, m = size(z)
# idx = 0
colors = ColorGradient(vec(z))
@@ -129,7 +130,7 @@ function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
# newz, ColorGradient(colors)
end
function imageHack(plotattributes::AKW)
function imageHack(plotattributes::KW)
is_seriestype_supported(:heatmap) || error("Neither :image or :heatmap are supported!")
plotattributes[:seriestype] = :heatmap
plotattributes[:z], plotattributes[:fillcolor] = replace_image_with_heatmap(plotattributes[:z].surf)
@@ -145,18 +146,16 @@ end
Segments() = Segments(Float64)
Segments(::Type{T}) where {T} = Segments(T[])
Segments(p::Int) = Segments(NTuple{p, Float64}[])
Segments(p::Int) = Segments(NTuple{2,Float64}[])
# Segments() = Segments(zeros(0))
to_nan(::Type{Float64}) = NaN
to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
to_nan(::Type{NTuple{3,Float64}}) = (NaN, NaN, NaN)
coords(segs::Segments{Float64}) = segs.pts
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
coords(segs::Segments{NTuple{3,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts], Float64[p[3] for p in segs.pts]
function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts)
@@ -184,26 +183,22 @@ end
mutable struct SegmentsIterator
args::Tuple
n1::Int
n2::Int
n::Int
end
function iter_segments(args...)
tup = Plots.wraptuple(args)
n1 = minimum(map(firstindex, tup))
n2 = maximum(map(lastindex, tup))
SegmentsIterator(tup, n1, n2)
n = maximum(map(length, tup))
SegmentsIterator(tup, n)
end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
if x === nothing
return UnitRange{Int}[]
elseif has_attribute_segments(series)
if has_attribute_segments(series)
if series[:seriestype] in (:scatter, :scatter3d)
return [[i] for i in eachindex(y)]
return [[i] for i in 1:length(y)]
else
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
return [i:(i + 1) for i in 1:(length(y) - 1)]
end
else
segs = UnitRange{Int}[]
@@ -217,19 +212,36 @@ end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> try isnan(_cycle(a,i)) catch MethodError false end, args)
anynan(args::Tuple) = i -> anynan(i,args)
anynan(istart::Int, iend::Int, args::Tuple) = any(anynan(args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend)
anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(i -> anynan(i, args), istart:iend)
function Base.iterate(itr::SegmentsIterator, nextidx::Int = itr.n1)
i = findfirst(!anynan(itr.args), nextidx:itr.n2)
i === nothing && return nothing
nextval = nextidx + i - 1
function Base.iterate(itr::SegmentsIterator, nextidx::Int = 1)
nextidx > itr.n && return nothing
if nextidx == 1 && !any(isempty,itr.args) && anynan(1, itr.args)
nextidx = 2
end
j = findfirst(anynan(itr.args), nextval:itr.n2)
nextnan = j === nothing ? itr.n2 + 1 : nextval + j - 1
i = istart = iend = nextidx
nextval:nextnan-1, nextnan
# find the next NaN, and iend is the one before
while i <= itr.n + 1
if i > itr.n || anynan(i, itr.args)
# done... array end or found NaN
iend = i-1
break
end
i += 1
end
# find the next non-NaN, and set nextidx
while i <= itr.n
if !anynan(i, itr.args)
break
end
i += 1
end
istart:iend, i
end
# Find minimal type that can contain NaN and x
@@ -261,9 +273,6 @@ _cycle(v, indices::AVec{Int}) = fill(v, length(indices))
_cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
_as_gradient(grad::ColorGradient) = grad
_as_gradient(c::Colorant) = ColorGradient([c,c])
makevec(v::AVec) = v
makevec(v::T) where {T} = T[v]
@@ -274,17 +283,18 @@ maketuple(x::Tuple{T,S}) where {T,S} = x
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
mapFuncOrFuncs(fs::AVec{F}, u::AVec) where {F<:Function} = [map(f, u) for f in fs]
for i in 2:4
@eval begin
unzip(v::Union{AVec{<:Tuple{Vararg{T,$i} where T}},
AVec{<:GeometryTypes.Point{$i}}}) = $(Expr(:tuple, (:([t[$j] for t in v]) for j=1:i)...))
end
end
unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] for t in xy]
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
unzip(v::Union{AVec{<:GeometryTypes.Point{N}},
AVec{<:Tuple{Vararg{T,N} where T}}}) where N = error("$N-dimensional unzip not implemented.")
unzip(v::Union{AVec{<:GeometryTypes.Point},
AVec{<:Tuple}}) = error("Can't unzip points of different dimensions.")
unzip(xy::AVec{StaticArrays.SVector{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
unzip(xy::StaticArrays.SVector{2,T}) where {T} = T[xy[1]], T[xy[2]]
unzip(xyz::AVec{StaticArrays.SVector{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
unzip(xyz::StaticArrays.SVector{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip(xyuv::AVec{StaticArrays.SVector{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
unzip(xyuv::StaticArrays.SVector{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x)
@@ -318,13 +328,13 @@ function replaceType(vec, val)
push!(vec, val)
end
function replaceAlias!(plotattributes::AKW, k::Symbol, aliases::Dict{Symbol,Symbol})
function replaceAlias!(plotattributes::KW, k::Symbol, aliases::Dict{Symbol,Symbol})
if haskey(aliases, k)
plotattributes[aliases[k]] = pop_kw!(plotattributes, k)
plotattributes[aliases[k]] = pop!(plotattributes, k)
end
end
function replaceAliases!(plotattributes::AKW, aliases::Dict{Symbol,Symbol})
function replaceAliases!(plotattributes::KW, aliases::Dict{Symbol,Symbol})
ks = collect(keys(plotattributes))
for k in ks
replaceAlias!(plotattributes, k, aliases)
@@ -346,11 +356,8 @@ const _scale_base = Dict{Symbol, Real}(
:ln => ,
)
function _heatmap_edges(v::AVec, isedges::Bool = false)
function _heatmap_edges(v::AVec)
length(v) == 1 && return v[1] .+ [-0.5, 0.5]
if isedges return v end
# `isedges = true` means that v is a vector which already describes edges
# and does not need to be extended.
vmin, vmax = ignorenan_extrema(v)
extra_min = (v[2] - v[1]) / 2
extra_max = (v[end] - v[end - 1]) / 2
@@ -358,40 +365,43 @@ function _heatmap_edges(v::AVec, isedges::Bool = false)
end
"create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges(v::AVec, scale::Symbol = :identity, isedges::Bool = false)
function heatmap_edges(v::AVec, scale::Symbol = :identity)
f, invf = scalefunc(scale), invscalefunc(scale)
map(invf, _heatmap_edges(map(f,v), isedges))
map(invf, _heatmap_edges(map(f,v)))
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
function calc_r_extrema(x, y)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
ignorenan_extrema(r)
end
function is_uniformly_spaced(v; tol=1e-6)
dv = diff(v)
maximum(dv) - minimum(dv) < tol * mean(abs.(dv))
end
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
rmin, rmax = r_extrema
theta, r = filter_radial_data(x, y, r_extrema)
r = (r .- rmin) ./ (rmax .- rmin)
x = r.*cos.(theta)
y = r.*sin.(theta)
x, y
end
# Filters radial data for points within the axis limits
function filter_radial_data(theta, r, r_extrema::Tuple{Real, Real})
n = max(length(theta), length(r))
rmin, rmax = r_extrema
x, y = zeros(n), zeros(n)
for i in 1:n
x[i] = _cycle(theta, i)
y[i] = _cycle(r, i)
end
points = map((a, b) -> (a, b), x, y)
filter!(a -> a[2] >= rmin && a[2] <= rmax, points)
x = map(a -> a[1], points)
y = map(a -> a[2], points)
x, y
end
function fakedata(sz...)
y = zeros(sz...)
for r in 2:size(y,1)
@@ -415,13 +425,13 @@ isscalar(::Any) = false
is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2
isvertical(plotattributes::AKW) = get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert)
isvertical(plotattributes::KW) = get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert)
isvertical(series::Series) = isvertical(series.plotattributes)
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = :ticks_and_labels
ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels
ticksType(ticks) = :invalid
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
@@ -499,13 +509,13 @@ function make_fillrange_side(y, rib)
end
# turn a ribbon into a fillrange
function make_fillrange_from_ribbon(kw::AKW)
function make_fillrange_from_ribbon(kw::KW)
y, rib = kw[:y], kw[:ribbon]
rib = wraptuple(rib)
rib1, rib2 = -first(rib), last(rib)
# kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2)
(get(kw, :fillalpha, nothing) === nothing) && (kw[:fillalpha] = 0.5)
(get(kw, :fillalpha, nothing) == nothing) && (kw[:fillalpha] = 0.5)
end
#turn tuple of fillranges to one path
@@ -517,7 +527,7 @@ function concatenate_fillrange(x,y::Tuple)
end
function get_sp_lims(sp::Subplot, letter::Symbol)
axis_limits(sp, letter)
axis_limits(sp[Symbol(letter, :axis)])
end
"""
@@ -550,93 +560,56 @@ zlims(sp_idx::Int = 1) = zlims(current(), sp_idx)
function get_clims(sp::Subplot)
zmin, zmax = Inf, -Inf
for series in series_list(sp)
if series[:colorbar_entry]
zmin, zmax = _update_clims(zmin, zmax, get_clims(series)...)
end
end
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
function get_clims(sp::Subplot, series::Series)
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)...)
for series in series_list(sp)
for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Real)
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
elseif (vals != nothing) && (eltype(vals) <: Real)
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
end
end
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
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) : (-0.1, 0.1)
end
_update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax)
_update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
function colorbar_style(series::Series)
colorbar_entry = series[:colorbar_entry]
if !(colorbar_entry isa Bool)
@warn "Non-boolean colorbar_entry ignored."
colorbar_entry = true
function hascolorbar(series::Series)
st = series[:seriestype]
hascbar = st == :heatmap
if st == :contour
hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1)
end
if !colorbar_entry
nothing
elseif isfilledcontour(series)
cbar_fill
elseif iscontour(series)
cbar_lines
elseif series[:seriestype] (:heatmap,:surface) ||
any(series[z] !== nothing for z [:marker_z,:line_z,:fill_z])
cbar_gradient
else
nothing
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
end
# no colorbar if we are creating a surface LightSource
if xor(st == :surface, series[:fill_z] != nothing)
hascbar = true
end
return hascbar
end
hascolorbar(series::Series) = colorbar_style(series) !== nothing
hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
iscontour(series::Series) = series[:seriestype] == :contour
isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing
function contour_levels(series::Series, clims)
iscontour(series) || error("Not a contour series")
zmin, zmax = clims
levels = series[:levels]
if levels isa Integer
levels = range(zmin, stop=zmax, length=levels+2)
if !isfilledcontour(series)
levels = levels[2:end-1]
function hascolorbar(sp::Subplot)
cbar = sp[:colorbar]
hascbar = false
if cbar != :none
for series in series_list(sp)
if hascolorbar(series)
hascbar = true
end
end
end
levels
hascbar
end
for comp in (:line, :fill, :marker)
compcolor = string(comp, :color)
@@ -651,7 +624,7 @@ for comp in (:line, :fill, :marker)
function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
c = series[$Symbol($compcolor)]
z = series[$Symbol($comp_z)]
if z === nothing
if z == nothing
isa(c, ColorGradient) ? c : plot_color(_cycle(c, i))
else
grad = isa(c, ColorGradient) ? c : cgrad()
@@ -662,7 +635,7 @@ for comp in (:line, :fill, :marker)
$get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1)
if series[$Symbol($comp_z)] === nothing
if series[$Symbol($comp_z)] == nothing
$get_compcolor(series, 0, 1, i)
else
$get_compcolor(series, get_clims(series[:subplot]), i)
@@ -673,9 +646,6 @@ for comp in (:line, :fill, :marker)
end
end
single_color(c, v = 0.5) = c
single_color(grad::ColorGradient, v = 0.5) = grad[v]
function get_linewidth(series, i::Int = 1)
_cycle(series[:linewidth], i)
end
@@ -699,11 +669,11 @@ function has_attribute_segments(series::Series)
for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and
# SegmentsIterator is used
series[letter] !== nothing && NaN in collect(series[letter]) && return false
series[letter] != nothing && NaN in collect(series[letter]) && return false
end
series[:seriestype] == :shape && return false
# ... else we check relevant attributes if they have multiple inputs
return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :linestyle, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z))
return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray{<:Real} for attr in (:line_z, :fill_z, :marker_z))
end
# ---------------------------------------------------------------
@@ -826,24 +796,24 @@ function debugplots(on = true)
_debugMode.on = on
end
debugshow(io, x) = show(io, x)
debugshow(io, x::AbstractArray) = print(io, summary(x))
debugshow(x) = show(x)
debugshow(x::AbstractArray) = print(summary(x))
function dumpdict(io::IO, plotattributes::AKW, prefix = "", alwaysshow = false)
function dumpdict(plotattributes::KW, prefix = "", alwaysshow = false)
_debugMode.on || alwaysshow || return
println(io)
println()
if prefix != ""
println(io, prefix, ":")
println(prefix, ":")
end
for k in sort(collect(keys(plotattributes)))
@printf("%14s: ", k)
debugshow(io, plotattributes[k])
println(io)
debugshow(plotattributes[k])
println()
end
println(io)
println()
end
DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix)
DD(plotattributes::KW, prefix = "") = dumpdict(plotattributes, prefix, true)
function dumpcallstack()
error() # well... you wanted the stacktrace, didn't you?!?
@@ -1109,15 +1079,6 @@ legendfont(sp::Subplot) = font(
sp[:legendfontcolor],
)
legendtitlefont(sp::Subplot) = font(
sp[:legendtitlefontfamily],
sp[:legendtitlefontsize],
sp[:legendtitlefontvalign],
sp[:legendtitlefonthalign],
sp[:legendtitlefontrotation],
sp[:legendtitlefontcolor],
)
tickfont(ax::Axis) = font(
ax[:tickfontfamily],
ax[:tickfontsize],
@@ -1164,20 +1125,20 @@ function convert_sci_unicode(label::AbstractString)
label
end
function straightline_data(series, expansion_factor = 1)
function straightline_data(series)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
n = length(x)
if n == 2
return straightline_data(xl, yl, x, y, expansion_factor)
return straightline_data(xl, yl, x, y)
else
k, r = divrem(n, 3)
if r == 0
xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k
inds = (3 * i - 2):(3 * i - 1)
xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds], expansion_factor)
xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds])
end
return xdata, ydata
else
@@ -1186,7 +1147,7 @@ function straightline_data(series, expansion_factor = 1)
end
end
function straightline_data(xl, yl, x, y, expansion_factor = 1)
function straightline_data(xl, yl, x, y)
x_vals, y_vals = if y[1] == y[2]
if x[1] == x[2]
error("Two identical points cannot be used to describe a straight line.")
@@ -1207,28 +1168,29 @@ function straightline_data(xl, yl, x, y, expansion_factor = 1)
end
# expand the data outside the axis limits, by a certain factor too improve
# plotly(js) and interactive behaviour
x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* expansion_factor .* [-1, 1]
y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* expansion_factor .* [-1, 1]
factor = 100
x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* factor .* [-1, 1]
y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* factor .* [-1, 1]
return x_vals, y_vals
end
function shape_data(series, expansion_factor = 1)
function shape_data(series)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
factor = 100
for i in eachindex(x)
if x[i] == -Inf
x[i] = xl[1] - expansion_factor * (xl[2] - xl[1])
x[i] = xl[1] - factor * (xl[2] - xl[1])
elseif x[i] == Inf
x[i] = xl[2] + expansion_factor * (xl[2] - xl[1])
x[i] = xl[2] + factor * (xl[2] - xl[1])
end
end
for i in eachindex(y)
if y[i] == -Inf
y[i] = yl[1] - expansion_factor * (yl[2] - yl[1])
y[i] = yl[1] - factor * (yl[2] - yl[1])
elseif y[i] == Inf
y[i] = yl[2] + expansion_factor * (yl[2] - yl[1])
y[i] = yl[2] + factor * (yl[2] - yl[1])
end
end
return x, y
@@ -1246,8 +1208,8 @@ function _fmt_paragraph(io::IOBuffer,
fillwidth=60,
leadingspaces=0)
kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces)
kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces)
m = match(r"(.*?) (.*)",remaining_text)
if isa(m,Nothing)
if column_count + length(remaining_text) fillwidth
-1
View File
@@ -1 +0,0 @@
reference_images
+10
View File
@@ -0,0 +1,10 @@
StatsPlots
Images
ImageMagick
@osx QuartzImageIO
FileIO
GR 0.31.0
RDatasets
VisualRegressionTests
UnicodePlots
LaTeXStrings
+50
View File
@@ -0,0 +1,50 @@
using Pkg
# need this to use Conda
# ENV["PYTHON"] = ""
to_add = [
# PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"),
PackageSpec(name="PlotUtils", rev="master"),
PackageSpec(name="RecipesBase", rev="master"),
# PackageSpec(name="Blink", rev="master"),
# PackageSpec(name="Rsvg", rev="master"),
# PackageSpec(name="PlotlyJS", rev="master"),
# PackageSpec(name="VisualRegressionTests", rev="master"),
# PackageSpec("PyPlot"),
# PackageSpec("InspectDR"),
]
if isinteractive()
Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"))
append!(to_add, [
PackageSpec(name="FileIO"),
PackageSpec(name="ImageMagick"),
PackageSpec(name="UnicodePlots"),
PackageSpec(name="VisualRegressionTests"),
PackageSpec(name="Gtk"),
# PlotlyJS:
# PackageSpec(name="PlotlyJS"),
# PackageSpec(name="Blink"),
# PackageSpec(name="ORCA"),
# PyPlot:
# PackageSpec(name="PyPlot"),
# PackageSpec(name="PyCall"),
# PackageSpec(name="LaTeXStrings"),
])
else
push!(to_add, PackageSpec(
name="PlotReferenceImages",
url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git",
rev = "sd-tomls"
))
end
Pkg.add(to_add)
Pkg.build("ImageMagick")
# Pkg.build("GR")
# Pkg.build("Blink")
# import Blink
# Blink.AtomShell.install()
# Pkg.build("PyPlot")
+73 -9
View File
@@ -1,28 +1,92 @@
using VisualRegressionTests
# using ExamplePlots
if isinteractive()
@eval Main import Gtk
end
# import DataFrames, RDatasets
# don't let pyplot use a gui... it'll crash
# note: Agg will set gui -> :none in PyPlot
# ENV["MPLBACKEND"] = "Agg"
# try
# @eval import PyPlot
# @info("Matplotlib version: $(PyPlot.matplotlib[:__version__])")
# end
using Plots
# using StatsPlots
import PlotReferenceImages
using Random
using Test
default(size=(500,300))
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
import Plots._current_plots_version
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = !is_ci(), sigma = [1,1], tol = 1e-2)
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2)
Plots._debugMode.on = debug
example = Plots._examples[idx]
Plots.theme(:default)
@info("Testing plot: $pkg:$idx:$(example.header)")
backend(pkg)
backend()
default(size=(500,300))
# ensure consistent results
Random.seed!(1234)
# reference image directory setup
# refdir = joinpath(Pkg.dir("ExamplePlots"), "test", "refimg", string(pkg))
refdir = joinpath(dirname(pathof(PlotReferenceImages)), "..", "Plots", string(pkg))
fn = "ref$idx.png"
reffn = reference_file(pkg, idx, _current_plots_version)
newfn = joinpath(reference_path(pkg, _current_plots_version), fn)
# firgure out version info
vns = filter(x->x[1] != '.', readdir(refdir))
versions = sort(VersionNumber.(vns), rev = true)
versions = filter(v -> v <= _current_plots_version, versions)
# @show refdir fn versions
newdir = joinpath(refdir, string(_current_plots_version))
newfn = joinpath(newdir, fn)
# figure out which reference file we should compare to, by finding the highest versioned file
reffn = nothing
for v in versions
tmpfn = joinpath(refdir, string(v), fn)
if isfile(tmpfn)
reffn = tmpfn
break
end
end
# now we have the fn (if any)... do the comparison
# @show reffn
if reffn == nothing
reffn = newfn
end
# @show reffn
# return
# test function
func = (fn, idx) -> begin
expr = Expr(:block)
append!(expr.args, example.exprs)
eval(expr)
map(eval, example.exprs)
png(fn)
end
# try
# run(`mkdir -p $newdir`)
# catch err
# display(err)
# end
# # reffn = joinpath(refdir, "ref$idx.png")
# the test
vtest = VisualTest(func, reffn, idx)
test_images(vtest, popup=popup, sigma=sigma, tol=tol, newfn = newfn)
@@ -36,7 +100,7 @@ function image_comparison_facts(pkg::Symbol;
tol = 1e-2) # acceptable error (percent)
for i in 1:length(Plots._examples)
i in skip && continue
if only === nothing || i in only
if only == nothing || i in only
@test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, tol=tol) |> success == true
end
end
+127 -122
View File
@@ -1,92 +1,103 @@
import ImageMagick
using VisualRegressionTests
using Plots
using Random
using Test
using FileIO
using Gtk
using LibGit2
using GeometryTypes
using Dates
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
module PlotsTests
include("add_packages.jl")
include("imgcomp.jl")
# don't actually show the plots
Random.seed!(1234)
default(show=false, reuse=true)
is_ci() = get(ENV, "CI", "false") == "true"
img_tol = is_ci() ? 10e-2 : 10e-2
img_tol = isinteractive() ? 1e-2 : 10e-2
@testset "Backends" begin
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@static if Sys.islinux()
image_comparison_facts(:gr, tol=img_tol, skip = Plots._backend_skips[:gr])
end
@static if Sys.islinux()
image_comparison_facts(:gr, tol=img_tol, skip = [25, 30])
end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = bar(randn(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([1, 2], [3, 4])
annotate!(p, [(1.5, 3.2, Plots.text("Test", :red, :center))])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
hline!(p, [3.1])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, Plots.text("Test", :red, :center))])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, Plots.text("Test", :red, :center))])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
end
end
# @static if isinteractive()
# @testset "PyPlot" begin
# @test pyplot() == Plots.PyPlotBackend()
# @test backend() == Plots.PyPlotBackend()
#
# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31])
# end
# end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@test isa(plot(rand(10)), Plots.Plot) == true
end
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# @static if isinteractive()
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# image_comparison_facts(:plotlyjs,
# skip=[
# 2, # animation (skipped for speed)
# 25,
# 27, # (polar plots) takes very long / not working
# 30,
# 31, # animation (skipped for speed)
# ],
# tol=img_tol)
# end
# end
# InspectDR returns that error on travis:
# ERROR: LoadError: InitError: Cannot open display:
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
# @testset "InspectDR" begin
# @test inspectdr() == Plots.InspectDRBackend()
# @test backend() == Plots.InspectDRBackend()
#
# image_comparison_facts(:inspectdr,
# skip=[
# 2, # animation
# 6, # heatmap not defined
# 10, # heatmap not defined
# 22, # contour not defined
# 23, # pie not defined
# 27, # polar plot not working
# 28, # heatmap not defined
# 31, # animation
# ],
# tol=img_tol)
# end
# @testset "Plotly" begin
# @test plotly() == Plots.PlotlyBackend()
# @test backend() == Plots.PlotlyBackend()
#
# # # until png generation is reliable on OSX, just test on linux
# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol)
# end
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# # as long as we can plot anything without error, it should be the same as Plotly
# image_comparison_facts(:plotlyjs, only=[1], tol=img_tol)
# end
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@@ -102,52 +113,46 @@ end
end
@testset "NoFail" begin
plots = [histogram([1, 0, 0, 0, 0, 0]),
plot([missing]),
plot([missing; 1:4]),
plot([fill(missing,10); 1:4]),
plot([1 1; 1 missing]),
plot(["a" "b"; missing "d"], [1 2; 3 4])]
for plt in plots
display(plt)
end
@test_nowarn plot(x->x^2,0,2)
histogram([1, 0, 0, 0, 0, 0])
end
@testset "EmptyAnim" begin
anim = @animate for i in []
end
# tests for preprocessing recipes
@test_throws ArgumentError gif(anim)
end
# @testset "recipes" begin
@testset "Segments" begin
function segments(args...)
segs = UnitRange{Int}[]
for seg in iter_segments(args...)
push!(segs,seg)
end
segs
end
# user recipe
nan10 = fill(NaN,10)
@test segments(11:20) == [1:10]
@test segments([NaN]) == []
@test segments(nan10) == []
@test segments([nan10; 1:5]) == [11:15]
@test segments([1:5;nan10]) == [1:5]
@test segments([nan10; 1:5; nan10; 1:5; nan10]) == [11:15, 26:30]
@test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10]
@test segments([nan10; 1:15], [1:15; nan10]) == [11:15]
end
# type T end
# @recipe function f(::T)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# bg := :yellow
# rand(10)
# end
# plot(T())
@testset "Utils" begin
zipped = ([(1,2)], [("a","b")], [(1,"a"),(2,"b")],
[(1,2),(3,4)], [(1,2,3),(3,4,5)], [(1,2,3,4),(3,4,5,6)],
[(1,2.0),(missing,missing)], [(1,missing),(missing,"a")],
[(missing,missing)], [(missing,missing,missing),("a","b","c")])
for z in zipped
@test isequal(collect(zip(Plots.unzip(z)...)), z)
@test isequal(collect(zip(Plots.unzip(GeometryTypes.Point.(z))...)), z)
end
end
# plot recipe
# @recipe function f(::Type{Val{:hiplt}},plt::Plot)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# bg:=:green
# ()
# end
# plot(rand(10),t=:hiplt)
# series recipe
# @recipe function f(::Type{Val{:hi}},x,y,z)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# ()
# end
# plot(rand(10),t=:hiplt)
# end
end # module
+36
View File
@@ -0,0 +1,36 @@
import SnoopCompile
### Log the compiles
# This only needs to be run once (to generate "/tmp/plots_compiles.csv")
# SnoopCompile.@snoop "/tmp/plots_compiles.csv" begin
# include(joinpath(dirname(@__FILE__), "runtests.jl"))
# end
# ----------------------------------------------------------
### Parse the compiles and generate precompilation scripts
# This can be run repeatedly to tweak the scripts
# IMPORTANT: we must have the module(s) defined for the parcelation
# step, otherwise we will get no precompiles for the Plots module
using Plots
data = SnoopCompile.read("/tmp/plots_compiles.csv")
# The Plots tests are run inside a module PlotsTest, so all
# the precompiles get credited to PlotsTest. Credit them to Plots instead.
subst = Dict("PlotsTests"=>"Plots")
# Blacklist helps fix problems:
# - MIME uses type-parameters with symbols like :image/png, which is
# not parseable
blacklist = ["MIME"]
# Use these two lines if you want to create precompile functions for
# individual packages
pc, discards = SnoopCompile.parcel(data[end:-1:1,2], subst=subst, blacklist=blacklist)
SnoopCompile.write("/tmp/precompile", pc)
pdir = joinpath(dirname(@__FILE__), "..")
run(`cp /tmp/precompile/precompile_Plots.jl $pdir/src/precompile.jl`)
-166
View File
@@ -1,166 +0,0 @@
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