Compare commits

..
134 Commits
Author SHA1 Message Date
Daniel SchwabenederandGitHub f742ae4c88 Merge pull request #2025 from daschw/registrator
add author and version to Project.toml
2019-05-10 17:55:17 +02:00
Daniel Schwabeneder a99783dfa0 add author and version 2019-05-10 17:45:56 +02:00
Daniel SchwabenederandGitHub 9af5edd04d Merge pull request #2022 from JuliaPlots/sd-toml
use Project.toml + clean up test deps
2019-05-10 17:39:45 +02:00
SimonDanisch d0830b90be remove PlotReferenceImages 2019-05-09 13:06:05 +02:00
SimonDanisch 8cd48bc660 add back tomls 2019-05-09 13:01:49 +02:00
SimonDanisch 379a320d2d remove debug 2019-05-09 12:45:13 +02:00
SimonDanisch d5f3a3ef69 clean up & fix tests 2019-05-09 12:40:19 +02:00
SimonDanisch a3be970f29 get around registered PLotReferenceImages by downloading source of tags 2019-05-09 11:48:40 +02:00
SimonDanisch 63f8f52c9f remove REQUIRES 2019-05-09 11:06:22 +02:00
SimonDanisch 169851564c use Project.toml + clean up test deps 2019-05-08 17:23:36 +02:00
Daniel SchwabenederandGitHub c32b9029d1 Merge pull request #2016 from H-M-H/pgf_axis_arrows
Add attribute draw_arrow for axes.
2019-05-06 22:20:52 +02:00
Daniel SchwabenederandGitHub 3fe60b9d18 Merge pull request #2018 from daschw/legend
outer legends for gr and pyplot and guide/margin improvements for gr
2019-05-05 16:24:07 +02:00
Daniel Schwabeneder 34cff752f1 missing method for gr_set_transparency 2019-05-05 13:22:16 +02:00
Daniel Schwabeneder 0dba83daf6 fix gr alphas 2019-05-05 13:08:03 +02:00
Daniel Schwabeneder c399092261 fix animations for pyplot 2019-05-04 20:43:49 +02:00
Daniel Schwabeneder dcabb2c579 ticks, guides, margins for gr 2019-05-02 23:04:35 +02:00
Daniel SchwabenederandGitHub 3542785021 Merge pull request #2017 from daschw/recipe
fix recipe error
2019-05-02 16:13:47 +02:00
Daniel Schwabeneder 65173e6dd2 fix recipe error 2019-05-02 12:48:06 +02:00
Daniel Schwabeneder bf0bb68e28 only add half of ticks text size to min padding 2019-05-02 11:31:20 +02:00
Daniel Schwabeneder 21774dc36b consider rotation in gr_get_ticks_size 2019-05-02 11:27:16 +02:00
Daniel Schwabeneder 0e3a9f0b8f outer legends for GR 2019-05-02 11:18:17 +02:00
Daniel Schwabeneder 903cb404c3 shorter implementation 2019-05-01 12:12:51 +02:00
Daniel Schwabeneder 03325533bf outer legend positions for pyplot 2019-05-01 12:08:35 +02:00
HMH 710123aab4 Add attribute draw_arrow for axes.
The draw_arrow attribute enables drawing an arrow at the end of an axis.
Currently supported only by the PGFPlots backend.
2019-05-01 00:27:20 +02:00
Daniel Schwabeneder 4742ec972b allow numeric legend positioning in pyplot 2019-04-30 15:25:08 +02:00
Michael Krabbe BorregaardandGitHub e860ba220a Merge pull request #2011 from 8uurg/master
Make legend=:outertopright work for GR
2019-04-29 08:26:36 +02:00
8uurg 39605bccc2 Make legend=:outertopright work
Move x to the right of the plot viewport
Perform legend size computation earlier as this computed width is required for adjusting the width of the plotarea viewport.
This adjustment has to be done before any further computations requiring this plotarea viewport width.
2019-04-27 20:13:36 +02:00
Daniel SchwabenederandGitHub 1a4f411b8f Merge pull request #2010 from daschw/polar
Avoid filtering data in polar plots (fix #2009)
2019-04-26 18:45:12 +02:00
Daniel Schwabeneder a6588daa3e allow negative radii in polar plots for pyplot 2019-04-26 13:17:29 +02:00
Daniel Schwabeneder b053366b06 don't filter polar data 2019-04-26 13:03:03 +02:00
Michael Krabbe BorregaardandGitHub e838ac502d Merge pull request #1999 from mkborregaard/fix_io
[RFC] fix io; close #1998
2019-04-15 15:16:41 +02:00
Michael Krabbe Borregaard 6131154dd0 mixing ios in println 2019-04-15 15:13:22 +02:00
Michael Krabbe Borregaard 0c67a61e7d fix io 2019-04-15 09:07:52 +02:00
Daniel SchwabenederandGitHub 72696a4326 Merge pull request #1995 from daschw/marker
don't let `marker = true` set the marker size to 1 (fix #1994)
2019-04-12 14:12:40 +02:00
Daniel SchwabenederandGitHub 3231f4d9b1 Merge pull request #1996 from daschw/line
sort vector attributes for seriestype line (fix #1989)
2019-04-12 14:02:04 +02:00
Daniel Schwabeneder 8a81b398cf fix typo 2019-04-12 12:44:34 +02:00
Daniel Schwabeneder a37a1a0004 sort vector attributes for seriestype line 2019-04-12 12:41:49 +02:00
Daniel Schwabeneder b6b00c843a set default to :circle instead of :auto for marker = true 2019-04-12 09:42:19 +02:00
Daniel Schwabeneder 5506c0543c don't let marker = true set the marker size to 1 2019-04-12 09:24:28 +02:00
Michael Krabbe BorregaardandGitHub 7a1b48311c Merge pull request #1993 from mkborregaard/fix_plotattr
fix plotattr
2019-04-10 10:09:15 +02:00
Michael Krabbe Borregaard 0b3dafcd18 fix plotattr
`plotattr` would fail when the description did not have a period (`.`) in it, e.g. for `ticks`. This seemed safer than to edit the argument descriptions
2019-04-09 21:16:56 +02:00
Daniel SchwabenederandGitHub 81f6b3c7bd Merge pull request #1986 from daschw/geometrytypes
replace StaticArrays with GeometryTypes (fix #1886)
2019-04-08 12:46:57 +02:00
Daniel Schwabeneder c2da4acb48 update news 2019-04-07 16:23:26 +02:00
Daniel Schwabeneder 841b05631d replace StaticArrays with GeometryTypes 2019-04-07 16:20:15 +02:00
Daniel SchwabenederandGitHub a6e60aea04 Merge pull request #1982 from daschw/colorvector
fix passing a vector of colors
2019-04-04 14:23:18 +02:00
Daniel Schwabeneder 7f2a1db64a fix passing a vector of colors 2019-04-04 11:26:12 +02:00
Daniel SchwabenederandGitHub 926ccdf618 Merge pull request #1977 from daschw/colorbar-alpha
fix alpha for colorbar in GR (fix #1976)
2019-04-02 21:55:49 +02:00
Josef Heinen 9774eca8e2 bump GR version to 0.39.0 2019-04-02 20:55:51 +02:00
Josef HeinenandGitHub 2ad033f8e2 Merge pull request #1978 from jheinen/master
gr: use correct workstation type after savefig()
2019-04-01 14:18:51 +02:00
Josef Heinen 7c26ffee51 gr: use correct workstation type after savefig() 2019-04-01 14:05:32 +02:00
Daniel SchwabenederandGitHub aa37ba0463 Merge pull request #1970 from SebRollen/master
Update `yaxis!` description
2019-04-01 13:16:50 +02:00
Daniel Schwabeneder d61c86b54b fix alpha for colorbar in GR 2019-04-01 13:14:06 +02:00
Daniel SchwabenederandGitHub e72fa1dc74 Merge pull request #1971 from daschw/grid-ticks
don't draw ticks twice in gr for framestyle in (:zerolines, :grid)
2019-04-01 10:03:45 +02:00
Michael Krabbe BorregaardandGitHub 16db531cce Merge pull request #1969 from yha/contour-colorbar
Some more fixes for contours and colorbars (mostly GR)
2019-04-01 09:52:56 +02:00
Michael Krabbe BorregaardandGitHub 226023043b Merge pull request #1972 from hycakir/patch-1
fix `abline!` description
2019-03-30 12:16:35 +01:00
Hamza Yusuf ÇakırandGitHub 5d2538c4c2 fix abline! description
It should be `ax+b` rather than `a+bx`.
2019-03-30 12:09:17 +03:00
yharel 0075103ddf Proportional colorbar spacing in pyplot 2019-03-29 22:01:28 +03:00
yharel 8982a67902 Fix colorbar for misc. series types with line_z,fill_z,marker_z. 2019-03-29 21:20:36 +03:00
Daniel Schwabeneder 65ab45ff1b don't draw ticks twice in gr for framestyle in (:zerolines, :grid) 2019-03-29 10:38:22 +01:00
Sebastian RollenandGitHub 577d434bc8 Update yaxis! description
Just fixing a small typo. The description for `yaxis!` used to read "Specify x axis attributes for an existing plot", changed to "Specify y axis attributes for an existing plot"
2019-03-28 09:54:23 -04:00
Daniel SchwabenederandGitHub b300e634f6 Merge pull request #1968 from daschw/ticks
fix multiple drawing of discrete ticks
2019-03-28 09:24:46 +01:00
Josef Heinen 61d13b9b2d gr: improved positioning of Y labels 2019-03-28 08:39:15 +01:00
yharel 78059bf825 Support for non-gradient colors in surface-like plots (useful for contour) 2019-03-28 02:28:19 +02:00
yharel dd02a69e8f Consistent interpretation of contour levels across PyPlot,GR,Plotly[JS] backends.
GR: fixed colorbar rendering/alignment for contour[f]. Merged colorbar 
for mutiple series.
:colorbar_entry property to include series in colorbar.
2019-03-28 02:21:25 +02:00
Daniel Schwabeneder 5ec80ad1f1 fix multiple drawing of discrete ticks 2019-03-27 17:37:47 +01:00
Josef Heinen 4849772435 gr: improve Y label alignment 2019-03-26 14:30:14 +01:00
Daniel SchwabenederandGitHub 6546879d3a Merge pull request #1963 from daschw/init
fix init error if PLOTS_DEFAULTS <: Dict{Symbol, Symbol} (fix #1962)
2019-03-26 09:51:18 +01:00
Josef Heinen cbc379daa9 gr: fixed problem with blank figures
see https://github.com/jheinen/GR.jl/issues/202
2019-03-25 17:15:06 +01:00
Daniel Schwabeneder a7be08ef46 fix init error if PLOTS_DEFAULTS <: Dict{Symbol, Symbol} 2019-03-25 09:46:37 +01:00
Daniel SchwabenederandGitHub 47e48e5d27 Merge pull request #1958 from JuliaPlots/sd-gifmime
add support for gif mime
2019-03-25 09:35:25 +01:00
Daniel SchwabenederandGitHub 968b8109dd Merge pull request #1956 from daschw/pyplot-update
Pyplot API update (fix #1932)
2019-03-25 09:35:03 +01:00
SimonDanisch 19fba27951 don't read into a buffer first 2019-03-19 14:23:25 +01:00
SimonDanisch b78da20d04 add support for gif mime 2019-03-19 12:40:40 +01:00
Daniel Schwabeneder 5e445b4a71 update NEWS.md 2019-03-16 19:33:35 +01:00
Daniel Schwabeneder 0e5df883d0 add warning for PyCall version 2019-03-16 10:42:45 +01:00
Daniel Schwabeneder b79ea119ea use a.''foo'' instead of a.foo 2019-03-15 15:15:59 +01:00
Daniel Schwabeneder b21d98affd switch to new PyCall API 2019-03-15 15:13:57 +01:00
Daniel SchwabenederandGitHub d83666bed3 Merge pull request #1953 from daschw/polar-axis
put radius 0 at the center for polar plots (fix #1813)
2019-03-14 10:27:49 +01:00
Daniel Schwabeneder cab6ca3ef0 default to radius 0 at center for polar plots 2019-03-13 13:40:05 +01:00
Daniel SchwabenederandGitHub 33a37f9494 Merge pull request #1951 from daschw/gr-image
fix image axis limits
2019-03-13 09:37:02 +01:00
Daniel Schwabeneder 79e978aac9 fix image axis limits 2019-03-12 14:56:41 +01:00
Michael Krabbe BorregaardandGitHub 3af60a81f8 Merge pull request #1950 from JuliaPlots/sd-plotlyjson
add plotly json mime to PlotlyBackend as well
2019-03-12 14:21:07 +01:00
SimonDanisch 56525ced92 also add plotly json mime to PlotlyBackend 2019-03-12 12:59:19 +01:00
SimonandGitHub 581f3797bc Merge pull request #1943 from JuliaPlots/sd-plotlymime
support plotly mime type
2019-03-11 15:12:21 +01:00
SimonDanisch 2c8d51988b support plotly mime type 2019-03-07 19:04:18 +01:00
Daniel SchwabenederandGitHub 19243b741a Merge pull request #1939 from daschw/gr-ticks
fix `ticks = :none` for gr
2019-03-05 14:19:48 +01:00
Daniel SchwabenederandGitHub afc1e08f21 Merge pull request #1940 from daschw/plotly-flip
plotly: fix yflip for `ticks = :none` (fix #1937)
2019-03-05 14:19:33 +01:00
Daniel Schwabeneder 80c01e74c6 plotly: fix yflip for ticks = :none 2019-03-05 10:34:05 +01:00
Daniel Schwabeneder d728bfb90c don't show labels for ticks = :none 2019-03-05 10:01:06 +01:00
Daniel Schwabeneder 203d73ee26 fix ticks = :none for gr 2019-03-05 09:57:12 +01:00
Daniel SchwabenederandGitHub 05fe220102 Merge pull request #1936 from balazsmezei/pgfplots-tex-standalone
Add option :tex_output_standalone for standalone documentclass
2019-03-05 09:30:06 +01:00
Balázs Ferenc Mezei c4f2de198e Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend. 2019-03-03 00:04:05 +00:00
Michael Krabbe BorregaardandGitHub 50f9846836 Merge pull request #1933 from JuliaPlots/new_pyplot
update to `o.show` syntax. Close #1932
2019-03-01 07:55:11 +01:00
Michael Krabbe Borregaard a33b3cfbd8 check for pycall version 2019-02-28 23:50:06 +01:00
Michael Krabbe Borregaard 248f7cce90 update to o.show syntax 2019-02-28 23:32:57 +01:00
Josef HeinenandGitHub 8f381e2611 Merge pull request #1931 from apalugniok/gr-titles3d
Add 3D axes guides for GR (Fixes #743)
2019-02-27 12:25:18 +01:00
Andrew Palugniok f4b14d0d8d Add 3D axes guides for GR 2019-02-27 10:30:34 +00:00
Michael Krabbe BorregaardandGitHub 93428815e4 Merge pull request #1924 from H-M-H/pgf_vline
Add vline to PGFPlots.
2019-02-23 10:19:42 +01:00
Michael Krabbe BorregaardandGitHub 6b70610770 Merge pull request #1925 from H-M-H/pyplot_tex
Add LaTeX output for pyplot backend.
2019-02-23 10:10:58 +01:00
Michael Krabbe BorregaardandGitHub 84eead47e3 Merge pull request #1926 from H-M-H/plotly_fix
Fix #1961
2019-02-23 10:08:06 +01:00
HMH 009d03f1f8 Set default output for plotly to html.
There does not exist any other.
2019-02-23 04:59:58 +01:00
HMH 9482a247e7 Remove 2 lines forgotten in 3c2cfa333c. 2019-02-23 03:39:01 +01:00
HMH 022c79fa95 Add LaTeX output for pyplot backend.
Actually matplotlib supports outputting LaTeX via pgf:
https://matplotlib.org/users/pgf.html
2019-02-23 00:35:52 +01:00
HMH a9ed4ac21d Add vline to PGFPlots.
This enables proper vertical errorbars.
2019-02-22 17:50:15 +01:00
Michael Krabbe BorregaardandGitHub 354e39e9bf Merge pull request #1923 from harryscholes/fix-1918
plotlyjs: Fix custom tick labels do not work when supplied as a tuple
2019-02-21 21:08:01 +01:00
harryscholes 757e08c6fe Add Union{AVec,Tuple} to accepted types for ticksType 2019-02-21 17:59:27 +00:00
Josef HeinenandGitHub 33e5775294 Merge pull request #1922 from jheinen/master
bump GR version to 0.38.1
2019-02-19 10:27:13 +01:00
Josef Heinen 5b73a8ed1c bump GR version to 0.38.1 2019-02-19 09:39:06 +01:00
Josef Heinen f864ebbf1a Merge remote-tracking branch 'upstream/master' 2019-02-18 20:24:09 +01:00
Michael Krabbe Borregaard 54b6051315 bump GR version 2019-02-18 11:37:15 +01:00
Michael Krabbe BorregaardandGitHub ebea34920b Merge pull request #1919 from yha/colorbar-fixes
GR: contour colorbar fixes
2019-02-18 08:17:11 +01:00
yharel 44294306ce Using fillcolor for contour with fill=true.
Removed failed attempt at supporting single-color contours.
2019-02-18 04:50:16 +02:00
yharel c2af1a0666 Colorbar and contour fixes 2019-02-18 04:02:31 +02:00
Josef Heinen 8f30696a4d gr: added support for volume plots 2019-02-16 18:03:21 +01:00
Josef Heinen b58082a37b Merge remote-tracking branch 'upstream/master'
t push
2019-02-14 14:08:29 +01:00
Michael Krabbe BorregaardandGitHub a594878860 Merge pull request #1915 from o01eg/fix-1904
Fix bar plot for unicode plots backend
2019-02-09 13:18:05 +01:00
O01eg 3a2b6296ac Fix UndefVarError: series not defined 2019-02-09 12:38:57 +03:00
O01eg 87af609a6f Add test case for https://github.com/JuliaPlots/Plots.jl/issues/1904 2019-02-09 12:25:02 +03:00
Josef Heinen a0d5d0f3c8 Merge remote-tracking branch 'upstream/master'
t push
2019-02-08 16:33:13 +01:00
Michael Krabbe BorregaardandGitHub 53510f3268 Merge pull request #1910 from BioTurboNick/master
Fixed MethodError
2019-02-03 21:03:15 +01:00
Nicholas Bauer 9d5ce9753a Fixed MethodError 2019-02-03 14:19:32 -05:00
Josef Heinen d7a2df41fa t push
Merge remote-tracking branch 'upstream/master'
2019-01-29 08:56:04 +01:00
Michael Krabbe BorregaardandGitHub f905cb9577 Merge pull request #1829 from oschulz/faster-load
Reduce load time for Plots and GR backend
2019-01-28 14:24:23 +01:00
Oliver Schulz b9b6439f47 Clean up backend default handling 2019-01-25 17:18:44 +01:00
Oliver Schulz ffcdf986a3 Set explicit return type for function _backend_instance
Inferred return type is Any, otherwise, not AbstractBackend.
2019-01-25 17:18:44 +01:00
Oliver Schulz 43245b5eb5 Clean up backend-related global vars and related functions 2019-01-25 17:18:44 +01:00
Oliver Schulz 420228c67b Remove function add_backend
No longer in use.
2019-01-25 17:18:44 +01:00
Oliver Schulz f1719d6e91 Improve implementation of backend(pkg::AbstractBackend) 2019-01-25 17:05:43 +01:00
Oliver Schulz 9aa1fd5c00 macro init_backend can call backend() with backend instance 2019-01-25 17:05:43 +01:00
Oliver Schulz 141845aa40 _initialize_backend doesn't need to do anything for PlotlyBackend 2019-01-25 17:05:43 +01:00
Oliver Schulz 7867df6079 _initialize_backend doesn't need to do anything for GRBackend 2019-01-25 17:05:43 +01:00
Oliver Schulz 182b937143 Refactor __init__() to make Plots load faster 2019-01-25 17:05:43 +01:00
Josef Heinen 5a54fb7e9f t push
Merge remote-tracking branch 'upstream/master'
2019-01-25 14:22:27 +01:00
Josef Heinen fef45dfc30 gr: clamp rgb values 2019-01-24 20:37:33 +01:00
34 changed files with 1086 additions and 950 deletions
+1
View File
@@ -7,3 +7,4 @@ examples/meetup/.ipynb_checkpoints/*
deps/plotly-latest.min.js
deps/build.log
deps/deps.jl
Manifest.toml
+5 -45
View File
@@ -4,57 +4,17 @@ os:
- linux
# - osx
julia:
# - 1.0
- 1.1
- nightly
# matrix:
# allow_failures:
# - julia: nightly
# # before install:
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install wkhtmltopdf; fi
# ref: http://askubuntu.com/a/556672 for the wkhtmltopdf apt repository info
matrix:
allow_failures:
- julia: nightly
sudo: required
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./test/install_wkhtmltoimage.sh ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:pov/wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltopdf -V ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltoimage -V ; fi
# echo 'exec xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@"' | sudo tee /usr/local/bin/wkhtmltopdf.sh >/dev/null
# sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh
# # borrowed from Blink.jl's travis file
# matrix:
# include:
# - os: linux
# julia: 0.4
# env: TESTCMD="xvfb-run julia"
# - os: osx
# julia: 0.4
# env: TESTCMD="julia"
notifications:
email: true
# uncomment the following lines to override the default test script
# script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'import Pkg; Pkg.add(Pkg.PackageSpec(path=pwd())); Pkg.build("Plots")'
# - julia test/travis_commands.jl
# - julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("GR"); Pkg.build("GR")'
# # - julia -e 'Pkg.clone("https://github.com/tbreloff/ImageMagick.jl.git"); Pkg.checkout("ImageMagick","tb_write"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");'
# # - julia -e 'Pkg.clone("https://github.com/JunoLab/Blink.jl.git"); Pkg.build("Blink"); import Blink; Blink.AtomShell.install()'
# # - julia -e 'Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")'
# - julia -e 'ENV["PYTHON"] = ""; Pkg.add("PyPlot"); Pkg.build("PyPlot")'
#
# # - $TESTCMD -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'Pkg.test("Plots"; coverage=false)'
# # - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'
+51
View File
@@ -11,6 +11,57 @@
---
## (current master)
## 0.25.0
- Replace StaticArrays with GeometryTypes
- Contour fixes for GR
## 0.24.0
- Update to the new PyCall and PyPlot API
- fix drawing of ticks
- fix y label position with GR
## 0.23.2
- pyplot fixes
- 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
+56
View File
@@ -0,0 +1,56 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.25.0"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
FixedPointNumbers = "≥ 0.3.0"
GR = "≥ 0.31.0"
PlotThemes = "≥ 0.1.3"
PlotUtils = "≥ 0.4.1"
RecipesBase = "≥ 0.6.0"
StatsBase = "≥ 0.14.0"
julia = "≥ 1.0.0"
[extras]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
[targets]
test = ["BinaryProvider", "Pkg", "Test", "Random", "StatsPlots", "VisualRegressionTests", "LaTeXStrings", "Images", "ImageMagick", "RDatasets", "FileIO", "UnicodePlots"]
-16
View File
@@ -1,16 +0,0 @@
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
+5 -4
View File
@@ -1,10 +1,10 @@
module Plots
_current_plots_version = v"0.20.6"
_current_plots_version = v"0.25.0"
using Reexport
import StaticArrays
import GeometryTypes
using Dates, Printf, Statistics, Base64, LinearAlgebra, Random
import SparseArrays: findnz
@@ -84,7 +84,6 @@ export
backends,
backend_name,
backend_object,
add_backend,
aliases,
Shape,
@@ -180,13 +179,15 @@ include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
include("output.jl")
include("ijulia.jl")
include("fileio.jl")
include("init.jl")
include("backends/plotly.jl")
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...)
+8
View File
@@ -106,6 +106,14 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
end
# Only gifs can be shown via image/gif
Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif"
function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif)
open(fio-> write(io, fio), agif.filename)
end
# -----------------------------------------------
function _animate(forloop::Expr, args...; callgif = false)
+2
View File
@@ -63,6 +63,7 @@ const _arg_desc = KW(
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
:tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.",
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
:dpi => "Number. Dots Per Inch of output figures",
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
@@ -149,4 +150,5 @@ const _arg_desc = KW(
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`",
:widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.",
:draw_arrow => "Bool. Draw arrow at the end of the axis.",
)
+23 -14
View File
@@ -232,6 +232,7 @@ const _bar_width = 0.8
const _series_defaults = KW(
:label => "AUTO",
:colorbar_entry => true,
:seriescolor => :auto,
:seriesalpha => nothing,
:seriestype => :path,
@@ -298,6 +299,7 @@ const _plot_defaults = KW(
:link => :none,
:overwrite_figure => true,
:html_output_format => :auto,
:tex_output_standalone => false,
:inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are
# the parent layout and the relative bounding box of inset subplots
:dpi => DPI, # dots per inch for images, etc
@@ -390,6 +392,7 @@ const _axis_defaults = KW(
:minorgrid => false,
:showaxis => true,
:widen => true,
:draw_arrow => false,
)
const _suppress_warnings = Set{Symbol}([
@@ -735,6 +738,10 @@ function processMarkerArg(plotattributes::KW, arg)
elseif allAlphas(arg)
plotattributes[:markeralpha] = arg
# bool
elseif typeof(arg) <: Bool
plotattributes[:markershape] = arg ? :circle : :none
# markersize
elseif allReals(arg)
plotattributes[:markersize] = arg
@@ -1180,7 +1187,7 @@ function convertLegendValue(val::Symbol)
:best
elseif val in (:no, :none)
:none
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright)
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright, :outertopleft, :outertop, :outerright, :outerleft, :outerbottomright, :outerbottomleft, :outerbottom)
val
else
error("Invalid symbol for legend: $val")
@@ -1508,19 +1515,19 @@ function has_black_border_for_default(st::Symbol)
like_histogram(st) || st in (:hexbin, :bar, :shape)
end
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
function getSeriesRGBColor(c, sp::Subplot, n::Int)
# converts a symbol or string into a Colorant or ColorGradient
# and assigns a color automatically
function get_series_color(c, sp::Subplot, n::Int, seriestype)
if c == :auto
c = autopick(sp[:color_palette], n)
c = like_surface(seriestype) ? cgrad() : autopick(sp[:color_palette], n)
elseif isa(c, Int)
c = autopick(sp[:color_palette], c)
end
plot_color(c)
end
function getSeriesRGBColor(c::AbstractArray, sp::Subplot, n::Int)
map(x->getSeriesRGBColor(x, sp, n), c)
function get_series_color(c::AbstractArray, sp::Subplot, n::Int, seriestype)
map(x->get_series_color(x, sp, n, seriestype), c)
end
function ensure_gradient!(plotattributes::KW, csym::Symbol, asym::Symbol)
@@ -1565,21 +1572,23 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
end
# update series color
plotattributes[:seriescolor] = getSeriesRGBColor(plotattributes[:seriescolor], sp, plotIndex)
scolor = plotattributes[:seriescolor]
stype = plotattributes[:seriestype]
plotattributes[:seriescolor] = scolor = get_series_color(scolor, sp, plotIndex, stype)
# update other colors
for s in (:line, :marker, :fill)
csym, asym = Symbol(s,:color), Symbol(s,:alpha)
plotattributes[csym] = if plotattributes[csym] == :auto
plot_color(if has_black_border_for_default(plotattributes[:seriestype]) && s == :line
plot_color(if has_black_border_for_default(stype) && s == :line
sp[:foreground_color_subplot]
else
plotattributes[:seriescolor]
scolor
end)
elseif plotattributes[csym] == :match
plot_color(plotattributes[:seriescolor])
plot_color(scolor)
else
getSeriesRGBColor(plotattributes[csym], sp, plotIndex)
get_series_color(plotattributes[csym], sp, plotIndex, stype)
end
end
@@ -1587,9 +1596,9 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
plotattributes[:markerstrokecolor] = if plotattributes[:markerstrokecolor] == :match
plot_color(sp[:foreground_color_subplot])
elseif plotattributes[:markerstrokecolor] == :auto
getSeriesRGBColor(plotattributes[:markercolor], sp, plotIndex)
get_series_color(plotattributes[:markercolor], sp, plotIndex, stype)
else
getSeriesRGBColor(plotattributes[:markerstrokecolor], sp, plotIndex)
get_series_color(plotattributes[:markerstrokecolor], sp, plotIndex, stype)
end
# if marker_z, fill_z or line_z are set, ensure we have a gradient
+11 -11
View File
@@ -117,7 +117,7 @@ end
# -------------------------------------------------------------------------
Base.show(io::IO, axis::Axis) = dumpdict(axis.plotattributes, "Axis", true)
Base.show(io::IO, axis::Axis) = dumpdict(io, axis.plotattributes, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.plotattributes, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.plotattributes, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k)
@@ -240,7 +240,7 @@ end
# return (continuous_values, discrete_values) for the ticks on this axis
function get_ticks(axis::Axis)
ticks = _transform_ticks(axis[:ticks])
ticks in (nothing, false) && return nothing
ticks in (:none, nothing, false) && return nothing
# treat :native ticks as :auto
ticks = ticks == :native ? :auto : ticks
@@ -251,7 +251,7 @@ function get_ticks(axis::Axis)
# discrete ticks...
n = length(dvals)
rng = if ticks == :auto
Int[round(Int,i) for i in range(1, stop=n, length=15)]
Int[round(Int,i) for i in range(1, stop=n, length=min(n,15))]
else # if ticks == :all
1:n
end
@@ -287,7 +287,7 @@ _transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.valu
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2])
function get_minor_ticks(axis,ticks)
axis[:minorticks] in (nothing, false) && !axis[:minorgrid] && return nothing
axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing
ticks = ticks[1]
length(ticks) < 2 && return nothing
@@ -502,7 +502,7 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis)
amin, amax = 0, 2pi
elseif lims == :auto
#widen max radius so ticks dont overlap with theta axis
amin, amax + 0.1 * abs(amax - amin)
0, amax + 0.1 * abs(amax - amin)
else
amin, amax
end
@@ -614,14 +614,14 @@ function axis_drawing_info(sp::Subplot)
end
push!(xaxis_segs, (xmin, y1), (xmax, y1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (nothing,false)) && length(xticks) > 1
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
showticks = xticks[1] .!= 0
xticks = (xticks[1][showticks], xticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine
end
if !(xaxis[:ticks] in (nothing, false))
if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
@@ -642,7 +642,7 @@ function axis_drawing_info(sp::Subplot)
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
end
if !(xaxis[:minorticks] in (nothing, false)) || xaxis[:minorgrid]
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
@@ -675,14 +675,14 @@ function axis_drawing_info(sp::Subplot)
end
push!(yaxis_segs, (x1, ymin), (x1, ymax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (nothing,false)) && length(yticks) > 1
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
showticks = yticks[1] .!= 0
yticks = (yticks[1][showticks], yticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine
end
if !(yaxis[:ticks] in (nothing, false))
if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
@@ -703,7 +703,7 @@ function axis_drawing_info(sp::Subplot)
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
if !(yaxis[:minorticks] in (nothing, false)) || yaxis[:minorgrid]
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
+40 -102
View File
@@ -7,16 +7,20 @@ const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
const _backends = Symbol[]
const _initialized_backends = Set{Symbol}()
const _default_backends = (:none, :gr, :plotly)
const _backendPackage = Dict{Symbol, Symbol}()
const _backend_packages = Dict{Symbol, Symbol}()
"Returns a list of supported backends"
backends() = _backends
"Returns the name of the current backend"
backend_name() = CURRENT_BACKEND.sym
_backend_instance(sym::Symbol) = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
backend_package(pkg::Symbol) = pkg in _default_backends ? :Plots : Symbol("Plots", _backendPackage[pkg])
backend_package_name(sym::Symbol) = sym in _default_backends ? :Plots : _backendPackage[sym]
function _backend_instance(sym::Symbol)::AbstractBackend
haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
end
backend_package_name(sym::Symbol) = _backend_packages[sym]
macro init_backend(s)
package_str = string(s)
@@ -26,13 +30,13 @@ macro init_backend(s)
esc(quote
struct $T <: AbstractBackend end
export $sym
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
$sym(; kw...) = (default(; kw...); backend($T()))
backend_name(::$T) = Symbol($str)
backend_package_name(pkg::$T) = backend_package_name(Symbol($str))
push!(_backends, Symbol($str))
_backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str)
_backendPackage[Symbol($str)] = Symbol($package_str)
_backend_packages[Symbol($str)] = Symbol($package_str)
# include("backends/" * $str * ".jl")
end)
end
@@ -42,12 +46,6 @@ end
# ---------------------------------------------------------
function add_backend(pkg::Symbol)
@info("To do a standard install of $pkg, copy and run this:\n\n")
println(add_backend_string(_backend_instance(pkg)))
println()
end
# don't do anything as a default
_create_backend_figure(plt::Plot) = nothing
_prepare_plot_object(plt::Plot) = nothing
@@ -138,33 +136,27 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, _backend_instance(sym))
# ---------------------------------------------------------
function pickDefaultBackend()
_fallback_default_backend() = backend(GRBackend())
function _pick_default_backend()
env_default = get(ENV, "PLOTS_DEFAULT_BACKEND", "")
if env_default != ""
sym = Symbol(lowercase(env_default))
if sym in _backends
if sym in _initialized_backends
return backend(sym)
backend(sym)
else
@warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.")
_fallback_default_backend()
end
else
@warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" *
join(sort(_backends), "\n\t"))
_fallback_default_backend()
end
else
_fallback_default_backend()
end
# the ordering/inclusion of this package list is my semi-arbitrary guess at
# which one someone will want to use if they have the package installed...accounting for
# features, speed, and robustness
# for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR")
# if pkgstr in keys(Pkg.installed())
# return backend(Symbol(lowercase(pkgstr)))
# end
# end
# the default if nothing else is installed
backend(:gr)
end
@@ -174,13 +166,11 @@ end
Returns the current plotting package name. Initializes package on first call.
"""
function backend()
if CURRENT_BACKEND.sym == :none
_pick_default_backend()
end
global CURRENT_BACKEND
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
end
CURRENT_BACKEND.pkg
CURRENT_BACKEND.pkg
end
"""
@@ -188,20 +178,13 @@ Set the plot backend.
"""
function backend(pkg::AbstractBackend)
sym = backend_name(pkg)
if sym in _initialized_backends
CURRENT_BACKEND.sym = backend_name(pkg)
CURRENT_BACKEND.pkg = pkg
else
# try
_initialize_backend(pkg)
push!(_initialized_backends, sym)
CURRENT_BACKEND.sym = backend_name(pkg)
CURRENT_BACKEND.pkg = pkg
# catch
# add_backend(sym)
# end
if !(sym in _initialized_backends)
_initialize_backend(pkg)
push!(_initialized_backends, sym)
end
backend()
CURRENT_BACKEND.sym = sym
CURRENT_BACKEND.pkg = pkg
pkg
end
function backend(sym::Symbol)
@@ -209,8 +192,8 @@ function backend(sym::Symbol)
backend(_backend_instance(sym))
else
@warn("`:$sym` is not a supported backend.")
backend()
end
backend()
end
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize]
@@ -316,13 +299,10 @@ function _initialize_backend(pkg::AbstractBackend)
end
end
function add_backend_string(pkg::AbstractBackend)
sym = backend_package_name(pkg)
"""
using Pkg
Pkg.add("$sym")
"""
end
_initialize_backend(pkg::GRBackend) = nothing
_initialize_backend(pkg::PlotlyBackend) = nothing
# ------------------------------------------------------------------------------
# gr
@@ -352,7 +332,7 @@ const _gr_attr = merge_with_base_supported([
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
:guidefontrotation, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar, :colorbar_title,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:fill_z, :line_z, :marker_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -371,7 +351,7 @@ const _gr_attr = merge_with_base_supported([
const _gr_seriestype = [
:path, :scatter, :straightline,
:heatmap, :pie, :image,
:contour, :path3d, :scatter3d, :surface, :wireframe,
:contour, :path3d, :scatter3d, :surface, :wireframe, :volume,
:shape
]
const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
@@ -379,13 +359,6 @@ const _gr_marker = _allMarkers
const _gr_scale = [:identity, :log10]
is_marker_supported(::GRBackend, shape::Shape) = true
function add_backend_string(::GRBackend)
"""
Pkg.add("GR")
Pkg.build("GR")
"""
end
# ------------------------------------------------------------------------------
# plotly
@@ -413,7 +386,7 @@ const _plotly_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridlinewidth,
:legend, :colorbar, :colorbar_title,
:legend, :colorbar, :colorbar_title, :colorbar_entry,
:marker_z, :fill_z, :line_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -444,17 +417,11 @@ const _plotly_marker = [
]
const _plotly_scale = [:identity, :log10]
defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html"
# ------------------------------------------------------------------------------
# pgfplots
function add_backend_string(::PGFPlotsBackend)
"""
using Pkg
Pkg.add("PGFPlots")
Pkg.build("PGFPlots")
"""
end
const _pgfplots_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
@@ -492,29 +459,19 @@ const _pgfplots_attr = merge_with_base_supported([
])
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline] #vcat(_allMarkers, Shape)
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
# ------------------------------------------------------------------------------
# plotlyjs
function _initialize_backend(pkg::PlotlyJSBackend)
sym = backend_package_name(pkg)
@eval Main begin
import PlotlyJS, ORCA
export PlotlyJS
end
end
function add_backend_string(::PlotlyJSBackend)
"""
using Pkg
Pkg.add(["PlotlyJS", "Blink", "ORCA"])
import Blink
Blink.AtomShell.install()
"""
end
const _plotlyjs_attr = _plotly_attr
const _plotlyjs_seriestype = _plotly_seriestype
const _plotlyjs_style = _plotly_style
@@ -535,16 +492,6 @@ function _initialize_backend(::PyPlotBackend)
end
end
function add_backend_string(::PyPlotBackend)
"""
using Pkg
withenv("PYTHON" => "") do
Pkg.add("PyPlot")
Pkg.build("PyPlot")
end
"""
end
const _pyplot_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
@@ -564,7 +511,7 @@ const _pyplot_attr = merge_with_base_supported([
:tickfontfamily, :tickfontsize, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
@@ -577,7 +524,6 @@ const _pyplot_attr = merge_with_base_supported([
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
:stride,
:framestyle,
:tick_direction,
@@ -598,14 +544,6 @@ const _pyplot_scale = [:identity, :ln, :log2, :log10]
# ------------------------------------------------------------------------------
# unicodeplots
function add_backend_string(::UnicodePlotsBackend)
"""
using Pkg
Pkg.add("UnicodePlots")
Pkg.build("UnicodePlots")
"""
end
const _unicodeplots_attr = merge_with_base_supported([
:label,
:legend,
+381 -174
View File
@@ -6,6 +6,7 @@
import GR
export GR
# --------------------------------------------------------------------------------------
const gr_linetype = KW(
@@ -78,7 +79,10 @@ gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(_cycle(c,1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1)))
gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1))
function gr_set_transparency(::Nothing) end
gr_set_transparency(::Nothing) = GR.settransparency(1)
gr_set_transparency(c, α) = gr_set_transparency(α)
gr_set_transparency(c::Colorant, ::Nothing) = gr_set_transparency(c)
gr_set_transparency(c::Colorant) = GR.settransparency(alpha(c))
# --------------------------------------------------------------------------------------
@@ -166,7 +170,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw angular grid
if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:gridalpha])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
for i in 1:length(α)
GR.polyline([sinf[i], 0], [cosf[i], 0])
end
@@ -175,7 +179,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
#draw radial grid
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:gridalpha])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
for i in 1:length(rtick_values)
r = (rtick_values[i] - rmin) / (rmax - rmin)
if r <= 1.0 && r >= 0.0
@@ -235,6 +239,7 @@ end
function gr_fill_viewport(vp::AVec{Float64}, c)
GR.savestate()
GR.selntran(0)
GR.setscale(0)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
gr_set_fillcolor(c)
GR.fillrect(vp...)
@@ -294,15 +299,17 @@ function gr_draw_markers(series::Series, x, y, clims, msize = series[:markersize
# draw a filled in shape, slightly bigger, to estimate a stroke
if series[:markerstrokewidth] > 0
cfunc(get_markerstrokecolor(series, i))
gr_set_transparency(get_markerstrokealpha(series, i))
c = get_markerstrokecolor(series, i)
cfunc(c)
gr_set_transparency(c, get_markerstrokealpha(series, i))
gr_draw_marker(x[i], y[i], msi + series[:markerstrokewidth], shape)
end
# draw the shape - don't draw filled area if marker shape is 1D
if !(shape in (:hline, :vline, :+, :x))
cfunc(get_markercolor(series, clims, i))
gr_set_transparency(get_markeralpha(series, i))
c = get_markercolor(series, clims, i)
cfunc(c)
gr_set_transparency(c, get_markeralpha(series, i))
gr_draw_marker(x[i], y[i], msi, shape)
end
end
@@ -413,17 +420,100 @@ function gr_set_viewport_polar()
r
end
struct GRColorbar
gradient::Ref{Union{Series,Nothing}}
fill::Ref{Union{Series,Nothing}}
lines::Ref{Union{Series,Nothing}}
GRColorbar() = new(nothing,nothing,nothing)
end
function gr_update_colorbar!(cbar::GRColorbar, series::Series)
style = colorbar_style(series)
style === nothing && return
ref = style == cbar_gradient ? cbar.gradient :
style == cbar_fill ? cbar.fill :
style == cbar_lines ? cbar.lines :
error("Unknown colorbar style: $style.")
if ref[] !== nothing
@warn "Overwriting colorbar entry"
end
ref[] = series
end
function gr_contour_levels(series::Series, clims)
levels = contour_levels(series, clims)
if isfilledcontour(series)
# GR implicitly uses the maximal z value as the highest level
levels = levels[1:end-1]
end
levels
end
function gr_colorbar_colors(series::Series, clims)
if iscontour(series)
levels = gr_contour_levels(series, clims)
if isfilledcontour(series)
# GR.contourf uses a color range according to supplied levels
zrange = ignorenan_extrema(levels)
else
# GR.contour uses a color range according to data range
zrange = clims
end
colors = 1000 .+ 255 .* (levels .- zrange[1]) ./ (zrange[2] - zrange[1])
else
colors = 1000:1255
end
round.(Int,colors)
end
# add the colorbar
function gr_colorbar(sp::Subplot, clims)
function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
GR.savestate()
xmin, xmax = gr_xy_axislims(sp)[1:2]
zmin, zmax = clims[1:2]
gr_set_viewport_cmap(sp)
l = zeros(Int32, 1, 256)
l[1,:] = Int[round(Int, _i) for _i in range(1000, stop=1255, length=256)]
GR.setscale(0)
GR.setwindow(xmin, xmax, clims[1], clims[2])
GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l)
ztick = 0.5 * GR.tick(clims[1], clims[2])
GR.axes(0, ztick, xmax, clims[1], 0, 1, 0.005)
GR.setwindow(xmin, xmax, zmin, zmax)
if (series = cbar.gradient[]) !== nothing
gr_set_gradient(series)
gr_set_transparency(get_fillalpha(series))
GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255)
end
if (series = cbar.fill[]) !== nothing
gr_set_gradient(series)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
levels = contour_levels(series, clims)
# GR implicitly uses the maximal z value as the highest level
if levels[end] < clims[2]
@warn("GR: highest contour level less than maximal z value is not supported.")
# replace levels, rather than assign to levels[end], to ensure type
# promotion in case levels is an integer array
levels = [levels[1:end-1]; clims[2]]
end
colors = gr_colorbar_colors(series, clims)
for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors)
GR.setfillcolorind(color)
gr_set_transparency(get_fillalpha(series))
GR.fillrect( xmin, xmax, from, to )
end
end
if (series = cbar.lines[]) !== nothing
gr_set_gradient(series)
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims))
gr_set_transparency(get_linealpha(series))
levels = contour_levels(series, clims)
colors = gr_colorbar_colors(series, clims)
for (line, color) in zip(levels, colors)
GR.setlinecolorind(color)
GR.polyline([xmin,xmax], [line,line] )
end
end
ztick = 0.5 * GR.tick(zmin, zmax)
gr_set_line(1, :solid, plot_color(:black))
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
gr_set_font(guidefont(sp[:yaxis]))
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
@@ -431,28 +521,52 @@ function gr_colorbar(sp::Subplot, clims)
gr_text(viewport_plotarea[2] + gr_colorbar_ratio,
gr_view_ycenter(), sp[:colorbar_title])
gr_set_viewport_plotarea()
GR.restorestate()
end
gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2])
gr_view_ycenter() = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4])
function gr_legend_pos(s::Symbol,w,h)
function gr_legend_pos(sp::Subplot, w, h)
s = sp[:legend]
typeof(s) <: Symbol || return gr_legend_pos(s, w, h)
str = string(s)
if str == "best"
str = "topright"
end
if occursin("outer", str)
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
xmirror = xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
ymirror = yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
end
if occursin("right", str)
xpos = viewport_plotarea[2] - 0.05 - w
if occursin("outer", str)
# As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525
xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_yaxis_width(sp)
else
xpos = viewport_plotarea[2] - 0.05 - w
end
elseif occursin("left", str)
xpos = viewport_plotarea[1] + 0.11
if occursin("outer", str)
xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_yaxis_width(sp)
else
xpos = viewport_plotarea[1] + 0.11
end
else
xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 - w/2 +.04
end
if occursin("top", str)
ypos = viewport_plotarea[4] - 0.06
if s == :outertop
ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_xaxis_height(sp)
else
ypos = viewport_plotarea[4] - 0.06
end
elseif occursin("bottom", str)
ypos = viewport_plotarea[3] + h + 0.06
if s == :outerbottom
ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_xaxis_height(sp)
else
ypos = viewport_plotarea[3] + h + 0.06
end
else
ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + h/2
end
@@ -470,7 +584,7 @@ end
const _gr_gradient_alpha = ones(256)
function gr_set_gradient(c)
grad = isa(c, ColorGradient) ? c : cgrad()
grad = _as_gradient(c)
for (i,z) in enumerate(range(0, stop=1, length=256))
c = grad[z]
GR.setcolorrep(999+i, red(c), green(c), blue(c))
@@ -479,6 +593,21 @@ function gr_set_gradient(c)
grad
end
function gr_set_gradient(series::Series)
st = series[:seriestype]
if st in (:surface, :heatmap) || isfilledcontour(series)
gr_set_gradient(series[:fillcolor])
elseif st in (:contour, :wireframe)
gr_set_gradient(series[:linecolor])
elseif series[:marker_z] != nothing
gr_set_gradient(series[:markercolor])
elseif series[:line_z] != nothing
gr_set_gradient(series[:linecolor])
elseif series[:fill_z] != nothing
gr_set_gradient(series[:fillcolor])
end
end
# this is our new display func... set up the viewport_canvas, compute bounding boxes, and display each subplot
function gr_display(plt::Plot, fmt="")
GR.clearws()
@@ -551,17 +680,65 @@ function gr_set_yticks_font(sp)
return flip, mirror
end
function gr_get_ticks_size(ticks, i)
function gr_text_size(str)
GR.savestate()
GR.selntran(0)
l = 0.0
for (cv, dv) in zip(ticks...)
tb = gr_inqtext(0, 0, string(dv))[i]
tb_min, tb_max = extrema(tb)
l = max(l, tb_max - tb_min)
end
xs, ys = gr_inqtext(0, 0, string(str))
l, r = extrema(xs)
b, t = extrema(ys)
w = r - l
h = t - b
GR.restorestate()
return l
return w, h
end
function gr_text_size(str, rot)
GR.savestate()
GR.selntran(0)
xs, ys = gr_inqtext(0, 0, string(str))
l, r = extrema(xs)
b, t = extrema(ys)
w = text_box_width(r - l, t - b, rot)
h = text_box_height(r - l, t - b, rot)
GR.restorestate()
return w, h
end
text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h
text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h
function gr_get_ticks_size(ticks, rot)
w, h = 0.0, 0.0
for (cv, dv) in zip(ticks...)
wi, hi = gr_text_size(dv, rot)
w = max(w, wi)
h = max(h, hi)
end
return w, h
end
function gr_xaxis_height(sp)
xaxis = sp[:xaxis]
xticks, yticks = axis_drawing_info(sp)[1:2]
gr_set_font(tickfont(xaxis))
h = (xticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(xticks, xaxis[:rotation])))
if xaxis[:guide] != ""
gr_set_font(guidefont(xaxis))
h += last(gr_text_size(xaxis[:guide]))
end
return h
end
function gr_yaxis_width(sp)
yaxis = sp[:yaxis]
xticks, yticks = axis_drawing_info(sp)[1:2]
gr_set_font(tickfont(yaxis))
w = (xticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(yticks, yaxis[:rotation])))
if yaxis[:guide] != ""
gr_set_font(guidefont(yaxis))
w += last(gr_text_size(yaxis[:guide]))
end
return w
end
function _update_min_padding!(sp::Subplot{GRBackend})
@@ -572,48 +749,59 @@ function _update_min_padding!(sp::Subplot{GRBackend})
end
end
# Add margin given by the user
leftpad = 4mm + sp[:left_margin]
leftpad = 2mm + sp[:left_margin]
toppad = 2mm + sp[:top_margin]
rightpad = 4mm + sp[:right_margin]
rightpad = 2mm + sp[:right_margin]
bottompad = 2mm + sp[:bottom_margin]
# Add margin for title
if sp[:title] != ""
toppad += 5mm
gr_set_font(titlefont(sp))
l = last(last(gr_text_size(sp[:title])))
h = 1mm + gr_plot_size[2] * l * px
toppad += h
end
# Add margin for x and y ticks
xticks, yticks = axis_drawing_info(sp)[1:2]
if !(xticks in (nothing, false, :none))
flip, mirror = gr_set_xticks_font(sp)
l = gr_get_ticks_size(xticks, 2)
l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
h = 1mm + gr_plot_size[2] * l * px
if mirror
toppad += 1mm + gr_plot_size[2] * l * px
toppad += h
else
bottompad += 1mm + gr_plot_size[2] * l * px
bottompad += h
end
end
if !(yticks in (nothing, false, :none))
flip, mirror = gr_set_yticks_font(sp)
l = gr_get_ticks_size(yticks, 1)
l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
w = 1mm + gr_plot_size[1] * l * px
if mirror
rightpad += 1mm + gr_plot_size[1] * l * px
rightpad += w
else
leftpad += 1mm + gr_plot_size[1] * l * px
leftpad += w
end
end
# Add margin for x label
if sp[:xaxis][:guide] != ""
gr_set_font(guidefont(sp[:xaxis]))
l = last(gr_text_size(sp[:xaxis][:guide]))
h = 1mm + gr_plot_size[2] * l * px
if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true)
toppad += 4mm
toppad += h
else
bottompad += 4mm
bottompad += h
end
end
# Add margin for y label
if sp[:yaxis][:guide] != ""
gr_set_font(guidefont(sp[:yaxis]))
l = last(gr_text_size(sp[:yaxis][:guide]))
w = 1mm + gr_plot_size[2] * l * px
if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true)
rightpad += 4mm
rightpad += w
else
leftpad += 4mm
leftpad += w
end
end
if sp[:colorbar_title] != ""
@@ -652,6 +840,54 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
end
# calculate legend size
# has to be done now due to a potential adjustment to the plotarea given an outer legend.
legendn = 0
legendw = 0
legendi = 0
if sp[:legend] != :none
GR.savestate()
GR.selntran(0)
GR.setscale(0)
gr_set_font(legendfont(sp))
if sp[:legendtitle] != nothing
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
legendw = tbx[3] - tbx[1]
legendn += 1
end
for series in series_list(sp)
should_add_to_legend(series) || continue
legendn += 1
if typeof(series[:label]) <: Array
legendi += 1
lab = series[:label][i]
else
lab = series[:label]
end
tbx, tby = gr_inqtext(0, 0, string(lab))
legendw = max(legendw, tbx[3] - tbx[1])
end
GR.setscale(1)
GR.selntran(1)
GR.restorestate()
end
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
legendh = dy * legendn
leg_str = string(sp[:legend])
if occursin("outer", leg_str)
if occursin("right", leg_str)
viewport_plotarea[2] -= legendw + 0.11
elseif occursin("left", leg_str)
viewport_plotarea[1] += legendw + 0.11
elseif occursin("top", leg_str)
viewport_plotarea[4] -= legendh + 0.03
elseif occursin("bottom", leg_str)
viewport_plotarea[3] += legendh + 0.04
end
end
# fill in the plot area background
bg = plot_color(sp[:background_color_inside])
gr_fill_viewport(viewport_plotarea, bg)
@@ -659,7 +895,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# reduced from before... set some flags based on the series in this subplot
# TODO: can these be generic flags?
outside_ticks = false
cmap = hascolorbar(sp)
# calculate the colorbar limits once for a subplot
clims = get_clims(sp)
cbar = GRColorbar()
draw_axes = sp[:framestyle] != :none
# axes_2d = true
for series in series_list(sp)
@@ -681,6 +920,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
expand_extrema!(sp[:yaxis], y)
data_lims = gr_xy_axislims(sp)
end
gr_update_colorbar!(cbar,series)
end
# set our plot area view
@@ -729,11 +970,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setlinewidth(sp.plt[:thickness_scaling])
if is3d(sp)
# TODO do we really need a different clims computation here from the one
# computed above using get_clims(sp)?
zmin, zmax = gr_lims(zaxis, true)
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
clims3d = sp[:clims]
if is_2tuple(clims3d)
isfinite(clims3d[1]) && (zmin = clims3d[1])
isfinite(clims3d[2]) && (zmax = clims3d[2])
end
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...)
xtick = GR.tick(xmin, xmax) / 2
@@ -743,21 +986,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:gridalpha])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0)
end
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:gridalpha])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0)
end
if zaxis[:grid]
gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid])
gr_set_transparency(zaxis[:gridalpha])
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha])
GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2)
end
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
gr_set_transparency(1)
gr_set_transparency(xaxis[:foreground_color_axis])
GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize)
GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize)
@@ -780,24 +1023,24 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# gr_set_linecolor(sp[:foreground_color_grid])
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:gridalpha])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
gr_polyline(coords(xgrid_segs)...)
end
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:gridalpha])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
gr_polyline(coords(ygrid_segs)...)
end
if xaxis[:minorgrid]
# gr_set_linecolor(sp[:foreground_color_grid])
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid])
gr_set_transparency(xaxis[:minorgridalpha])
gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha])
gr_polyline(coords(xminorgrid_segs)...)
end
if yaxis[:minorgrid]
gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid])
gr_set_transparency(yaxis[:minorgridalpha])
gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha])
gr_polyline(coords(yminorgrid_segs)...)
end
gr_set_transparency(1.0)
@@ -819,7 +1062,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if xaxis[:showaxis]
if sp[:framestyle] in (:zerolines, :grid)
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:gridalpha])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0)
else
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
end
@@ -829,7 +1072,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if yaxis[:showaxis]
if sp[:framestyle] in (:zerolines, :grid)
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:gridalpha])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0)
else
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
end
@@ -881,10 +1124,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
intensity = sp[:framestyle] == :semi ? 0.5 : 1.0
if sp[:framestyle] in (:box, :semi)
gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
gr_set_transparency(intensity)
gr_set_transparency(xaxis[:foreground_color_border], intensity)
gr_polyline(coords(xborder_segs)...)
gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
gr_set_transparency(intensity)
gr_set_transparency(yaxis[:foreground_color_border], intensity)
gr_polyline(coords(yborder_segs)...)
end
end
@@ -908,27 +1151,34 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
gr_text(xpos, viewport_subplot[4], sp[:title])
end
if xaxis[:guide] != ""
if is3d(sp)
gr_set_font(guidefont(xaxis))
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
else
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide])
else
xticks, yticks = axis_drawing_info(sp)[1:2]
if xaxis[:guide] != ""
h = 0.01 + gr_xaxis_height(sp)
gr_set_font(guidefont(xaxis))
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
gr_text(gr_view_xcenter(), viewport_plotarea[4] + h, xaxis[:guide])
else
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(gr_view_xcenter(), viewport_plotarea[3] - h, xaxis[:guide])
end
end
end
if yaxis[:guide] != ""
gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
else
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
if yaxis[:guide] != ""
w = 0.02 + gr_yaxis_width(sp)
gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(viewport_plotarea[2] + w, gr_view_ycenter(), yaxis[:guide])
else
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
gr_text(viewport_plotarea[1] - w, gr_view_ycenter(), yaxis[:guide])
end
end
end
GR.restorestate()
@@ -938,26 +1188,14 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# this needs to be here to point the colormap to the right indices
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
# calculate the colorbar limits once for a subplot
clims = get_clims(sp)
for (idx, series) in enumerate(series_list(sp))
st = series[:seriestype]
# update the current stored gradient
if st in (:contour, :surface, :wireframe, :heatmap)
gr_set_gradient(series[:fillcolor]) #, series[:fillalpha])
elseif series[:marker_z] != nothing
series[:markercolor] = gr_set_gradient(series[:markercolor])
elseif series[:line_z] != nothing
series[:linecolor] = gr_set_gradient(series[:linecolor])
elseif series[:fill_z] != nothing
series[:fillcolor] = gr_set_gradient(series[:fillcolor])
end
gr_set_gradient(series)
GR.savestate()
# update the bounding window
if ispolar(sp)
gr_set_viewport_polar()
@@ -990,7 +1228,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if st in (:path, :scatter, :straightline)
if length(x) > 1
if x != nothing && length(x) > 1
lz = series[:line_z]
segments = iter_segments(series)
# do area fill
@@ -998,10 +1236,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i, rng) in enumerate(segments)
gr_set_fillcolor(get_fillcolor(series, clims, i))
fc = get_fillcolor(series, clims, i)
gr_set_fillcolor(fc)
fx = _cycle(x, vcat(rng, reverse(rng)))
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
gr_set_transparency(get_fillalpha(series, i))
gr_set_transparency(fc, get_fillalpha(series, i))
GR.fillarea(fx, fy)
end
end
@@ -1009,8 +1248,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# draw the line(s)
if st in (:path, :straightline)
for (i, rng) in enumerate(segments)
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha])
gr_set_transparency(get_linealpha(series, i))
lc = get_linecolor(series, clims, i)
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha])
gr_set_transparency(lc, get_linealpha(series, i))
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
gr_polyline(x[rng], y[rng]; arrowside = arrowside)
end
@@ -1022,34 +1262,23 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
elseif st == :contour
zmin, zmax = clims
GR.setspace(zmin, zmax, 0, 90)
if typeof(series[:levels]) <: AbstractArray
h = series[:levels]
else
h = series[:levels] > 1 ? range(zmin, stop=zmax, length=series[:levels]) : [(zmin + zmax) / 2]
end
GR.setspace(clims[1], clims[2], 0, 90)
GR.setlinetype(gr_linetype[get_linestyle(series)])
GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001)))
is_lc_black = let black=plot_color(:black)
plot_color(series[:linecolor]) in (black,[black])
end
h = gr_contour_levels(series, clims)
if series[:fillrange] != nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines")
end
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
else
coff = plot_color(series[:linecolor]) == [plot_color(:black)] ? 0 : 1000
coff = is_lc_black ? 0 : 1000
GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0))
end
# create the colorbar of contour levels
if cmap
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
gr_set_viewport_cmap(sp)
l = (length(h) > 1) ? round.(Int32, 1000 .+ (h .- ignorenan_minimum(h)) ./ (ignorenan_maximum(h) - ignorenan_minimum(h)) .* 255) : Int32[1000, 1255]
GR.setwindow(xmin, xmax, zmin, zmax)
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
ztick = 0.5 * GR.tick(zmin, zmax)
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
gr_set_viewport_plotarea()
end
elseif st in [:surface, :wireframe]
if st == :surface
if length(x) == length(y) == length(z)
@@ -1066,6 +1295,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
end
elseif st == :volume
sp[:legend] = :none
GR.gr3.clear()
dmin, dmax = GR.gr3.volume(y.v, 0)
elseif st == :heatmap
xmin, xmax, ymin, ymax = xy_lims
zmin, zmax = clims
@@ -1090,8 +1324,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
lz = series[:line_z]
segments = iter_segments(series)
for (i, rng) in enumerate(segments)
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha])
gr_set_transparency(get_linealpha(series, i))
lc = get_linecolor(series, clims, i)
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha])
gr_set_transparency(lc, get_linealpha(series, i))
GR.polyline3d(x[rng], y[rng], z[rng])
end
end
@@ -1162,13 +1397,15 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
xseg, yseg = x[rng], y[rng]
# draw the interior
gr_set_fill(get_fillcolor(series, clims, i))
gr_set_transparency(get_fillalpha(series, i))
fc = get_fillcolor(series, clims, i)
gr_set_fill(fc)
gr_set_transparency(fc, get_fillalpha(series, i))
GR.fillarea(xseg, yseg)
# draw the shapes
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i))
gr_set_transparency(get_linealpha(series, i))
lc = get_linecolor(series, clims, i)
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc)
gr_set_transparency(lc, get_linealpha(series, i))
GR.polyline(xseg, yseg)
end
end
@@ -1176,19 +1413,19 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :image
z = transpose_z(series, series[:z].surf, true)'
w, h = length(x), length(y)
w, h = size(z)
xinds = sort(1:w, rev = xaxis[:flip])
yinds = sort(1:h, rev = yaxis[:flip])
z = z[xinds, yinds]
xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
if eltype(z) <: Colors.AbstractGray
grey = round.(UInt8, float(z) * 255)
grey = round.(UInt8, clamp.(float(z) * 255, 0, 255))
rgba = map(c -> UInt32( 0xff000000 + UInt(c)<<16 + UInt(c)<<8 + UInt(c) ), grey)
else
rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 +
round(UInt, blue(c) * 255) << 16 +
round(UInt, green(c) * 255) << 8 +
round(UInt, red(c) * 255) ), z)
rgba = map(c -> UInt32( round(UInt, clamp(alpha(c) * 255, 0, 255)) << 24 +
round(UInt, clamp(blue(c) * 255, 0, 255)) << 16 +
round(UInt, clamp(green(c) * 255, 0, 255)) << 8 +
round(UInt, clamp(red(c) * 255, 0, 255)) ), z)
end
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
end
@@ -1204,14 +1441,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
# draw the colorbar
GR.savestate()
# special colorbar with steps is drawn for contours
if cmap && any(series[:seriestype] != :contour for series in series_list(sp))
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
gr_set_transparency(1)
gr_colorbar(sp, clims)
end
GR.restorestate()
hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims)
# add the legend
if sp[:legend] != :none
@@ -1219,30 +1449,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.selntran(0)
GR.setscale(0)
gr_set_font(legendfont(sp))
w = 0
i = 0
n = 0
if sp[:legendtitle] != nothing
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
w = tbx[3] - tbx[1]
n += 1
end
for series in series_list(sp)
should_add_to_legend(series) || continue
n += 1
if typeof(series[:label]) <: Array
i += 1
lab = series[:label][i]
else
lab = series[:label]
end
tbx, tby = gr_inqtext(0, 0, string(lab))
w = max(w, tbx[3] - tbx[1])
end
w = legendw
i = legendi
n = legendn
if w > 0
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
h = dy*n
(xpos,ypos) = gr_legend_pos(sp[:legend],w,h)
xpos, ypos = gr_legend_pos(sp, w, h)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
gr_set_fillcolor(sp[:background_color_legend])
GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
@@ -1252,30 +1465,33 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if sp[:legendtitle] != nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(sp[:legendfontcolor])
gr_set_transparency(1)
gr_set_transparency(sp[:legendfontcolor])
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy
end
for series in series_list(sp)
should_add_to_legend(series) || continue
st = series[:seriestype]
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) #, series[:linealpha])
lc = get_linecolor(series, clims)
gr_set_line(get_linewidth(series), get_linestyle(series), lc) #, series[:linealpha])
if (st == :shape || series[:fillrange] != nothing) && series[:ribbon] == nothing
gr_set_fill(get_fillcolor(series, clims)) #, series[:fillalpha])
fc = get_fillcolor(series, clims)
gr_set_fill(fc) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01
b, t = ypos-0.4dy, ypos+0.4dy
x = [l, r, r, l, l]
y = [b, b, t, t, b]
gr_set_transparency(get_fillalpha(series))
gr_set_transparency(fc, get_fillalpha(series))
gr_polyline(x, y, GR.fillarea)
gr_set_transparency(get_linealpha(series))
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims))
lc = get_linecolor(series, clims)
gr_set_transparency(lc, get_linealpha(series))
gr_set_line(get_linewidth(series), get_linestyle(series), lc)
st == :shape && gr_polyline(x, y)
end
if st in (:path, :straightline)
gr_set_transparency(get_linealpha(series))
gr_set_transparency(lc, get_linealpha(series))
if series[:fillrange] == nothing || series[:ribbon] != nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
else
@@ -1337,16 +1553,7 @@ const _gr_mimeformats = Dict(
"image/svg+xml" => "svg",
)
const _gr_wstype_default = @static if Sys.islinux()
"x11"
# "cairox11"
elseif Sys.isapple()
"quartz"
else
"use_default"
end
const _gr_wstype = Ref(get(ENV, "GKSwstype", _gr_wstype_default))
const _gr_wstype = Ref(get(ENV, "GKSwstype", ""))
gr_set_output(wstype::String) = (_gr_wstype[] = wstype)
for (mime, fmt) in _gr_mimeformats
@@ -1381,7 +1588,7 @@ function _display(plt::Plot{GRBackend})
rm(filepath)
else
ENV["GKS_DOUBLE_BUF"] = true
if _gr_wstype[] != "use_default"
if _gr_wstype[] != ""
ENV["GKSwstype"] = _gr_wstype[]
end
gr_display(plt)
+10 -5
View File
@@ -26,7 +26,8 @@ const _pgfplots_markers = KW(
:star6 => "asterisk",
:diamond => "diamond*",
:pentagon => "pentagon*",
:hline => "-"
:hline => "-",
:vline => "|"
)
const _pgfplots_legend_pos = KW(
@@ -170,7 +171,7 @@ function pgf_series(sp::Subplot, series::Series)
elseif st == :shape
shape_data(series)
elseif ispolar(sp)
theta, r = filter_radial_data(plotattributes[:x], plotattributes[:y], axis_limits(sp[:yaxis]))
theta, r = plotattributes[:x], plotattributes[:y]
rad2deg.(theta), r
else
plotattributes[:x], plotattributes[:y]
@@ -398,8 +399,12 @@ function pgf_axis(sp::Subplot, letter)
# framestyle
if framestyle in (:axes, :origin)
axispos = framestyle == :axes ? "left" : "middle"
# the * after lines disables the arrows at the axes
push!(style, string("axis lines* = ", axispos))
if axis[:draw_arrow]
push!(style, string("axis ", letter, " line = ", axispos))
else
# the * after line disables the arrow at the axis
push!(style, string("axis ", letter, " line* = ", axispos))
end
end
if framestyle == :zerolines
@@ -563,7 +568,7 @@ end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone])
write(io, read(open(fn), String))
end
+18 -14
View File
@@ -186,11 +186,6 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
# flip
if axis[:flip]
ax[:range] = reverse(ax[:range])
end
# ticks
if axis[:ticks] != :native
ticks = get_ticks(axis)
@@ -208,6 +203,10 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
ax[:showgrid] = false
end
# flip
if axis[:flip]
ax[:range] = reverse(ax[:range])
end
ax
end
@@ -355,7 +354,7 @@ end
function plotly_colorscale(grad::ColorGradient, α)
[[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)]
end
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α)
if length(c) == 1
return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]]
@@ -507,13 +506,13 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showscale] = hascolorbar(sp)
elseif st == :contour
filled = isfilledcontour(series)
plotattributes_out[:type] = "contour"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
# plotattributes_out[:showscale] = series[:colorbar] != :none
plotattributes_out[:ncontours] = series[:levels]
plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
plotattributes_out[:ncontours] = series[:levels] + 2
plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
plotattributes_out[:showscale] = hascolorbar(sp)
plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series)
elseif st in (:surface, :wireframe)
plotattributes_out[:type] = "surface"
@@ -775,7 +774,7 @@ end
function plotly_polar!(plotattributes_out::KW, series::Series)
# convert polar plots x/y to theta/radius
if ispolar(series[:subplot])
theta, r = filter_radial_data(pop!(plotattributes_out, :x), pop!(plotattributes_out, :y), axis_limits(series[:subplot][:yaxis]))
theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
plotattributes_out[:t] = rad2deg.(theta)
plotattributes_out[:r] = r
end
@@ -854,11 +853,16 @@ end
# ----------------------------------------------------------------
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
write(io, html_head(plt) * html_body(plt))
function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
data = []
for series in plot.series_list
append!(data, plotly_series(plot, series))
end
layout = plotly_layout(plot)
JSON.print(io, Dict(:data => data, :layout => layout))
end
function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt)
end
+5
View File
@@ -55,6 +55,11 @@ _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf")
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps")
function _show(io::IO, m::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend})
show(io, m, plt.o)
end
function write_temp_html(plt::Plot{PlotlyJSBackend})
filename = string(tempname(), ".html")
savefig(plt, filename)
+196 -143
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,6 +34,11 @@ else
:set_facecolor
end
# PyCall API changes in v1.90.0
if !isdefined(PyCall, :_setproperty!)
@warn "Plots no longer supports PyCall < 1.90.0 and PyPlot < 2.8.0. Either update PyCall and PyPlot or pin Plots to a version <= 0.23.2."
end
# # convert colorant to 4-tuple RGBA
# py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha))
@@ -64,17 +69,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) = py_colormap(cgrad())
py_colormap(c::Colorant) = py_colormap(_as_gradient(c))
function py_shading(c, z)
cmap = py_colormap(c)
ls = pycolors["LightSource"](270,45)
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
ls = pycolors."LightSource"(270,45)
ls."shade"(z, cmap, vert_exag=0.1, blend_mode="soft")
end
# get the style (solid, dashed, etc)
@@ -97,7 +102,7 @@ function py_marker(marker::Shape)
mat[i,2] = y[i]
end
mat[n+1,:] = mat[1,:]
pypath["Path"](mat)
pypath."Path"(mat)
end
const _path_MOVETO = UInt8(1)
@@ -182,7 +187,7 @@ end
# end
function get_locator_and_formatter(vals::AVec)
pyticker["FixedLocator"](1:length(vals)), pyticker["FixedFormatter"](vals)
pyticker."FixedLocator"(1:length(vals)), pyticker."FixedFormatter"(vals)
end
function add_pyfixedformatter(cbar, vals::AVec)
@@ -204,20 +209,22 @@ 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)
x, y = series[:x], series[:y]
nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
else
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
if series[:x] != nothing
x, y = series[:x], series[:y]
nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
else
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end
end
end
end
@@ -248,26 +255,28 @@ 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
@@ -279,13 +288,13 @@ end
# bounding box: union of axis tick labels
function py_bbox_ticks(ax, letter)
labels = ax[Symbol("get_"*letter*"ticklabels")]()
labels = getproperty(ax, Symbol("get_"*letter*"ticklabels"))()
py_bbox(labels)
end
# bounding box: axis guide
function py_bbox_axislabel(ax, letter)
pyaxis_label = ax[Symbol("get_"*letter*"axis")]()[:label]
pyaxis_label = getproperty(ax, Symbol("get_"*letter*"axis"))().label
py_bbox(pyaxis_label)
end
@@ -301,11 +310,14 @@ end
function py_bbox_title(ax)
bb = defaultbox
for s in (:title, :_left_title, :_right_title)
bb = bb + py_bbox(ax[s])
bb = bb + py_bbox(getproperty(ax, s))
end
bb
end
# 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
@@ -339,7 +351,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
@@ -371,6 +383,18 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
elseif st == :shape
x, y = shape_data(series)
end
if ispolar(series)
# make negative radii positive and flip the angle
# (PyPlot ignores negative radii)
for i in eachindex(y)
if y[i] < 0
y[i] = -y[i]
x[i] -= π
end
end
end
xyargs = (st in _3dTypes ? (x,y,z) : (x,y))
# handle zcolor and get c/cmap
@@ -440,7 +464,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# push!(handles, handle)
# else
for (i, rng) in enumerate(iter_segments(series))
handle = ax[:plot]((arg[rng] for arg in xyargs)...;
handle = ax."plot"((arg[rng] for arg in xyargs)...;
label = i == 1 ? series[:label] : "",
zorder = series[:series_plotindex],
color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
@@ -468,7 +492,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
:linestyle => py_linestyle(st, get_linestyle(series)),
)
add_arrows(x, y) do xyprev, xy
ax[:annotate]("",
ax."annotate"("",
xytext = (0.001xyprev[1] + 0.999xy[1], 0.001xyprev[2] + 0.999xy[2]),
xy = xy,
arrowprops = arrowprops,
@@ -514,7 +538,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
for i=1:length(y)
extrakw[:c] = _cycle(markercolor, i)
push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i);
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(_cycle(shapes,i)),
@@ -553,7 +577,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
continue
end
push!(handle, ax[:scatter](cur_x_list, cur_y_list;
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = prev_marker,
@@ -574,7 +598,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if !isempty(cur_color_list)
push!(handle, ax[:scatter](cur_x_list, cur_y_list;
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = prev_marker,
@@ -589,7 +613,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
else
# do a normal scatter plot
handle = ax[:scatter](xyargs...;
handle = ax."scatter"(xyargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(series[:markershape]),
@@ -603,7 +627,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if st == :hexbin
handle = ax[:hexbin](x, y;
handle = ax."hexbin"(x, y;
label = series[:label],
zorder = series[:series_plotindex],
gridsize = series[:bins],
@@ -635,7 +659,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
# contour lines
handle = ax[:contour](x, y, z, levelargs...;
handle = ax."contour"(x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex],
linewidths = py_thickness_scale(plt, series[:linewidth]),
@@ -643,13 +667,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw...
)
if series[:contour_labels] == true
PyPlot.clabel(handle, handle[:levels])
PyPlot."clabel"(handle, handle.levels)
end
push!(handles, handle)
# contour fills
if series[:fillrange] != nothing
handle = ax[:contourf](x, y, z, levelargs...;
handle = ax."contourf"(x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
extrakw...
@@ -675,7 +699,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:cmap] = py_fillcolormap(series)
end
end
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
handle = getproperty(ax, st == :surface ? :plot_surface : :plot_wireframe)(x, y, z;
label = series[:label],
zorder = series[:series_plotindex],
rstride = series[:stride][1],
@@ -690,7 +714,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:contours]
for (zdir,mat) in (("x",x), ("y",y), ("z",z))
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat)
handle = ax[:contourf](x, y, z, levelargs...;
handle = ax."contourf"(x, y, z, levelargs...;
zdir = zdir,
cmap = py_fillcolormap(series),
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane
@@ -702,7 +726,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
elseif typeof(z) <: AbstractVector
# tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots)
handle = ax[:plot_trisurf](x, y, z;
handle = ax."plot_trisurf"(x, y, z;
label = series[:label],
zorder = series[:series_plotindex],
cmap = py_fillcolormap(series),
@@ -727,7 +751,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
else
z # hopefully it's in a data format that will "just work" with imshow
end
handle = ax[:imshow](z;
handle = ax."imshow"(z;
zorder = series[:series_plotindex],
cmap = py_colormap(cgrad([:black, :white])),
vmin = 0.0,
@@ -737,7 +761,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
# expand extrema... handle is AxesImage object
xmin, xmax, ymax, ymin = handle[:get_extent]()
xmin, xmax, ymax, ymin = handle."get_extent"()
expand_extrema!(sp, xmin, xmax, ymin, ymax)
# sp[:yaxis].series[:flip] = true
end
@@ -752,7 +776,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
discrete_colorbar_values = dvals
end
handle = ax[:pcolormesh](x, y, py_mask_nans(z);
handle = ax."pcolormesh"(x, y, py_mask_nans(z);
label = series[:label],
zorder = series[:series_plotindex],
cmap = py_fillcolormap(series),
@@ -767,8 +791,8 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
handle = []
for (i, rng) in enumerate(iter_segments(series))
if length(rng) > 1
path = pypath["Path"](hcat(x[rng], y[rng]))
patches = pypatches["PathPatch"](
path = pypath."Path"(hcat(x[rng], y[rng]))
patches = pypatches."PathPatch"(
path;
label = series[:label],
zorder = series[:series_plotindex],
@@ -778,14 +802,14 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
linestyle = py_linestyle(st, get_linestyle(series, i)),
fill = true
)
push!(handle, ax[:add_patch](patches))
push!(handle, ax."add_patch"(patches))
end
end
push!(handles, handle)
end
if st == :pie
handle = ax[:pie](y;
handle = ax."pie"(y;
# colors = # a vector of colors?
labels = pie_labels(sp, series)
)[1]
@@ -820,7 +844,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
dim1, _cycle(fillrange[1], rng), _cycle(fillrange[2], rng)
end
handle = ax[f](args..., trues(n), false, py_fillstepstyle(st);
handle = getproperty(ax, f)(args..., trues(n), false, py_fillstepstyle(st);
zorder = series[:series_plotindex],
facecolor = py_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
linewidths = 0
@@ -841,27 +865,27 @@ end
function py_set_lims(ax, axis::Axis)
letter = axis[:letter]
lfrom, lto = axis_limits(axis)
ax[Symbol("set_", letter, "lim")](lfrom, lto)
getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto)
end
function py_set_ticks(ax, ticks, letter)
ticks == :auto && return
axis = ax[Symbol(letter,"axis")]
axis = getproperty(ax, Symbol(letter,"axis"))
if ticks == :none || ticks == nothing || ticks == false
kw = KW()
for dir in (:top,:bottom,:left,:right)
kw[dir] = kw[Symbol(:label,dir)] = false
end
axis[:set_tick_params](;which="both", kw...)
axis."set_tick_params"(;which="both", kw...)
return
end
ttype = ticksType(ticks)
if ttype == :ticks
axis[:set_ticks](ticks)
axis."set_ticks"(ticks)
elseif ttype == :ticks_and_labels
axis[:set_ticks](ticks[1])
axis[:set_ticklabels](ticks[2])
axis."set_ticks"(ticks[1])
axis."set_ticklabels"(ticks[2])
else
error("Invalid input for $(letter)ticks: $ticks")
end
@@ -891,7 +915,7 @@ function py_set_scale(ax, axis::Axis)
scale = axis[:scale]
letter = axis[:letter]
scale in supported_scales() || return @warn("Unhandled scale value in pyplot: $scale")
func = ax[Symbol("set_", letter, "scale")]
func = getproperty(ax, Symbol("set_", letter, "scale"))
kw = KW()
arg = if scale == :identity
"linear"
@@ -911,16 +935,16 @@ end
function py_set_axis_colors(sp, ax, a::Axis)
for (loc, spine) in ax[:spines]
spine[:set_color](py_color(a[:foreground_color_border]))
for (loc, spine) in ax.spines
spine."set_color"(py_color(a[:foreground_color_border]))
end
axissym = Symbol(a[:letter], :axis)
if haskey(ax, axissym)
if PyCall.hasproperty(ax, axissym)
tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis])
ax[:tick_params](axis=string(a[:letter]), which="both",
ax."tick_params"(axis=string(a[:letter]), which="both",
colors=tickcolor,
labelcolor=py_color(a[:tickfontcolor]))
ax[axissym][:label][:set_color](py_color(a[:guidefontcolor]))
getproperty(ax, axissym).label.set_color(py_color(a[:guidefontcolor]))
end
end
@@ -932,14 +956,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update the fig
w, h = plt[:size]
fig = plt.o
fig[:clear]()
fig."clear"()
dpi = plt[:dpi]
fig[:set_size_inches](w/DPI, h/DPI, forward = true)
fig[set_facecolor_sym](py_color(plt[:background_color_outside]))
fig[:set_dpi](plt[:dpi])
fig."set_size_inches"(w/DPI, h/DPI, forward = true)
getproperty(fig, set_facecolor_sym)(py_color(plt[:background_color_outside]))
fig."set_dpi"(plt[:dpi])
# resize the window
PyPlot.plt[:get_current_fig_manager]()[:resize](w, h)
PyPlot.plt."get_current_fig_manager"().resize(w, h)
# initialize subplots
for sp in plt.subplots
@@ -973,10 +997,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
else
:title
end
ax[func][:set_text](sp[:title])
ax[func][:set_fontsize](py_thickness_scale(plt, sp[:titlefontsize]))
ax[func][:set_family](sp[:titlefontfamily])
ax[func][:set_color](py_color(sp[:titlefontcolor]))
getproperty(ax, func)."set_text"(sp[:title])
getproperty(ax, func)."set_fontsize"(py_thickness_scale(plt, sp[:titlefontsize]))
getproperty(ax, func)."set_family"(sp[:titlefontfamily])
getproperty(ax, func)."set_color"(py_color(sp[:titlefontcolor]))
# ax[:set_title](sp[:title], loc = loc)
end
@@ -996,7 +1020,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw[:boundaries] = vcat(0, kw[:values] + 0.5)
elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z))
cmin, cmax = get_clims(sp)
norm = pycolors[:Normalize](vmin = cmin, vmax = cmax)
norm = pycolors."Normalize"(vmin = cmin, vmax = cmax)
f = if colorbar_series[:line_z] != nothing
py_linecolormap
elseif colorbar_series[:fill_z] != nothing
@@ -1004,21 +1028,22 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
else
py_markercolormap
end
cmap = pycmap[:ScalarMappable](norm = norm, cmap = f(colorbar_series))
cmap[:set_array]([])
cmap = pycmap."ScalarMappable"(norm = norm, cmap = f(colorbar_series))
cmap."set_array"([])
handle = cmap
end
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
@@ -1026,28 +1051,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# framestyle
if !ispolar(sp) && !is3d(sp)
ax[:spines]["left"][:set_linewidth](py_thickness_scale(plt, 1))
ax[:spines]["bottom"][:set_linewidth](py_thickness_scale(plt, 1))
ax.spines["left"]."set_linewidth"(py_thickness_scale(plt, 1))
ax.spines["bottom"]."set_linewidth"(py_thickness_scale(plt, 1))
if sp[:framestyle] == :semi
intensity = 0.5
ax[:spines]["right"][:set_alpha](intensity)
ax[:spines]["top"][:set_alpha](intensity)
ax[:spines]["right"][:set_linewidth](py_thickness_scale(plt, intensity))
ax[:spines]["top"][:set_linewidth](py_thickness_scale(plt, intensity))
ax.spines["right"]."set_alpha"(intensity)
ax.spines["top"]."set_alpha"(intensity)
ax.spines["right"]."set_linewidth"(py_thickness_scale(plt, intensity))
ax.spines["top"]."set_linewidth"(py_thickness_scale(plt, intensity))
elseif sp[:framestyle] in (:axes, :origin)
ax[:spines]["right"][:set_visible](false)
ax[:spines]["top"][:set_visible](false)
ax.spines["right"]."set_visible"(false)
ax.spines["top"]."set_visible"(false)
if sp[:framestyle] == :origin
ax[:spines]["bottom"][:set_position]("zero")
ax[:spines]["left"][:set_position]("zero")
ax.spines["bottom"]."set_position"("zero")
ax.spines["left"]."set_position"("zero")
end
elseif sp[:framestyle] in (:grid, :none, :zerolines)
for (loc, spine) in ax[:spines]
spine[:set_visible](false)
for (loc, spine) in ax.spines
spine."set_visible"(false)
end
if sp[:framestyle] == :zerolines
ax[:axhline](y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax[:axvline](x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax."axhline"(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
ax."axvline"(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
end
end
end
@@ -1055,22 +1080,22 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# axis attributes
for letter in (:x, :y, :z)
axissym = Symbol(letter, :axis)
haskey(ax, axissym) || continue
PyCall.hasproperty(ax, axissym) || continue
axis = sp[axissym]
pyaxis = ax[axissym]
pyaxis = getproperty(ax, axissym)
if axis[:mirror] && letter != :z
pos = letter == :x ? "top" : "right"
pyaxis[:set_label_position](pos) # the guides
pyaxis[:set_ticks_position]("both") # the hash marks
pyaxis[Symbol(:tick_, pos)]() # the tick labels
pyaxis."set_label_position"(pos) # the guides
pyaxis."set_ticks_position"("both") # the hash marks
getproperty(pyaxis, Symbol(:tick_, pos))() # the tick labels
end
if axis[:guide_position] != :auto && letter != :z
pyaxis[:set_label_position](axis[:guide_position])
pyaxis."set_label_position"(axis[:guide_position])
end
py_set_scale(ax, axis)
axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing
if ispolar(sp) && letter == :y
ax[:set_rlabel_position](90)
ax."set_rlabel_position"(90)
end
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
# don't show the 0 tick label for the origin framestyle
@@ -1078,28 +1103,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
ticks[2][ticks[1] .== 0] .= ""
end
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
ax[Symbol("set_", letter, "label")](axis[:guide])
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in")
getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide])
if get(axis.plotattributes, :flip, false)
ax[Symbol("invert_", letter, "axis")]()
getproperty(ax, Symbol("invert_", letter, "axis"))()
end
pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize]))
pyaxis[:label][:set_family](axis[:guidefontfamily])
for lab in ax[Symbol("get_", letter, "ticklabels")]()
lab[:set_fontsize](py_thickness_scale(plt, axis[:tickfontsize]))
lab[:set_family](axis[:tickfontfamily])
lab[:set_rotation](axis[:rotation])
pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize]))
pyaxis."label"."set_family"(axis[:guidefontfamily])
for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))()
lab."set_fontsize"(py_thickness_scale(plt, axis[:tickfontsize]))
lab."set_family"(axis[:tickfontfamily])
lab."set_rotation"(axis[:rotation])
end
if axis[:grid] && !(ticks in (:none, nothing, false))
fgcolor = py_color(axis[:foreground_color_grid])
pyaxis[:grid](true,
pyaxis."grid"(true,
color = fgcolor,
linestyle = py_linestyle(:line, axis[:gridstyle]),
linewidth = py_thickness_scale(plt, axis[:gridlinewidth]),
alpha = axis[:gridalpha])
ax[:set_axisbelow](true)
ax."set_axisbelow"(true)
else
pyaxis[:grid](false)
pyaxis."grid"(false)
end
py_set_axis_colors(sp, ax, axis)
end
@@ -1109,48 +1134,48 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw = KW()
for dir in (:top, :bottom)
if ispolar(sp)
ax[:spines]["polar"][:set_visible](false)
ax."spines"."polar"."set_visible"(false)
else
ax[:spines][string(dir)][:set_visible](false)
getproperty(ax.spines, dir).set_visible(false)
end
kw[dir] = kw[Symbol(:label,dir)] = false
end
ax[:xaxis][:set_tick_params](; which="both", kw...)
ax."xaxis"."set_tick_params"(; which="both", kw...)
end
if !sp[:yaxis][:showaxis]
kw = KW()
for dir in (:left, :right)
if !ispolar(sp)
ax[:spines][string(dir)][:set_visible](false)
getproperty(ax.spines, dir).set_visible(false)
end
kw[dir] = kw[Symbol(:label,dir)] = false
end
ax[:yaxis][:set_tick_params](; which="both", kw...)
ax."yaxis"."set_tick_params"(; which="both", kw...)
end
# aspect ratio
aratio = sp[:aspect_ratio]
if aratio != :none
ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
ax."set_aspect"(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
end
#camera/view angle
if is3d(sp)
#convert azimuthal to match GR behaviour
#view_init(elevation, azimuthal) so reverse :camera args
ax[:view_init]((sp[:camera].-(90,0))[end:-1:1]...)
ax."view_init"((sp[:camera].-(90,0))[end:-1:1]...)
end
# legend
py_add_legend(plt, sp, ax)
# this sets the bg color inside the grid
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
getproperty(ax, set_facecolor_sym)(py_color(sp[:background_color_inside]))
# link axes
x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o
ax != x_ax_link && ax[:get_shared_x_axes]()[:join](ax, sp[:xaxis].sps[1].o)
ax != y_ax_link && ax[:get_shared_y_axes]()[:join](ax, sp[:yaxis].sps[1].o)
ax != x_ax_link && ax."get_shared_x_axes"()."join"(ax, sp[:xaxis].sps[1].o)
ax != y_ax_link && ax."get_shared_y_axes"()."join"(ax, sp[:yaxis].sps[1].o)
end
py_drawfig(fig)
end
@@ -1170,7 +1195,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
toppad = 0mm
rightpad = 0mm
bottompad = 0mm
for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax))
for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax), py_bbox_legend(ax))
if ispositive(width(bb)) && ispositive(height(bb))
leftpad = max(leftpad, left(plotbb) - left(bb))
toppad = max(toppad, top(plotbb) - top(bb))
@@ -1181,7 +1206,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
# optionally add the width of colorbar labels and colorbar to rightpad
if haskey(sp.attr, :cbar_ax)
bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]())
bb = py_bbox(sp.attr[:cbar_handle]."ax"."get_yticklabels"())
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
rightpad = rightpad + sp.attr[:cbar_width]
end
@@ -1202,13 +1227,13 @@ end
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val)
ax = sp.o
ax[:annotate](val, xy = (x,y), zorder = 999)
ax."annotate"(val, xy = (x,y), zorder = 999)
end
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
ax = sp.o
ax[:annotate](val.str,
ax."annotate"(val.str,
xy = (x,y),
family = val.font.family,
color = py_color(val.font.color),
@@ -1233,6 +1258,34 @@ 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)
@@ -1244,14 +1297,14 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
if should_add_to_legend(series)
# add a line/marker and a label
push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
pypatches[:Patch](
pypatches."Patch"(
edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)),
facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)),
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(series[:seriestype], get_linestyle(series))
)
elseif series[:seriestype] in (:path, :straightline, :scatter)
PyPlot.plt[:Line2D]((0,1),(0,0),
PyPlot.plt."Line2D"((0,1),(0,0),
color = py_color(get_linecolor(series, clims), get_linealpha(series)),
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(:path, get_linestyle(series)),
@@ -1268,22 +1321,23 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# if anything was added, call ax.legend and set the colors
if !isempty(handles)
leg = ax[:legend](handles,
leg = ax."legend"(handles,
labels,
loc = get(_pyplot_legend_pos, leg, "best"),
loc = py_legend_pos(leg),
bbox_to_anchor = py_legend_bbox(leg),
scatterpoints = 1,
fontsize = py_thickness_scale(plt, sp[:legendfontsize]),
facecolor = py_color(sp[:background_color_legend]),
edgecolor = py_color(sp[:foreground_color_legend]),
framealpha = alpha(plot_color(sp[:background_color_legend])),
)
frame = leg[:get_frame]()
frame[:set_linewidth](py_thickness_scale(plt, 1))
leg[:set_zorder](1000)
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
frame = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000)
sp[:legendtitle] != nothing && leg."set_title"(sp[:legendtitle])
for txt in leg[:get_texts]()
PyPlot.plt[:setp](txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
for txt in leg."get_texts"()
PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
end
end
end
@@ -1301,7 +1355,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
figw, figh = sp.plt[:size]
figw, figh = figw*px, figh*px
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
ax[:set_position](pcts)
ax."set_position"(pcts)
# set the cbar position if there is one
if haskey(sp.attr, :cbar_ax)
@@ -1311,7 +1365,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7)
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm))
pcts = bbox_to_pcts(cb_bbox, figw, figh)
sp.attr[:cbar_ax][:set_position](pcts)
sp.attr[:cbar_ax]."set_position"(pcts)
end
end
PyPlot.draw()
@@ -1320,9 +1374,7 @@ end
# -----------------------------------------------------------------
# display/output
function _display(plt::Plot{PyPlotBackend})
plt.o[:show]()
end
_display(plt::Plot{PyPlotBackend}) = plt.o."show"()
@@ -1332,23 +1384,24 @@ const _pyplot_mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"application/postscript" => "ps",
"image/svg+xml" => "svg"
"image/svg+xml" => "svg",
"application/x-tex" => "pgf"
)
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")
+1 -1
View File
@@ -116,7 +116,7 @@ function addUnicodeSeries!(o, plotattributes::KW, addlegend::Bool, xlim, ylim)
x, y = if st == :straightline
straightline_data(plotattributes)
elseif st == :shape
shape_data(series)
shape_data(plotattributes)
else
[collect(float(plotattributes[s])) for s in (:x, :y)]
end
+7 -10
View File
@@ -1,7 +1,7 @@
const P2 = StaticArrays.SVector{2,Float64}
const P3 = StaticArrays.SVector{3,Float64}
const P2 = GeometryTypes.Point2{Float64}
const P3 = GeometryTypes.Point3{Float64}
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
@@ -261,13 +261,13 @@ end
Create a Font from a list of features. Values may be specified either as
arguments (which are distinguished by type/value) or as keyword arguments.
# Arguments
- `family`: AbstractString. "serif" or "sans-serif" or "monospace"
- `family`: AbstractString. "serif" or "sans-serif" or "monospace"
- `pointsize`: Integer. Size of font in points
- `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right)
- `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom)
- `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type)
- `color`: Colorant or Symbol
# Examples
# Examples
```julia-repl
julia> font(8)
julia> font(family="serif",halign=:center,rotation=45.0)
@@ -388,8 +388,8 @@ PlotText(str) = PlotText(string(str), font())
"""
text(string, args...; kw...)
Create a PlotText object wrapping a string with font info, for plot annotations.
`args` and `kw` are passed to `font`.
Create a PlotText object wrapping a string with font info, for plot annotations.
`args` and `kw` are passed to `font`.
"""
text(t::PlotText) = t
text(t::PlotText, font::Font) = PlotText(t.str, font)
@@ -779,7 +779,7 @@ end
# -----------------------------------------------------------------------
"create a BezierCurve for plotting"
mutable struct BezierCurve{T <: StaticArrays.SVector}
mutable struct BezierCurve{T <: GeometryTypes.Point}
control_points::Vector{T}
end
@@ -792,9 +792,6 @@ function (bc::BezierCurve)(t::Real)
p
end
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
# mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
@deprecate curve_points coords
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50))
+3 -2
View File
@@ -86,8 +86,9 @@ yaxis!("YLABEL", :log10)
PlotExample("Images",
"Plot an image. y-axis is set to flipped",
[:(begin
import FileIO, PlotReferenceImages
img = FileIO.load(joinpath(dirname(pathof(PlotReferenceImages)), "..", "Plots","pyplot","0.7.0","ref1.png"))
import FileIO
path = download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png")
img = FileIO.load(path)
plot(img)
end)]
),
+24
View File
@@ -0,0 +1,24 @@
# ---------------------------------------------------------
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
_fileio_load(@nospecialize(filename::AbstractString)) = FileIO.load(filename::AbstractString)
_fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) = FileIO.save(filename::AbstractString, x)
function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot)
fn = tempname()
# first save a pdf file
pdf(plt, fn)
# load that pdf into a FileIO Stream
s = _fileio_load(fn * ".pdf")
# save a png
pngfn = fn * ".png"
_fileio_save(pngfn, s)
# now write from the file
write(io, read(open(pngfn), String))
end
const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
+59
View File
@@ -0,0 +1,59 @@
const use_local_dependencies = Ref(false)
const use_local_plotlyjs = Ref(false)
function _init_ijulia_plotting()
# IJulia is more stable with local file
use_local_plotlyjs[] = isfile(plotly_local_file_path)
ENV["MPLBACKEND"] = "Agg"
end
"""
Add extra jupyter mimetypes to display_dict based on the plot backed.
The default is nothing, except for plotly based backends, where it
adds data for `application/vnd.plotly.v1+json` that is used in
frontends like jupyterlab and nteract.
"""
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
out
end
function _ijulia__extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict(
:data => plotly_series(plt),
:layout => plotly_layout(plt)
)
out
end
function _ijulia_display_dict(plt::Plot)
output_type = Symbol(plt.attr[:html_output_format])
if output_type == :auto
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
end
out = Dict()
if output_type == :txt
mime = "text/plain"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :png
mime = "image/png"
out[mime] = base64encode(show, MIME(mime), plt)
elseif output_type == :svg
mime = "image/svg+xml"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :html
mime = "text/html"
out[mime] = sprint(show, MIME(mime), plt)
else
error("Unsupported output type $output_type")
end
_ijulia__extra_mime_info!(plt, out)
out
end
+22 -85
View File
@@ -1,16 +1,22 @@
using REPL
const use_local_dependencies = Ref(false)
function _plots_defaults()
if isdefined(Main, :PLOTS_DEFAULTS)
Dict{Symbol,Any}(Main.PLOTS_DEFAULTS)
else
Dict{Symbol,Any}()
end
end
function __init__()
if isdefined(Main, :PLOTS_DEFAULTS)
if haskey(Main.PLOTS_DEFAULTS, :theme)
theme(Main.PLOTS_DEFAULTS[:theme])
end
for (k,v) in Main.PLOTS_DEFAULTS
k == :theme || default(k, v)
end
user_defaults = _plots_defaults()
if haskey(user_defaults, :theme)
theme(user_defaults[:theme])
end
for (k,v) in user_defaults
k == :theme || default(k, v)
end
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
@@ -29,95 +35,26 @@ function __init__()
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" include(joinpath(@__DIR__, "backends", "pyplot.jl"))
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" include(joinpath(@__DIR__, "backends", "unicodeplots.jl"))
# ---------------------------------------------------------
# IJulia
# ---------------------------------------------------------
use_local = false
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited
# IJulia is more stable with local file
use_local = isfile(plotly_local_file_path)
"""
Add extra jupyter mimetypes to display_dict based on the plot backed.
_init_ijulia_plotting()
The default is nothing, except for plotly based backends, where it
adds data for `application/vnd.plotly.v1+json` that is used in
frontends like jupyterlab and nteract.
"""
_extra_mime_info!(plt::Plot, out::Dict) = out
function _extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
out
end
function _extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict(
:data => plotly_series(plt),
:layout => plotly_layout(plt)
)
out
end
function IJulia.display_dict(plt::Plot)
output_type = Symbol(plt.attr[:html_output_format])
if output_type == :auto
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
end
out = Dict()
if output_type == :txt
mime = "text/plain"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :png
mime = "image/png"
out[mime] = base64encode(show, MIME(mime), plt)
elseif output_type == :svg
mime = "image/svg+xml"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :html
mime = "text/html"
out[mime] = sprint(show, MIME(mime), plt)
else
error("Unsupported output type $output_type")
end
_extra_mime_info!(plt, out)
out
end
ENV["MPLBACKEND"] = "Agg"
IJulia.display_dict(plt::Plot) = _ijulia_display_dict(plt)
end
end
if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL")
use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local
if use_local && !isfile(plotly_local_file_path)
use_local_plotlyjs[] = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local_plotlyjs[]
if use_local_plotlyjs[] && !isfile(plotly_local_file_path)
@warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true")
end
else
use_local_dependencies[] = use_local
use_local_dependencies[] = use_local_plotlyjs[]
end
# ---------------------------------------------------------
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
@require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin
PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
fn = tempname()
# first save a pdf file
pdf(plt, fn)
# load that pdf into a FileIO Stream
s = FileIO.load(fn * ".pdf")
# save a png
pngfn = fn * ".png"
FileIO.save(pngfn, s)
# now write from the file
write(io, read(open(pngfn), String))
end
_show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt)
end
end
+1 -3
View File
@@ -55,9 +55,7 @@ tex(fn::AbstractString) = tex(current(), fn)
function html(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "html")
io = open(fn, "w")
_use_remote[] = true
show(io, MIME("text/html"), plt)
_use_remote[] = false
close(io)
end
html(fn::AbstractString) = html(current(), fn)
@@ -191,7 +189,7 @@ end
# for writing to io streams... first prepare, then callback
for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml",
"application/eps", "application/pdf", "application/postscript",
"application/x-tex")
"application/x-tex", "application/vnd.plotly.v1+json")
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
if haskey(io, :juno_plotsize)
showjuno(io, m, plt)
+7 -2
View File
@@ -50,8 +50,13 @@ function plotattr(attrtype::Symbol, attribute::AbstractString)
desc = get(_arg_desc, attribute, "")
first_period_idx = findfirst(isequal('.'), desc)
typedesc = desc[1:first_period_idx-1]
desc = strip(desc[first_period_idx+1:end])
if isnothing(first_period_idx)
typedesc = ""
desc = strip(desc)
else
typedesc = desc[1:first_period_idx-1]
desc = strip(desc[first_period_idx+1:end])
end
als = keys(filter(x->x[2]==attribute, _keyAliases)) |> collect |> sort
als = join(map(string,als), ", ")
def = _attribute_defaults[attrtype][attribute]
+33 -2
View File
@@ -47,16 +47,47 @@ end
num_series(x::AMat) = size(x,2)
num_series(x) = 1
RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T"))
RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T"))
# ---------------------------------------------------------------------------
# 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
@@ -1061,7 +1092,7 @@ end
# -------------------------------------------------
"Adds a+bx... straight line over the current plot, without changing the axis limits"
"Adds ax+b... straight line over the current plot, without changing the axis limits"
abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...)
abline!(args...; kw...) = abline!(current(), args...; kw...)
+7 -7
View File
@@ -554,7 +554,7 @@ end
#
#
# # --------------------------------------------------------------------
# # Lists of tuples and StaticArrays
# # Lists of tuples and GeometryTypes.Points
# # --------------------------------------------------------------------
#
# # if we get an unhandled tuple, just splat it in
@@ -576,14 +576,14 @@ end
#
# # 2D StaticArrays
@recipe f(xy::AVec{StaticArrays.SVector{2,T}}) where {T<:Number} = unzip(xy)
@recipe f(xy::StaticArrays.SVector{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
# # 2D Points
@recipe f(xy::AVec{GeometryTypes.Point{2,T}}) where {T<:Number} = unzip(xy)
@recipe f(xy::GeometryTypes.Point{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
#
# # 3D StaticArrays
@recipe f(xyz::AVec{StaticArrays.SVector{3,T}}) where {T<:Number} = unzip(xyz)
@recipe f(xyz::StaticArrays.SVector{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
# # 3D Points
@recipe f(xyz::AVec{GeometryTypes.Point{3,T}}) where {T<:Number} = unzip(xyz)
@recipe f(xyz::GeometryTypes.Point{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
#
# # --------------------------------------------------------------------
+1 -1
View File
@@ -449,7 +449,7 @@ yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip
"Specify x axis attributes for an existing plot"
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
"Specify x axis attributes for an existing plot"
"Specify y axis attributes for an existing plot"
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
+63 -67
View File
@@ -194,7 +194,9 @@ end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
if has_attribute_segments(series)
if x == nothing
return UnitRange{Int}[]
elseif has_attribute_segments(series)
if series[:seriestype] in (:scatter, :scatter3d)
return [[i] for i in 1:length(y)]
else
@@ -273,6 +275,9 @@ _cycle(v, indices::AVec{Int}) = fill(v, length(indices))
_cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
_as_gradient(grad::ColorGradient) = grad
_as_gradient(c::Colorant) = ColorGradient([c,c])
makevec(v::AVec) = v
makevec(v::T) where {T} = T[v]
@@ -287,14 +292,14 @@ unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2]
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
unzip(xy::AVec{StaticArrays.SVector{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
unzip(xy::StaticArrays.SVector{2,T}) where {T} = T[xy[1]], T[xy[2]]
unzip(xy::AVec{GeometryTypes.Point{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
unzip(xy::GeometryTypes.Point{2,T}) where {T} = T[xy[1]], T[xy[2]]
unzip(xyz::AVec{StaticArrays.SVector{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
unzip(xyz::StaticArrays.SVector{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip(xyz::AVec{GeometryTypes.Point{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
unzip(xyz::GeometryTypes.Point{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip(xyuv::AVec{StaticArrays.SVector{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
unzip(xyuv::StaticArrays.SVector{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
unzip(xyuv::AVec{GeometryTypes.Point{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
unzip(xyuv::GeometryTypes.Point{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x)
@@ -370,38 +375,14 @@ function heatmap_edges(v::AVec, scale::Symbol = :identity)
map(invf, _heatmap_edges(map(f,v)))
end
function calc_r_extrema(x, y)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
ignorenan_extrema(r)
end
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
rmin, rmax = r_extrema
theta, r = filter_radial_data(x, y, r_extrema)
r = (r .- rmin) ./ (rmax .- rmin)
x = r.*cos.(theta)
y = r.*sin.(theta)
x, y
end
# Filters radial data for points within the axis limits
function filter_radial_data(theta, r, r_extrema::Tuple{Real, Real})
n = max(length(theta), length(r))
rmin, rmax = r_extrema
x, y = zeros(n), zeros(n)
for i in 1:n
x[i] = _cycle(theta, i)
y[i] = _cycle(r, i)
end
points = map((a, b) -> (a, b), x, y)
filter!(a -> a[2] >= rmin && a[2] <= rmax, points)
x = map(a -> a[1], points)
y = map(a -> a[2], points)
x, y
end
function fakedata(sz...)
y = zeros(sz...)
for r in 2:size(y,1)
@@ -431,7 +412,7 @@ isvertical(series::Series) = isvertical(series.plotattributes)
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels
ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = :ticks_and_labels
ticksType(ticks) = :invalid
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
@@ -581,35 +562,50 @@ end
_update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
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)
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
function colorbar_style(series::Series)
colorbar_entry = series[:colorbar_entry]
if !(colorbar_entry isa Bool)
@warn "Non-boolean colorbar_entry ignored."
colorbar_entry = true
end
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
if !colorbar_entry
nothing
elseif isfilledcontour(series)
cbar_fill
elseif iscontour(series)
cbar_lines
elseif series[:seriestype] (:heatmap,:surface) ||
any(series[z] !== nothing for z [:marker_z,:line_z,:fill_z])
cbar_gradient
else
nothing
end
# no colorbar if we are creating a surface LightSource
if xor(st == :surface, series[:fill_z] != nothing)
hascbar = true
end
return hascbar
end
function hascolorbar(sp::Subplot)
cbar = sp[:colorbar]
hascbar = false
if cbar != :none
for series in series_list(sp)
if hascolorbar(series)
hascbar = true
end
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]
end
end
hascbar
levels
end
for comp in (:line, :fill, :marker)
compcolor = string(comp, :color)
@@ -726,7 +722,7 @@ function with(f::Function, args...; kw...)
# save the backend
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
_pick_default_backend()
end
oldbackend = CURRENT_BACKEND.sym
@@ -796,24 +792,24 @@ function debugplots(on = true)
_debugMode.on = on
end
debugshow(x) = show(x)
debugshow(x::AbstractArray) = print(summary(x))
debugshow(io, x) = show(io, x)
debugshow(io, x::AbstractArray) = print(io, summary(x))
function dumpdict(plotattributes::KW, prefix = "", alwaysshow = false)
function dumpdict(io::IO, plotattributes::KW, prefix = "", alwaysshow = false)
_debugMode.on || alwaysshow || return
println()
println(io)
if prefix != ""
println(prefix, ":")
println(io, prefix, ":")
end
for k in sort(collect(keys(plotattributes)))
@printf("%14s: ", k)
debugshow(plotattributes[k])
println()
debugshow(io, plotattributes[k])
println(io)
end
println()
println(io)
end
DD(plotattributes::KW, prefix = "") = dumpdict(plotattributes, prefix, true)
DD(io::IO, plotattributes::KW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
DD(plotattributes::KW, prefix = "") = DD(stdout, plotattributes, prefix)
function dumpcallstack()
error() # well... you wanted the stacktrace, didn't you?!?
@@ -1208,8 +1204,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
@@ -0,0 +1 @@
reference_images
-10
View File
@@ -1,10 +0,0 @@
StatsPlots
Images
ImageMagick
@osx QuartzImageIO
FileIO
GR 0.31.0
RDatasets
VisualRegressionTests
UnicodePlots
LaTeXStrings
-46
View File
@@ -1,46 +0,0 @@
using Pkg
# need this to use Conda
# ENV["PYTHON"] = ""
to_add = [
# PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"),
PackageSpec(name="PlotUtils", rev="master"),
PackageSpec(name="RecipesBase", rev="master"),
# PackageSpec(name="Blink", rev="master"),
# PackageSpec(name="Rsvg", rev="master"),
# PackageSpec(name="PlotlyJS", rev="master"),
# PackageSpec(name="VisualRegressionTests", rev="master"),
# PackageSpec("PyPlot"),
# PackageSpec("InspectDR"),
]
if isinteractive()
Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"))
append!(to_add, [
PackageSpec(name="FileIO"),
PackageSpec(name="ImageMagick"),
PackageSpec(name="UnicodePlots"),
PackageSpec(name="VisualRegressionTests"),
PackageSpec(name="Gtk"),
# PlotlyJS:
# PackageSpec(name="PlotlyJS"),
# PackageSpec(name="Blink"),
# PackageSpec(name="ORCA"),
# PyPlot:
# PackageSpec(name="PyPlot"),
# PackageSpec(name="PyCall"),
# PackageSpec(name="LaTeXStrings"),
])
else
push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"))
end
Pkg.add(to_add)
Pkg.build("ImageMagick")
# Pkg.build("GR")
# Pkg.build("Blink")
# import Blink
# Blink.AtomShell.install()
# Pkg.build("PyPlot")
+33 -35
View File
@@ -1,50 +1,46 @@
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
# Taken from MakieGallery
"""
Downloads the reference images from ReferenceImages for a specific version
"""
function download_reference(version = v"0.0.1")
download_dir = abspath(@__DIR__, "reference_images")
isdir(download_dir) || mkpath(download_dir)
tarfile = joinpath(download_dir, "reference_images.zip")
url = "https://github.com/JuliaPlots/PlotReferenceImages.jl/archive/v$(version).tar.gz"
refpath = joinpath(download_dir, "PlotReferenceImages.jl-$(version)")
if !isdir(refpath) # if not yet downloaded
@info "downloading reference images for version $version"
download(url, tarfile)
BinaryProvider.unpack(tarfile, download_dir)
# check again after download
if !isdir(refpath)
error("Something went wrong while downloading reference images. Plots can't be compared to references")
else
rm(tarfile, force = true)
end
else
@info "using reference images for version $version (already downloaded)"
end
refpath
end
const ref_image_dir = download_reference()
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2)
Plots._debugMode.on = debug
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))
refdir = joinpath(ref_image_dir, "Plots", string(pkg))
fn = "ref$idx.png"
# firgure out version info
@@ -76,7 +72,9 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
# test function
func = (fn, idx) -> begin
map(eval, example.exprs)
expr = Expr(:block)
append!(expr.args, example.exprs)
eval(expr)
png(fn)
end
+12 -115
View File
@@ -1,8 +1,11 @@
module PlotsTests
using VisualRegressionTests
using Plots
using Random
using BinaryProvider
using Test
using FileIO
include("add_packages.jl")
include("imgcomp.jl")
# don't actually show the plots
Random.seed!(1234)
default(show=false, reuse=true)
@@ -19,85 +22,20 @@ img_tol = isinteractive() ? 1e-2 : 10e-2
end
end
# @static if isinteractive()
# @testset "PyPlot" begin
# @test pyplot() == Plots.PyPlotBackend()
# @test backend() == Plots.PyPlotBackend()
#
# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31])
# end
# end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@test isa(plot(rand(10)), Plots.Plot) == true
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = bar(randn(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
end
# The plotlyjs testimages return a connection error on travis:
# 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]
@@ -115,44 +53,3 @@ end
@testset "NoFail" begin
histogram([1, 0, 0, 0, 0, 0])
end
# tests for preprocessing recipes
# @testset "recipes" begin
# user recipe
# type T end
# @recipe function f(::T)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# bg := :yellow
# rand(10)
# end
# plot(T())
# plot recipe
# @recipe function f(::Type{Val{:hiplt}},plt::Plot)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# bg:=:green
# ()
# end
# plot(rand(10),t=:hiplt)
# series recipe
# @recipe function f(::Type{Val{:hi}},x,y,z)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# ()
# end
# plot(rand(10),t=:hiplt)
# end
end # module
-36
View File
@@ -1,36 +0,0 @@
import SnoopCompile
### Log the compiles
# This only needs to be run once (to generate "/tmp/plots_compiles.csv")
# SnoopCompile.@snoop "/tmp/plots_compiles.csv" begin
# include(joinpath(dirname(@__FILE__), "runtests.jl"))
# end
# ----------------------------------------------------------
### Parse the compiles and generate precompilation scripts
# This can be run repeatedly to tweak the scripts
# IMPORTANT: we must have the module(s) defined for the parcelation
# step, otherwise we will get no precompiles for the Plots module
using Plots
data = SnoopCompile.read("/tmp/plots_compiles.csv")
# The Plots tests are run inside a module PlotsTest, so all
# the precompiles get credited to PlotsTest. Credit them to Plots instead.
subst = Dict("PlotsTests"=>"Plots")
# Blacklist helps fix problems:
# - MIME uses type-parameters with symbols like :image/png, which is
# not parseable
blacklist = ["MIME"]
# Use these two lines if you want to create precompile functions for
# individual packages
pc, discards = SnoopCompile.parcel(data[end:-1:1,2], subst=subst, blacklist=blacklist)
SnoopCompile.write("/tmp/precompile", pc)
pdir = joinpath(dirname(@__FILE__), "..")
run(`cp /tmp/precompile/precompile_Plots.jl $pdir/src/precompile.jl`)