Compare commits

...

82 Commits

Author SHA1 Message Date
Daniel Schwabeneder 1ea5a5ac0b Merge pull request #2029 from daschw/register
up version
2019-05-13 22:17:04 +02:00
Daniel Schwabeneder bc8370eadd update NEWS.md 2019-05-13 22:16:18 +02:00
Daniel Schwabeneder cdc5a2b361 up version 2019-05-13 22:13:27 +02:00
Daniel Schwabeneder 4270ac80fb Merge pull request #2028 from shipengcheng1230/master
fix gr_display (close #2026)
2019-05-12 19:34:32 +02:00
shipengcheng1230 405df5da8b fix gr_display 2019-05-12 13:14:03 -04:00
Daniel Schwabeneder 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 Schwabeneder 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 Schwabeneder 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 Schwabeneder 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 Schwabeneder 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 Borregaard 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 Schwabeneder 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 Borregaard 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 Schwabeneder 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 Schwabeneder 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 Borregaard 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 Schwabeneder 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 Schwabeneder 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 Schwabeneder 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 Heinen 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 Schwabeneder 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 Schwabeneder 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 Borregaard 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 Borregaard 226023043b Merge pull request #1972 from hycakir/patch-1
fix `abline!` description
2019-03-30 12:16:35 +01:00
Hamza Yusuf Çakır 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 Rollen 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 Schwabeneder 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 Schwabeneder 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 Schwabeneder 47e48e5d27 Merge pull request #1958 from JuliaPlots/sd-gifmime
add support for gif mime
2019-03-25 09:35:25 +01:00
Daniel Schwabeneder 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
29 changed files with 846 additions and 707 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())'
+54
View File
@@ -11,6 +11,60 @@
---
## (current master)
## 0.25.1
- fix gr_display
## 0.25.0
- Replace StaticArrays with GeometryTypes
- Contour fixes for GR
## 0.24.0
- Update to the new PyCall and PyPlot API
- fix drawing of ticks
- fix y label position with GR
## 0.23.2
- pyplot fixes
- Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend.
- fix ticks
- support plotly json mime
- fix image axis limits
- default to radius 0 at center for polar plots
## 0.23.1
- slightly faster load time
- fixed errant MethodError
- fix bar plots with unicodeplots
- better colorbars for contour
- add volume seriestype for GR
- fix passing a tuple to custom ticks
- add vline to pgfplots
- add tex output for pyplot
- better 3d axis labels for GR
## 0.23.0
- compatible with StatPlots -> StatsPlots name shift
- fix histograms for vectors with NaN and Inf
- change gif behaviour (remove cache-busting)
- improved docstrings for shorthands functions
- fix font rotation for pyplot
- fix greyscale images for pyplot
- clamp greyscale images with values outside 0,1
- support keyword argument for font options
- allow vector of markers for pyplot scatter
## 0.22.5
- improve behaviour of plotlyjs backend
## 0.22.4
- Add support for discrete contourf plots with GR
## 0.22.3
- Fix the `showtheme` function
## 0.22.2
- Allow annotations to accept a Tuple instead of the result of a text call (making it possible to specify font characteristics in recipes). E.g. `annotations = (2, 4, ("test", :right, 8, :red))` is the same as `annotations = (2, 4, text("test", :right, 8, :red))`
## 0.22.1
- push PlotsDisplay just after REPLDisplay
+56
View File
@@ -0,0 +1,56 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.25.1"
[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.38.1
+3 -3
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
@@ -187,7 +187,7 @@ include("backends/plotly.jl")
include("backends/gr.jl")
include("backends/web.jl")
include("shorthands.jl")
include("shorthands.jl")
let PlotOrSubplot = Union{Plot, Subplot}
global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
+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)
+1
View File
@@ -150,4 +150,5 @@ const _arg_desc = KW(
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`",
:widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.",
:draw_arrow => "Bool. Draw arrow at the end of the axis.",
)
+22 -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,
@@ -391,6 +392,7 @@ const _axis_defaults = KW(
:minorgrid => false,
:showaxis => true,
:widen => true,
:draw_arrow => false,
)
const _suppress_warnings = Set{Symbol}([
@@ -736,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
@@ -1181,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")
@@ -1509,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)
@@ -1566,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
@@ -1588,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
+2 -2
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)
@@ -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
+3 -4
View File
@@ -332,7 +332,7 @@ const _gr_attr = merge_with_base_supported([
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
:guidefontrotation, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar, :colorbar_title,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:fill_z, :line_z, :marker_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -386,7 +386,7 @@ const _plotly_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridlinewidth,
:legend, :colorbar, :colorbar_title,
:legend, :colorbar, :colorbar_title, :colorbar_entry,
:marker_z, :fill_z, :line_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -511,7 +511,7 @@ const _pyplot_attr = merge_with_base_supported([
:tickfontfamily, :tickfontsize, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefontcolor,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar,
:legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
@@ -524,7 +524,6 @@ const _pyplot_attr = merge_with_base_supported([
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
:stride,
:framestyle,
:tick_direction,
+327 -128
View File
@@ -79,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))
# --------------------------------------------------------------------------------------
@@ -167,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
@@ -176,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
@@ -236,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...)
@@ -295,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
@@ -414,24 +420,99 @@ 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, levels)
function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
GR.savestate()
xmin, xmax = gr_xy_axislims(sp)[1:2]
zmin, zmax = clims[1:2]
gr_set_viewport_cmap(sp)
l = if levels === nothing
(1000:1255)'
elseif length(levels) > 1
min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels)
round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255)
else
Int32[1000, 1255]
end
GR.setscale(0)
GR.setwindow(xmin, xmax, zmin, zmax)
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
if (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]))
@@ -446,22 +527,46 @@ 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
@@ -479,7 +584,7 @@ end
const _gr_gradient_alpha = ones(256)
function gr_set_gradient(c)
grad = c isa ColorGradient ? c : cgrad()
grad = _as_gradient(c)
for (i,z) in enumerate(range(0, stop=1, length=256))
c = grad[z]
GR.setcolorrep(999+i, red(c), green(c), blue(c))
@@ -488,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()
@@ -560,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})
@@ -581,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] != ""
@@ -661,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][legendi]
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)
@@ -670,7 +897,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
outside_ticks = false
# calculate the colorbar limits once for a subplot
clims = get_clims(sp)
clevels = nothing
cbar = GRColorbar()
draw_axes = sp[:framestyle] != :none
# axes_2d = true
@@ -694,8 +921,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
data_lims = gr_xy_axislims(sp)
end
# color levels overwritten by the last relevant series
hascolorbar(series) && (clevels = colorbar_levels(series, clims))
gr_update_colorbar!(cbar,series)
end
# set our plot area view
@@ -760,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)
@@ -797,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)
@@ -836,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
@@ -846,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
@@ -898,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
@@ -929,26 +1155,29 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_set_font(guidefont(xaxis))
GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide])
else
xticks, yticks = axis_drawing_info(sp)[1:2]
if xaxis[:guide] != ""
h = 0.01 + gr_xaxis_height(sp)
gr_set_font(guidefont(xaxis))
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
gr_text(gr_view_xcenter(), viewport_plotarea[4] + h, xaxis[:guide])
else
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
gr_text(gr_view_xcenter(), viewport_plotarea[3] - h, xaxis[:guide])
end
end
if yaxis[:guide] != ""
w = 0.02 + gr_yaxis_width(sp)
gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
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_subplot[1], gr_view_ycenter(), yaxis[:guide])
gr_text(viewport_plotarea[1] - w, gr_view_ycenter(), yaxis[:guide])
end
end
end
@@ -963,22 +1192,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
st = series[:seriestype]
# update the current stored gradient
if st in (:surface, :heatmap) ||
(st == :contour && series[:fillrange] !== nothing)
gr_set_gradient(series[:fillcolor]) #, series[:fillalpha])
elseif st in (:contour, :wireframe)
gr_set_gradient(series[:linecolor])
elseif series[:marker_z] != nothing
series[:markercolor] = gr_set_gradient(series[:markercolor])
elseif series[:line_z] != nothing
series[:linecolor] = gr_set_gradient(series[:linecolor])
elseif series[:fill_z] != nothing
series[:fillcolor] = gr_set_gradient(series[:fillcolor])
end
gr_set_gradient(series)
GR.savestate()
# update the bounding window
if ispolar(sp)
gr_set_viewport_polar()
@@ -1011,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
@@ -1019,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
@@ -1030,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
@@ -1044,12 +1263,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :contour
GR.setspace(clims[1], clims[2], 0, 90)
h = colorbar_levels(series, clims)
GR.setlinetype(gr_linetype[get_linestyle(series)])
GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001)))
is_lc_black = let black=plot_color(:black)
plot_color(series[:linecolor]) in (black,[black])
end
h = gr_contour_levels(series, clims)
if series[:fillrange] != nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines")
@@ -1105,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
@@ -1177,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
@@ -1219,7 +1441,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
# draw the colorbar
hascolorbar(sp) && gr_colorbar(sp, clims, clevels)
hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims)
# add the legend
if sp[:legend] != :none
@@ -1227,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)
@@ -1260,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
@@ -1345,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
@@ -1389,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)
+7 -3
View File
@@ -171,7 +171,7 @@ function pgf_series(sp::Subplot, series::Series)
elseif st == :shape
shape_data(series)
elseif ispolar(sp)
theta, r = filter_radial_data(plotattributes[:x], plotattributes[:y], axis_limits(sp[:yaxis]))
theta, r = plotattributes[:x], plotattributes[:y]
rad2deg.(theta), r
else
plotattributes[:x], plotattributes[:y]
@@ -399,8 +399,12 @@ function pgf_axis(sp::Subplot, letter)
# framestyle
if framestyle in (:axes, :origin)
axispos = framestyle == :axes ? "left" : "middle"
# the * after lines disables the arrows at the axes
push!(style, string("axis lines* = ", axispos))
if axis[:draw_arrow]
push!(style, string("axis ", letter, " line = ", axispos))
else
# the * after line disables the arrow at the axis
push!(style, string("axis ", letter, " line* = ", axispos))
end
end
if framestyle == :zerolines
+6 -6
View File
@@ -354,7 +354,7 @@ end
function plotly_colorscale(grad::ColorGradient, α)
[[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)]
end
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α)
if length(c) == 1
return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]]
@@ -506,13 +506,13 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showscale] = hascolorbar(sp)
elseif st == :contour
filled = isfilledcontour(series)
plotattributes_out[:type] = "contour"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
# plotattributes_out[:showscale] = series[:colorbar] != :none
plotattributes_out[:ncontours] = series[:levels]
plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
plotattributes_out[:ncontours] = series[:levels] + 2
plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
plotattributes_out[:showscale] = hascolorbar(sp)
plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series)
elseif st in (:surface, :wireframe)
plotattributes_out[:type] = "surface"
@@ -774,7 +774,7 @@ end
function plotly_polar!(plotattributes_out::KW, series::Series)
# convert polar plots x/y to theta/radius
if ispolar(series[:subplot])
theta, r = filter_radial_data(pop!(plotattributes_out, :x), pop!(plotattributes_out, :y), axis_limits(series[:subplot][:yaxis]))
theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
plotattributes_out[:t] = rad2deg.(theta)
plotattributes_out[:r] = r
end
+194 -142
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})
isdefined(PyCall, :_setproperty!) ? plt.o.show() : plot.o[:show]()
end
_display(plt::Plot{PyPlotBackend}) = plt.o."show"()
@@ -1340,16 +1392,16 @@ const _pyplot_mimeformats = Dict(
for (mime, fmt) in _pyplot_mimeformats
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend})
fig = plt.o
fig[:canvas][:print_figure](
fig."canvas"."print_figure"(
io,
format=$fmt,
# bbox_inches = "tight",
# figsize = map(px2inch, plt[:size]),
facecolor = fig[:get_facecolor](),
facecolor = fig."get_facecolor"(),
edgecolor = "none",
dpi = plt[:dpi]
)
end
end
closeall(::PyPlotBackend) = PyPlot.plt[:close]("all")
closeall(::PyPlotBackend) = PyPlot.plt."close"("all")
+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)]
),
+1 -1
View File
@@ -3,7 +3,7 @@ using REPL
function _plots_defaults()
if isdefined(Main, :PLOTS_DEFAULTS)
Main.PLOTS_DEFAULTS::Dict{Symbol,Any}
Dict{Symbol,Any}(Main.PLOTS_DEFAULTS)
else
Dict{Symbol,Any}()
end
+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]
+32 -1
View File
@@ -53,10 +53,41 @@ RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where
# for seriestype `line`, need to sort by x values
const POTENTIAL_VECTOR_ARGUMENTS = [
:seriescolor, :seriesalpha,
:linecolor, :linealpha, :linewidth, :linestyle, :line_z,
:fillcolor, :fillalpha, :fill_z,
:markercolor, :markeralpha, :markershape, :marker_z,
:markerstrokecolor, :markerstrokealpha,
:yerror, :yerror,
:series_annotations, :fillrange
]
@recipe function f(::Type{Val{:line}}, x, y, z)
indices = sortperm(x)
x := x[indices]
y := y[indices]
# sort vector arguments
for arg in POTENTIAL_VECTOR_ARGUMENTS
if typeof(plotattributes[arg]) <: AVec
plotattributes[arg] = _cycle(plotattributes[arg], indices)
end
end
# a tuple as fillrange has to be 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...)
+59 -79
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)
@@ -581,50 +562,49 @@ 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)
end
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
end
# no colorbar if we are creating a surface LightSource
if xor(st == :surface, series[:fill_z] != nothing)
hascbar = true
end
return hascbar
end
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
function hascolorbar(sp::Subplot)
cbar = sp[:colorbar]
hascbar = false
if cbar != :none
for series in series_list(sp)
if hascolorbar(series)
hascbar = true
end
end
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
hascbar
end
function colorbar_levels(series::Series, clims)
if series[:seriestype] == :contour
zmin, zmax = clims
levels = series[:levels]
levels isa AbstractArray ?
levels :
levels > 1 ?
range(zmin, stop=zmax, length=levels) :
[(zmin + zmax) / 2]
else # including heatmap, surface
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
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
levels
end
for comp in (:line, :fill, :marker)
@@ -812,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?!?
+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
+6 -114
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,14 +22,6 @@ img_tol = isinteractive() ? 1e-2 : 10e-2
end
end
# @static if isinteractive()
# @testset "PyPlot" begin
# @test pyplot() == Plots.PyPlotBackend()
# @test backend() == Plots.PyPlotBackend()
#
# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31])
# end
# end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@@ -41,68 +36,6 @@ end
@test isa(display(p), Nothing) == true
end
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# @static if isinteractive()
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# image_comparison_facts(:plotlyjs,
# skip=[
# 2, # animation (skipped for speed)
# 25,
# 27, # (polar plots) takes very long / not working
# 30,
# 31, # animation (skipped for speed)
# ],
# tol=img_tol)
# end
# end
# InspectDR returns that error on travis:
# ERROR: LoadError: InitError: Cannot open display:
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
# @testset "InspectDR" begin
# @test inspectdr() == Plots.InspectDRBackend()
# @test backend() == Plots.InspectDRBackend()
#
# image_comparison_facts(:inspectdr,
# skip=[
# 2, # animation
# 6, # heatmap not defined
# 10, # heatmap not defined
# 22, # contour not defined
# 23, # pie not defined
# 27, # polar plot not working
# 28, # heatmap not defined
# 31, # animation
# ],
# tol=img_tol)
# end
# @testset "Plotly" begin
# @test plotly() == Plots.PlotlyBackend()
# @test backend() == Plots.PlotlyBackend()
#
# # # until png generation is reliable on OSX, just test on linux
# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol)
# end
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# # as long as we can plot anything without error, it should be the same as Plotly
# image_comparison_facts(:plotlyjs, only=[1], tol=img_tol)
# end
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@@ -120,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`)