Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ea5a5ac0b | |||
| bc8370eadd | |||
| cdc5a2b361 | |||
| 4270ac80fb | |||
| 405df5da8b | |||
| f742ae4c88 | |||
| a99783dfa0 | |||
| 9af5edd04d | |||
| d0830b90be | |||
| 8cd48bc660 | |||
| 379a320d2d | |||
| d5f3a3ef69 | |||
| a3be970f29 | |||
| 63f8f52c9f | |||
| 169851564c | |||
| c32b9029d1 | |||
| 3fe60b9d18 | |||
| 34cff752f1 | |||
| 0dba83daf6 | |||
| c399092261 | |||
| dcabb2c579 | |||
| 3542785021 | |||
| 65173e6dd2 | |||
| bf0bb68e28 | |||
| 21774dc36b | |||
| 0e3a9f0b8f | |||
| 903cb404c3 | |||
| 03325533bf | |||
| 710123aab4 | |||
| 4742ec972b | |||
| e860ba220a | |||
| 39605bccc2 | |||
| 1a4f411b8f | |||
| a6588daa3e | |||
| b053366b06 | |||
| e838ac502d | |||
| 6131154dd0 | |||
| 0c67a61e7d | |||
| 72696a4326 | |||
| 3231f4d9b1 | |||
| 8a81b398cf | |||
| a37a1a0004 | |||
| b6b00c843a | |||
| 5506c0543c | |||
| 7a1b48311c | |||
| 0b3dafcd18 | |||
| 81f6b3c7bd | |||
| c2da4acb48 | |||
| 841b05631d | |||
| a6e60aea04 | |||
| 7f2a1db64a | |||
| 926ccdf618 | |||
| 9774eca8e2 | |||
| 2ad033f8e2 | |||
| 7c26ffee51 | |||
| aa37ba0463 | |||
| d61c86b54b | |||
| e72fa1dc74 | |||
| 16db531cce | |||
| 226023043b | |||
| 5d2538c4c2 | |||
| 0075103ddf | |||
| 8982a67902 | |||
| 65ab45ff1b | |||
| 577d434bc8 | |||
| b300e634f6 | |||
| 61d13b9b2d | |||
| 78059bf825 | |||
| dd02a69e8f | |||
| 5ec80ad1f1 | |||
| 4849772435 | |||
| 6546879d3a | |||
| cbc379daa9 | |||
| a7be08ef46 | |||
| 47e48e5d27 | |||
| 968b8109dd | |||
| 19fba27951 | |||
| b78da20d04 | |||
| 5e445b4a71 | |||
| 0e5df883d0 | |||
| b79ea119ea | |||
| b21d98affd |
@@ -7,3 +7,4 @@ examples/meetup/.ipynb_checkpoints/*
|
||||
deps/plotly-latest.min.js
|
||||
deps/build.log
|
||||
deps/deps.jl
|
||||
Manifest.toml
|
||||
|
||||
+5
-45
@@ -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())'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"]
|
||||
@@ -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
@@ -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...)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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?!?
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
reference_images
|
||||
@@ -1,10 +0,0 @@
|
||||
StatsPlots
|
||||
Images
|
||||
ImageMagick
|
||||
@osx QuartzImageIO
|
||||
FileIO
|
||||
GR 0.31.0
|
||||
RDatasets
|
||||
VisualRegressionTests
|
||||
UnicodePlots
|
||||
LaTeXStrings
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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`)
|
||||
Reference in New Issue
Block a user