Compare commits

...

90 Commits

Author SHA1 Message Date
Simon Christ 138589bb61 1.24.1 [skip ci] 2021-11-25 14:38:34 +01:00
Simon Christ c2af71756e add missing get_clims in GR (#3950) 2021-11-25 14:34:15 +01:00
Simon Christ c1e88d0360 1.24.0 [skip ci] 2021-11-25 12:17:23 +01:00
github-actions[bot] e0ea601239 Update precompile_*.jl file [skip ci] (#3949)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-25 12:15:50 +01:00
Simon Christ e471ce8d28 rework layout macro to use Base types (#3943)
* @layout -> Base types except for `grid` call

* add layout conversion of namedtuples, vectors and matrices

* add missing method

* rip it out

* fix slicing

* adjust compat

* add Measure conversion
2021-11-25 11:40:25 +01:00
Simon Christ 1bdec476c3 add missing docstrings 2021-11-25 10:23:44 +01:00
github-actions[bot] b23c620d77 Format .jl files [skip ci] (#3941)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-11-15 09:56:31 +01:00
Simon Christ 21c3ac4c45 1.23.6 [skip ci] 2021-11-11 10:30:39 +01:00
github-actions[bot] 861f537736 Update precompile_*.jl file [skip ci] (#3939)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-11 10:27:14 +01:00
Simon Christ e9ae75dfa4 Fix setting of legend font via legend_font (#3934)
* find pipeline spot

* better spot

* construct font

* set font and matching

* respect defaults
2021-11-11 09:48:29 +01:00
github-actions[bot] 07bcecd47c Update precompile_*.jl file [skip ci] (#3937)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-10 21:18:39 +01:00
Simon Christ af3ebe9936 split looops (#3931) 2021-11-10 20:34:49 +01:00
github-actions[bot] 9d3ce54c37 Format .jl files [skip ci] (#3927)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-11-09 16:13:21 +01:00
Josef Heinen 6df1f38492 gr: fix text problems 2021-11-03 14:43:06 +01:00
Simon Christ c4b7757e22 1.23.4 [skip ci] 2021-11-03 10:53:01 +01:00
t-bltg d1309c6c7b Fix LaTeXStrings support for UnicodePlots and InspectDR (#3879)
* fix LaTeXStrings support for UnicodePlots and InspectDR

* rename & fix
2021-11-03 09:22:37 +01:00
github-actions[bot] 58ed4a60de Update precompile_*.jl file [skip ci] (#3919)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-02 20:39:32 +01:00
Lukas Hauertmann 70dec42308 Add :log10-colorbar_scale support in GR (#3915)
* Add `:log10`-`colorbar_scale` support in GR

* Change `clims` behaviour (gr heatmap)
2021-11-02 19:08:10 +01:00
Simon Christ fdbd2c397c GR compat and 1.23.3 [skip ci] 2021-11-02 13:46:23 +01:00
github-actions[bot] c337f15e18 Update precompile_*.jl file [skip ci] (#3916)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-01 14:16:28 +01:00
Simon Christ 1fe9a9f536 update gaston backend 2021-11-01 13:52:03 +01:00
github-actions[bot] 41cf64b400 Format .jl files [skip ci] (#3914)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-11-01 12:46:08 +01:00
Josef Heinen 19b70c06ff Update gr.jl
Use new text functionality. GR v0.62+ can handle multiline strings and inline math expressions.
2021-10-29 15:22:37 +02:00
Josef Heinen 40fe8eed9a Update Project.toml
add GR v0.62.0
2021-10-29 13:33:04 +02:00
Simon Christ 4b94384c7d support axis flip (#3908) 2021-10-29 12:01:07 +02:00
Simon Christ 35e96a5302 1.23.2 [skip ci] 2021-10-28 16:13:37 +02:00
Simon Christ e84905c2a0 detect aliases in recipes (#3904)
* detect aliases in recipes

* remove doubled tests
2021-10-28 16:12:59 +02:00
Simon Christ 1c621feacc 1.23.1 [skip ci] 2021-10-26 09:17:12 +02:00
Simon Christ e8356965e9 fix pyplot backend 2021-10-26 09:15:46 +02:00
Nicholas Bauer 72428000cc Moved clims into plot/series attributes (#3897)
* Moved limits into plot/series attributes

* Moved const to args
2021-10-26 09:09:23 +02:00
Simon Christ d9116d577f 1.23.0 [skip ci] 2021-10-25 15:02:58 +02:00
github-actions[bot] 96dbd07627 Update precompile_*.jl file [skip ci] (#3889)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-10-25 09:00:09 +02:00
github-actions[bot] 804fab45ad Format .jl files [skip ci] (#3896)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-10-25 08:57:08 +02:00
Simon Christ 2e67e84361 Legend overhaul including horizontal legends (#2854)
* prototype

* use add_attributes macro with modification

* add Colors back

* fix convertLegendValue

* fix legendtitlefontsize

* fix gr legend position

* fix aliases

* symbolic color is okay

* remove redundant legend_forground_color aliases

* legend -> legend_postion

* fix inspectdr

* add legendtitlefont pointsize and color

* fix symbol cache

* fix rebase woes

* Update precompile_*.jl file [skip ci] (#3885)

Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>

* fix gr

* more fixes

* add match_table to `@add_attributes`

* fix match_map

* Update src/backends/pgfplotsx.jl

Co-authored-by: t-bltg <tf.bltg@gmail.com>

* fix font calls

* apply formatter

* readd descriptions

* more missing descriptions

* adjust pyplot to master

* fix pgfplotsx

* Revert "Merge branch 'bbs/horizontal-legends' of https://github.com/JuliaPlots/Plots.jl into bbs/horizontal-legends"

This reverts commit d880d89ef6.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
Co-authored-by: t-bltg <tf.bltg@gmail.com>
2021-10-22 15:09:14 +02:00
Simon Christ b298711379 1.22.7 [skip ci] 2021-10-22 15:04:30 +02:00
t-bltg bacf2d2f06 Update SnoopCompile.yml 2021-10-20 13:47:07 +02:00
t-bltg bb9cd718a5 Fix formatting src/precompile_includer.jl 2021-10-20 13:08:56 +02:00
Simon Christ 0af22a8fe6 fix name [skip ci] 2021-10-20 10:59:59 +02:00
Yuval 3b0950f915 Fix vector attributes to bar plots (#3751) 2021-10-19 21:21:20 +02:00
github-actions[bot] 31d3bf3e06 Format .jl files [skip ci] (#3882)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-10-18 09:39:08 +02:00
Simon Christ c487a10f79 use codecov-action v2 2021-10-13 17:23:39 +02:00
github-actions[bot] ef3417617c Update precompile_*.jl file [skip ci] (#3876)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-10-13 13:06:08 +02:00
Simon Christ 0d2d516ca6 1.22.6 [skip ci] 2021-10-13 11:37:48 +02:00
Lukas Hauertmann 12a1d83595 Use GR.polygonmesh3d for :mesh3d seriestype (#3868)
* Use `GR.polygonmesh3d` for `:mesh3d` seriestype

* Remove unecessary code

* Update GR version dependency

* Add drawing of edges in `:mesh3d` with GR
2021-10-13 11:35:06 +02:00
Simon Christ 9eba5964d9 1.22.5 [skip ci] 2021-10-12 20:18:58 +02:00
Nicholas Bauer d74ee63710 Fix for regression with colorbar limits (#3874)
* Fix for regression

* Remove call

* Refactored to dispatching

* Fixes

* Unrolling loop

* Change to IdDict in case objects mutated
2021-10-12 20:18:12 +02:00
github-actions[bot] 9941563b0b Update precompile_*.jl file [skip ci] (#3849)
Co-authored-by: isentropic <isentropic@users.noreply.github.com>
2021-10-11 17:18:56 +02:00
github-actions[bot] fb82722dd3 Format .jl files [skip ci] (#3872)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-10-11 17:18:02 +02:00
Jack Dunn 86a9b8bf6d Fix PyCall deprecations (#3864)
Fixes #3818
2021-10-11 18:55:52 +09:00
Josef Heinen 5a19673eaf Update Project.toml 2021-10-09 09:04:26 +02:00
Josef Heinen c26561eab3 Update Project.toml
Bump GR version
2021-10-06 20:51:21 +02:00
Simon Christ f0ad66da36 1.22.4 [skip ci] 2021-10-05 19:25:45 +02:00
Nicholas Bauer aca2aa49b8 Generalize GR tick label rotations (#3782)
* gr tick rotations

* consistency

* start of angle offset work

* Working!

* simplify logic

* gr tick rotations

* consistency

* start of angle offset work

* Working!

* simplify logic

* all offsets

* Rebase

* tick factor reversion

* Fix for 3d plots

* simplification

* offset update

* bump offset

* Remove conflict error

* Resolve merge conflict error.

* Resolve merge conflict error

* 3d done

* remove excess

* adjust offset

* restore offset

* fix sign check

Co-authored-by: t-bltg <tf.bltg@gmail.com>
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-10-05 13:44:12 +02:00
t-bltg 9d56e72f6a Update .zenodo.json
Fix broken .json
2021-10-05 09:43:40 +02:00
Lee Phillips f06225655d Allow styling of magnification shape in lens!() (#3860)
* Allow styling of magnification shape in lens!()

The guide lines that indicate the region of the plot magnified in the
inset lens plot, called the magnification shape, are hard-coded with
the :lightgray color and are drawn with the default other line
attributes. This is often too light to be seen clearly and could be a
problem for publication. This commit allows the user to set the
linecolor, linewidth, and linestyle in the call to lens!().

* Update src/recipes.jl

Co-authored-by: t-bltg <tf.bltg@gmail.com>

* Update .zenodo.json

Co-authored-by: t-bltg <tf.bltg@gmail.com>
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-10-04 17:38:59 +02:00
github-actions[bot] 4f0f84f400 Format .jl files [skip ci] (#3861)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-10-04 13:23:01 +02:00
Jan Schneider a65cda8b7e change docs link to httpS (#3852)
always bugs me to get a warning from my browser about the not secure connection.
Could someone also update the About section at the right of the Github page to a https URL?
2021-09-28 16:15:26 +02:00
Simon Christ 37744d7b6a 1.22.3 [skip ci] 2021-09-27 19:24:47 +02:00
Jan Schneider 09a66224ce Update Plots.jl's colorbar_titel maps to PGFPlotsX's color bar style={ylabel} (#3848)
* Update PGFPlotsX colorbar_titel map to ylabel

For most of the backends supported by Polts.jl the `colorbar_title` attribute maps to the attribute in the backend that ultimately is displayed on the vertical axis of the colorbar, which is vertically aligned. Not for PGFPlotsX as in this backend the `title` attribute is displayed on top of the colorbar while the `ylabel` is shown on the vertical bar.

* Update .zenodo.json

added my name to the contributors list
2021-09-27 16:16:16 +02:00
Nicholas Bauer 405bc0820b Speed up get_clims (#3839)
* For Shape type, cut off process

* Remove fillcolor for now

* Address type inference failure instead

* Store value instead of re-evaluating

* Works, but not ideal

* Unnecessary to update here, I think

* return type

* Remove unnecessary default arg

* Typo

* Change to clims

* missed one

* reconfigured to free up clims property

* fix

* Remove debug println, add hook for updating clims after series added

* restore docstring

* typo

* Change to _update_subplot_colorbars
2021-09-27 14:01:18 +02:00
github-actions[bot] 1c89bd8727 Update precompile_*.jl file [skip ci] (#3841)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-26 15:44:10 +02:00
github-actions[bot] 8e17a182f9 Format .jl files [skip ci] (#3846)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-26 15:42:31 +02:00
t-bltg 032c5d1638 UnicodePlots: support markers (#3845) 2021-09-25 12:18:41 +02:00
BerndR 8d95333d1e Legend positioning for 3d plots in plotly (#3840)
* Remove hardoced numbers, shift for 3d plots

* Revert changes

* Fixed some missed reverts
2021-09-23 19:14:55 +02:00
github-actions[bot] 7bfc97285c Update precompile_*.jl file [skip ci] (#3828)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-09-23 10:26:58 +02:00
Simon Christ acca707f34 1.22.2 [skip ci] 2021-09-22 21:21:13 +02:00
Nicholas Bauer 6fa3dae166 Fix type inference failure in get_clims (#3838)
* For Shape type, cut off process

* Remove fillcolor for now

* NaN

* Address type inference failure instead
2021-09-22 19:18:57 +02:00
Lukas Hauertmann 866cb0c335 Add :mesh3d seriesstyle for PyPlot backend (#3835)
* Add `:mesh3d` seriesstyle for PyPlot backend

via `Poly3DCollection`.

* Add `:connections` to lists of supported keywords

for the backends which support `:mesh3d` as series type.

* Remove #47 from list of skipping examples for PyPlot

* Add support for only-triangle syntax for `:connections` kw

for PyPlot

* Add 1-based indexing syntax for `connections` kw in `:mesh3d`

* Update description for example `#47` (`:mesh3d`)

* Hotfix 1-based indexing for mesh3d in pgfplotsx
2021-09-22 17:12:11 +02:00
t-bltg 4d40bae9cc Update bug.md
update supported backends
2021-09-21 00:28:51 +02:00
github-actions[bot] 5a48002d31 Format .jl files [skip ci] (#3829)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-20 16:10:29 +02:00
t-bltg 0cd81243ad UnicodePlots: compact plots 2021-09-18 14:13:37 +02:00
t-bltg ed3bab0e6f 1.22.1 [skip ci] 2021-09-17 22:11:50 +02:00
github-actions[bot] 4621c18b23 Update precompile_*.jl file [skip ci] (#3822)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-17 22:10:48 +02:00
BerndR 4f8a265c6a Fix generic aliases (#3824) 2021-09-17 21:43:26 +02:00
t-bltg e2539a3d19 UnicodePlots: adjust layout width per column (#3825) 2021-09-17 21:42:50 +02:00
t-bltg 85739932f0 Negate condition on :warn_on_unsupported (#3816) 2021-09-17 14:55:43 +02:00
t-bltg 9d84e53bcb Test cleanup (#3821) 2021-09-17 12:00:40 +02:00
zhanibek 82f31c48b7 pyplot fixing ticks=:native 2021-09-17 16:30:22 +09:00
zhanibek 81571fe534 fix typos 2021-09-17 14:44:16 +09:00
zhanibek 293b8b112e instructions for matplotlib update 2021-09-17 14:38:24 +09:00
t-bltg d988d4c9d1 1.22.0 [skip ci] 2021-09-15 12:54:42 +02:00
github-actions[bot] 85bd3ea53f Update precompile_*.jl file [skip ci] (#3810)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-15 12:53:58 +02:00
t-bltg cd6a8c87b6 GR: fix NaN tick size (#3813) 2021-09-15 12:28:53 +02:00
t-bltg 175c87cec6 Avoid Vararg usage (#3809) 2021-09-15 12:28:24 +02:00
t-bltg c3f45dd712 UnicodePlots: minor fixes (#3812) 2021-09-15 11:21:41 +02:00
t-bltg 198a59b621 UnicodePlots: propagate xyscale (#3811) 2021-09-15 01:29:23 +02:00
t-bltg c5d7283473 Update examples.jl
UnicodePlots: annotations are supported
2021-09-14 21:02:30 +02:00
t-bltg 7a1bc88f66 Use hyphens to specify version ranges 2021-09-14 20:27:44 +02:00
github-actions[bot] ad5cd2f1da Update precompile_*.jl file [skip ci] (#3807)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-14 19:01:40 +02:00
t-bltg 6cf01229bb UnicodePlots: support :annotations (#3804) 2021-09-14 18:46:46 +02:00
32 changed files with 1452 additions and 905 deletions
+2 -1
View File
@@ -20,10 +20,11 @@ Backend | yes | no | untested
-------------|-----|-----|---------
gr (default) | | |
pyplot | | |
plotly | | |
plotlyjs | | |
pgfplotsx | | |
unicodeplots | | |
inspectdr | | |
gaston | | |
### Versions
+5 -1
View File
@@ -69,7 +69,11 @@ jobs:
uses: actions/download-artifact@v2
- name: CompileBot postprocess
run: julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();'
run: |
ls artifact
ls
if ! grep -m1 -q 'format' artifact/src/precompile_includer.jl; then sed -i '1 i\#! format: off' artifact/src/precompile_includer.jl; fi
julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
+1 -1
View File
@@ -78,7 +78,7 @@ jobs:
# Codecov
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v2
with:
file: lcov.info
+11 -1
View File
@@ -401,7 +401,7 @@
"type": "Other"
},
{
"name": "Moesè Giodano",
"name": "Mosè Giodano",
"type": "Other"
},
{
@@ -692,6 +692,16 @@
{
"name": "Fred Callaway",
"type": "Other"
},
{
"name": "Jan Thorben Schneider",
"type": "Other"
},
{
"orcid": "0000-0003-4102-2460",
"affiliation": "Alogus Research Corporation",
"name": "Lee Phillips",
"type": "Other"
}
],
"upload_type": "software"
+12 -9
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.21.3"
version = "1.24.1"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@@ -31,31 +31,34 @@ Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
UnicodeFun = "1cfade01-22cf-5700-b092-accc4b62d6e1"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
Contour = "0.5"
FFMPEG = "0.2, 0.3, 0.4"
FixedPointNumbers = "0.6, 0.7, 0.8"
GR = "0.53, 0.54, 0.55, 0.57, 0.58, 0.59"
FFMPEG = "0.2 - 0.4"
FixedPointNumbers = "0.6 - 0.8"
GR = "0.62.1"
GeometryBasics = "0.2, 0.3.1, 0.4"
JSON = "0.21, 1"
Latexify = "0.14, 0.15"
Latexify = "0.14 - 0.15"
Measures = "0.3"
NaNMath = "0.3"
PlotThemes = "2"
PlotUtils = "1"
RecipesBase = "1"
RecipesBase = "1.2"
RecipesPipeline = "0.3.5, 0.4"
Reexport = "0.2, 1.0"
Requires = "1"
Scratch = "1"
Showoff = "0.3.1, 1.0"
StatsBase = "0.32, 0.33"
UnicodePlots = "2.2"
StatsBase = "0.32 - 0.33"
UnicodeFun = "0.4"
UnicodePlots = "2.4"
julia = "1.5"
[extras]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
@@ -76,4 +79,4 @@ UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
[targets]
test = ["Distributions", "FileIO", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"]
test = ["Colors", "Distributions", "FileIO", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"]
+1 -1
View File
@@ -10,7 +10,7 @@
[gitter-url]: https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[docs-img]: https://img.shields.io/badge/docs-stable-blue.svg
[docs-url]: http://docs.juliaplots.org/latest/
[docs-url]: https://docs.juliaplots.org/latest/
[![][gh-ci-img]][gh-ci-url]
[![][pkgeval-img]][pkgeval-url]
+27 -58
View File
@@ -66,8 +66,6 @@ end
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:label, :blank), Tuple{Symbol, Bool}},Type{EmptyLayout}})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:label, :width, :height), Tuple{Symbol, Symbol, Length{:pct, Float64}}},Type{EmptyLayout}})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:parent,), Tuple{GridLayout}},Type{Subplot},GRBackend})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:parent,), Tuple{GridLayout}},Type{Subplot},PlotlyBackend})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:parent,), Tuple{Subplot{GRBackend}}},Type{Subplot},GRBackend})
@@ -76,28 +74,20 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}, Vector{Float64}},Tuple{Int64, Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}},Symbol})
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Vector{Int64}}},typeof(_make_hist),Tuple{Vector{Float64}},Symbol})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:flip,), Tuple{Bool}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:formatter,), Tuple{Symbol}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:formatter,), Tuple{typeof(datetimeformatter)}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid, :flip, :minorgrid, :guide), Tuple{Bool, Bool, Bool, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid, :lims), Tuple{Bool, Tuple{Float64, Float64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid, :lims, :flip), Tuple{Bool, Tuple{Float64, Float64}, Bool}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid, :minorgrid, :guide), Tuple{Bool, Bool, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid, :minorgrid, :mirror, :guide), Tuple{Bool, Bool, Bool, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:grid,), Tuple{Bool}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:gridlinewidth, :grid, :gridalpha, :gridstyle, :foreground_color_grid), Tuple{Int64, Bool, Float64, Symbol, RGBA{Float64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:guide,), Tuple{String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:guide_position, :guidefontvalign, :mirror, :guide), Tuple{Symbol, Symbol, Bool, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:guidefonthalign, :guide_position, :mirror, :guide), Tuple{Symbol, Symbol, Bool, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:lims, :flip, :ticks, :guide), Tuple{Tuple{Int64, Int64}, Bool, StepRange{Int64, Int64}, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:lims,), Tuple{Tuple{Float64, Float64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:lims,), Tuple{Tuple{Int64, Float64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:lims,), Tuple{Tuple{Int64, Int64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:minorgrid, :scale, :guide), Tuple{Bool, Symbol, String}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:minorgrid,), Tuple{Bool}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:rotation,), Tuple{Int64}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:ticks,), Tuple{Nothing}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:ticks,), Tuple{UnitRange{Int64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(default)),NamedTuple{(:shape,), Tuple{Symbol}},typeof(default)})
Base.precompile(Tuple{Core.kwftype(typeof(default)),NamedTuple{(:titlefont, :legendfontsize, :guidefont, :tickfont, :guide, :framestyle, :yminorgrid), Tuple{Tuple{Int64, String}, Int64, Tuple{Int64, Symbol}, Tuple{Int64, Symbol}, String, Symbol, Bool}},typeof(default)})
Base.precompile(Tuple{Core.kwftype(typeof(font)),NamedTuple{(:family, :pointsize, :halign, :valign, :rotation, :color), Tuple{String, Int64, Symbol, Symbol, Float64, RGBA{Float64}}},typeof(font)})
@@ -107,13 +97,11 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),UnitRange{Int64},UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),UnitRange{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),Vector{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_set_font)),NamedTuple{(:halign, :valign, :rotation), Tuple{Symbol, Symbol, Int64}},typeof(gr_set_font),Font,Subplot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(hline!)),Any,typeof(hline!),Any})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :seriestype), Tuple{Float64, Symbol}},typeof(plot!),Plot{GRBackend},Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :seriestype), Tuple{Float64, Symbol}},typeof(plot!),Plot{PlotlyBackend},Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :seriestype), Tuple{Float64, Symbol}},typeof(plot!),Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:annotation,), Tuple{Vector{Tuple{Int64, Float64, Tuple{String, Any, Any, Any}}}}},typeof(plot!)})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:layout, :margin), Tuple{GridLayout, AbsoluteLength}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:layout, :margin), Tuple{Matrix{Any}, AbsoluteLength}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
@@ -126,48 +114,42 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),Plot{GRBackend},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),Plot{PlotlyBackend},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:markersize, :c, :seriestype), Tuple{Int64, Symbol, Symbol}},typeof(plot!),Plot{GRBackend},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:markersize, :c, :seriestype), Tuple{Int64, Symbol, Symbol}},typeof(plot!),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype, :inset), Tuple{Symbol, Tuple{Int64, BoundingBox{Tuple{Length{:w, Float64}, Length{:h, Float64}}, Tuple{Length{:w, Float64}, Length{:h, Float64}}}}}},typeof(plot!),Plot{GRBackend},Vector{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype, :inset), Tuple{Symbol, Tuple{Int64, BoundingBox{Tuple{Length{:w, Float64}, Length{:h, Float64}}, Tuple{Length{:w, Float64}, Length{:h, Float64}}}}}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype, :inset), Tuple{Symbol, Tuple{Int64, BoundingBox{Tuple{Length{:w, Float64}, Length{:h, Float64}}, Tuple{Length{:w, Float64}, Length{:h, Float64}}}}}},typeof(plot!),Vector{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot!),Plot{GRBackend},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot!),Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:title,), Tuple{String}},typeof(plot!),Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:title,), Tuple{String}},typeof(plot!),Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:title,), Tuple{String}},typeof(plot!)})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:w,), Tuple{Int64}},typeof(plot!),Plot{GRBackend},Vector{Float64},Vector{Float64},Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:xgrid,), Tuple{Tuple{Symbol, Symbol, Int64, Symbol, Float64}}},typeof(plot!),Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:yaxis, :minorgrid), Tuple{Tuple{String, Symbol}, Bool}},typeof(plot!),Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:yaxis, :minorgrid), Tuple{Tuple{String, Symbol}, Bool}},typeof(plot!)})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:zcolor, :m, :ms, :lab, :seriestype), Tuple{Vector{Float64}, Tuple{Symbol, Float64, Stroke}, Vector{Float64}, String, Symbol}},typeof(plot!),Plot{GRBackend},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:zcolor, :m, :ms, :lab, :seriestype), Tuple{Vector{Float64}, Tuple{Symbol, Float64, Stroke}, Vector{Float64}, String, Symbol}},typeof(plot!),Plot{PlotlyBackend},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:zcolor, :m, :ms, :lab, :seriestype), Tuple{Vector{Float64}, Tuple{Symbol, Float64, Stroke}, Vector{Float64}, String, Symbol}},typeof(plot!),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:annotations, :leg), Tuple{Tuple{Int64, Float64, PlotText}, Bool}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:arrow,), Tuple{Int64}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:aspect_ratio, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{String},Vector{String},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:bar_width, :alpha, :color, :fillto, :label, :seriestype), Tuple{Float64, Float64, Vector{Symbol}, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, String, Symbol}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:bins, :weights, :seriestype), Tuple{Symbol, Vector{Int64}, Symbol}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:color, :line, :marker), Tuple{Matrix{Symbol}, Tuple{Symbol, Int64}, Tuple{Matrix{Symbol}, Int64, Float64, Stroke}}},typeof(plot),Vector{Vector{T} where T}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:connections, :title, :xlabel, :ylabel, :zlabel, :legend, :margin, :seriestype), Tuple{Tuple{Vector{Int64}, Vector{Int64}, Vector{Int64}}, String, String, String, String, Symbol, AbsoluteLength, Symbol}},typeof(plot),Vector{Int64},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:fill, :seriestype), Tuple{Bool, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:fill_z, :alpha, :label, :bar_width, :seriestype), Tuple{StepRange{Int64, Int64}, Vector{Float64}, String, UnitRange{Int64}, Symbol}},typeof(plot),Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:framestyle, :title, :color, :layout, :label, :markerstrokewidth, :ticks, :seriestype), Tuple{Matrix{Symbol}, Matrix{String}, Base.ReshapedArray{Int64, 2, UnitRange{Int64}, Tuple{}}, Int64, String, Int64, UnitRange{Int64}, Symbol}},typeof(plot),Vector{Vector{Float64}},Vector{Vector{Float64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:grid, :title), Tuple{Tuple{Symbol, Symbol, Symbol, Int64, Float64}, String}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:lab, :w, :palette, :fill, :α), Tuple{String, Int64, PlotUtils.ContinuousColorGradient, Int64, Float64}},typeof(plot),StepRange{Int64, Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:label, :title, :xlabel, :linewidth, :legend), Tuple{Matrix{String}, String, String, Int64, Symbol}},typeof(plot),Vector{Function},Float64,Float64})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:label,), Tuple{Matrix{String}}},typeof(plot),Vector{AbstractVector{Float64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:labels,), Tuple{Matrix{String}}},typeof(plot),PortfolioComposition})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :group, :linetype, :linecolor), Tuple{GridLayout, Vector{String}, Matrix{Symbol}, Symbol}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :group, :linetype, :linecolor), Tuple{Matrix{Any}, Vector{String}, Matrix{Symbol}, Symbol}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :label, :fillrange, :fillalpha), Tuple{Tuple{Int64, Int64}, String, Int64, Float64}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :label, :fillrange, :fillalpha), Tuple{Tuple{Int64, Int64}, String, Int64, Float64}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :link), Tuple{Int64, Symbol}},typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :link), Tuple{Int64, Symbol}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :margin), Tuple{GridLayout, AbsoluteLength}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :margin), Tuple{Matrix{Any}, AbsoluteLength}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :palette, :bg_inside), Tuple{Int64, Matrix{PlotUtils.ContinuousColorGradient}, Matrix{Symbol}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :t, :leg, :ticks, :border), Tuple{GridLayout, Matrix{Symbol}, Bool, Nothing, Symbol}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :title, :titlelocation, :left_margin, :bottom_margin, :xrotation), Tuple{GridLayout, Matrix{String}, Symbol, Matrix{AbsoluteLength}, AbsoluteLength, Int64}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :t, :leg, :ticks, :border), Tuple{Matrix{Any}, Matrix{Symbol}, Bool, Nothing, Symbol}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :title, :titlelocation, :left_margin, :bottom_margin, :xrotation), Tuple{Matrix{Any}, Matrix{String}, Symbol, Matrix{AbsoluteLength}, AbsoluteLength, Int64}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :xguide, :yguide, :xguidefonthalign, :yguidefontvalign, :xguideposition, :yguideposition, :ymirror, :xmirror, :legend, :seriestype), Tuple{Int64, String, String, Matrix{Symbol}, Matrix{Symbol}, Symbol, Matrix{Symbol}, Matrix{Bool}, Matrix{Bool}, Bool, Matrix{Symbol}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :xlims), Tuple{GridLayout, Tuple{Int64, Float64}}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :xlims), Tuple{Matrix{Any}, Tuple{Int64, Float64}}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout,), Tuple{Tuple{Int64, Int64}}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout,), Tuple{Tuple{Int64, Int64}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
@@ -191,7 +173,6 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:projection, :seriestype), Tuple{Symbol, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},UnitRange{Int64},Matrix{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:quiver, :seriestype), Tuple{Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:reg, :fill), Tuple{Bool, Tuple{Int64, Symbol}}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{Int64}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{Tuple{LinRange{Float64}, LinRange{Float64}}}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{typeof(sqrt)}},typeof(plot),UnitRange{Int64}})
@@ -211,12 +192,11 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:zcolor, :m, :leg, :cbar, :w), Tuple{StepRange{Int64, Int64}, Tuple{Int64, Float64, Symbol, Stroke}, Bool, Bool, Int64}},typeof(plot),Vector{Float64},Vector{Float64},UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(portfoliocomposition)),Any,typeof(portfoliocomposition),Any,Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(scatter!)),Any,typeof(scatter!),Any})
Base.precompile(Tuple{Core.kwftype(typeof(test_examples)),NamedTuple{(:skip, :disp), Tuple{Vector{Int64}, Bool}},typeof(test_examples),Symbol})
Base.precompile(Tuple{Core.kwftype(typeof(test_examples)),NamedTuple{(:skip,), Tuple{Vector{Int64}}},typeof(test_examples),Symbol})
Base.precompile(Tuple{Type{GridLayout},Int64,Vararg{Int64, N} where N})
Base.precompile(Tuple{Type{NaNSegmentsIterator},Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Vector{Float64}},Int64,Int64})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{OHLC}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},PortfolioComposition})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:barbins}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:barhist}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:bar}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:bins2d}},Any,Any,Any})
@@ -237,20 +217,13 @@ function _precompile_()
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_attributes!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.process_userrecipe!),Plot{GRBackend},Vector{Dict{Symbol, Any}},Dict{Symbol, Any}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_userrecipe!),Plot{PlotlyBackend},Vector{Dict{Symbol, Any}},Dict{Symbol, Any}})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{GRBackend},DefaultsDict,Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{GRBackend},Dict{Symbol, Any},Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{PlotlyBackend},DefaultsDict,Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{PlotlyBackend},Dict{Symbol, Any},Symbol,Any})
Base.precompile(Tuple{typeof(_bin_centers),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Float64},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Int64},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Nothing},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{PlotUtils.ContinuousColorGradient},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Symbol},String})
Base.precompile(Tuple{typeof(_cycle),Base.OneTo{Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),StepRange{Int64, Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},UnitRange{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},Vector{Int64}})
Base.precompile(Tuple{typeof(_do_plot_show),Plot{GRBackend},Bool})
Base.precompile(Tuple{typeof(_do_plot_show),Plot{PlotlyBackend},Bool})
Base.precompile(Tuple{typeof(_heatmap_edges),Vector{Float64},Bool,Bool})
@@ -260,6 +233,8 @@ function _precompile_()
Base.precompile(Tuple{typeof(_update_min_padding!),GridLayout})
Base.precompile(Tuple{typeof(_update_subplot_args),Plot{GRBackend},Subplot{GRBackend},Dict{Symbol, Any},Int64,Bool})
Base.precompile(Tuple{typeof(_update_subplot_args),Plot{PlotlyBackend},Subplot{PlotlyBackend},Dict{Symbol, Any},Int64,Bool})
Base.precompile(Tuple{typeof(_update_subplot_legend),Subplot{GRBackend},Dict{Symbol, Any}})
Base.precompile(Tuple{typeof(_update_subplot_legend),Subplot{PlotlyBackend},Dict{Symbol, Any}})
Base.precompile(Tuple{typeof(_update_subplot_periphery),Subplot{GRBackend},Vector{Any}})
Base.precompile(Tuple{typeof(_update_subplot_periphery),Subplot{PlotlyBackend},Vector{Any}})
Base.precompile(Tuple{typeof(axis_limits),Subplot{GRBackend},Symbol,Bool,Bool})
@@ -269,16 +244,14 @@ function _precompile_()
Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64})
Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}})
Base.precompile(Tuple{typeof(convert_to_polar),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Int64, Float64}})
Base.precompile(Tuple{typeof(create_grid),Expr})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64},Vararg{Vector{Float64}, N} where N})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{typeof(error_zipit),Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}})
Base.precompile(Tuple{typeof(fakedata),Int64,Int64})
Base.precompile(Tuple{typeof(fakedata),MersenneTwister,Int64,Vararg{Int64, N} where N})
Base.precompile(Tuple{typeof(get_minor_ticks),Subplot{GRBackend},Axis,Tuple{Vector{Float64}, Vector{String}}})
Base.precompile(Tuple{typeof(get_minor_ticks),Subplot{GRBackend},Axis,Tuple{Vector{Int64}, Vector{String}}})
Base.precompile(Tuple{typeof(get_series_color),SubArray{Symbol, 1, Vector{Symbol}, Tuple{UnitRange{Int64}}, true},Subplot{GRBackend},Int64,Symbol})
Base.precompile(Tuple{typeof(get_series_color),Vector{Symbol},Subplot{GRBackend},Int64,Symbol})
Base.precompile(Tuple{typeof(get_series_color),Vector{Symbol},Subplot{PlotlyBackend},Int64,Symbol})
Base.precompile(Tuple{typeof(get_ticks),StepRange{Int64, Int64},Vector{Float64},Vector{Any},Tuple{Int64, Int64},Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Float64},Vararg{Any, N} where N})
@@ -295,10 +268,6 @@ function _precompile_()
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Float64,Float64,Tuple{Float64, Float64},Int64,Int64,Int64,Shape{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Int64,Float64,Tuple{Float64, Float64},Int64,Float64,Int64,Symbol})
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Int64,Int64,Tuple{Float64, Float64},Int64,Int64,Int64,Symbol})
Base.precompile(Tuple{typeof(gr_draw_markers),Series,Base.OneTo{Int64},Vector{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_markers),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_markers),Series,UnitRange{Int64},Vector{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_markers),Series,Vector{Int64},Vector{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Base.OneTo{Int64},UnitRange{Int64},Tuple{Vector{Float64}, Vector{Float64}},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Base.OneTo{Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,StepRange{Int64, Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
@@ -307,13 +276,15 @@ function _precompile_()
Base.precompile(Tuple{typeof(gr_draw_surface),Series,Vector{Float64},Vector{Float64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_surface),Series,Vector{Float64},Vector{Float64},Vector{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_fill_viewport),Vector{Float64},RGBA{Float64}})
Base.precompile(Tuple{typeof(gr_get_3d_axis_angle),Vector{Float64},Float64,Float64,Symbol})
Base.precompile(Tuple{typeof(gr_get_ticks_size),Tuple{Vector{Float64}, Vector{String}},Int64})
Base.precompile(Tuple{typeof(gr_get_ticks_size),Tuple{Vector{Int64}, Vector{String}},Int64})
Base.precompile(Tuple{typeof(gr_label_ticks),Subplot{GRBackend},Symbol,Tuple{Vector{Float64}, Vector{String}}})
Base.precompile(Tuple{typeof(gr_label_ticks),Subplot{GRBackend},Symbol,Tuple{Vector{Int64}, Vector{String}}})
Base.precompile(Tuple{typeof(gr_label_ticks_3d),Subplot{GRBackend},Symbol,Tuple{Vector{Float64}, Vector{String}}})
Base.precompile(Tuple{typeof(gr_polaraxes),Int64,Float64,Subplot{GRBackend}})
Base.precompile(Tuple{typeof(gr_polyline),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{typeof(gr_set_gradient),PlotUtils.ContinuousColorGradient})
Base.precompile(Tuple{typeof(gr_text),Float64,Float64,String})
Base.precompile(Tuple{typeof(gr_update_viewport_legend!),Vector{Float64},Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), NTuple{9, Float64}}})
Base.precompile(Tuple{typeof(gr_update_viewport_legend!),Vector{Float64},Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), Tuple{Int64, Int64, Int64, Float64, Int64, Float64, Float64, Float64, Float64}}})
Base.precompile(Tuple{typeof(gr_viewport_from_bbox),Subplot{GRBackend},BoundingBox{Tuple{AbsoluteLength, AbsoluteLength}, Tuple{AbsoluteLength, AbsoluteLength}},AbsoluteLength,AbsoluteLength,Vector{Float64}})
@@ -325,7 +296,8 @@ function _precompile_()
Base.precompile(Tuple{typeof(heatmap_edges),Vector{Float64},Symbol,Vector{Float64},Symbol,Tuple{Int64, Int64},Bool})
Base.precompile(Tuple{typeof(heatmap_edges),Vector{Float64},Symbol})
Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}})
Base.precompile(Tuple{typeof(make_fillrange_side),UnitRange{Int64},LinRange{Float64}})
Base.precompile(Tuple{typeof(layout_args),NamedTuple{(:label, :blank), Tuple{Symbol, Bool}}})
Base.precompile(Tuple{typeof(layout_args),NamedTuple{(:label, :width, :height), Tuple{Symbol, Symbol, Float64}}})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Float64, Float64},Symbol,Function})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Float64, Float64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Int64, Float64},Symbol,Symbol})
@@ -334,7 +306,6 @@ function _precompile_()
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),UnitRange{Int64},Tuple{Float64, Float64},Symbol,Symbol})
Base.precompile(Tuple{typeof(partialcircle),Int64,Float64,Int64})
Base.precompile(Tuple{typeof(plot),Any,Any})
Base.precompile(Tuple{typeof(plot),Any})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}, N} where N})
@@ -345,9 +316,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Matrix{Symbol}})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},RGBA{Float64}})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Shape{Float64, Float64}})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Stroke})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(processMinorGridArg!),Dict{Symbol, Any},Bool,Symbol})
Base.precompile(Tuple{typeof(process_annotation),Subplot{GRBackend},Int64,Float64,PlotText})
Base.precompile(Tuple{typeof(process_annotation),Subplot{GRBackend},Int64,Float64,Tuple{String, Int64, Symbol, Symbol}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{GRBackend},Int64,Float64,Tuple{String, Symbol, Int64, String}})
@@ -358,28 +327,28 @@ function _precompile_()
Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},Symbol,Symbol})
Base.precompile(Tuple{typeof(push!),Plot{GRBackend},Float64,Vector{Float64}})
Base.precompile(Tuple{typeof(push!),Segments{Tuple{Float64, Float64, Float64}},Tuple{Float64, Float64, Float64},Tuple{Float64, Float64, Float64}})
Base.precompile(Tuple{typeof(push!),Segments{Tuple{Float64, Float64, Float64}},Tuple{Int64, Float64, Int64},Tuple{Int64, Float64, Int64}})
Base.precompile(Tuple{typeof(push!),Segments{Tuple{Float64, Float64, Float64}},Tuple{Int64, Float64, Int64},Tuple{Float64, Float64, Int64}})
Base.precompile(Tuple{typeof(resetfontsizes)})
Base.precompile(Tuple{typeof(scalefontsizes),Float64})
Base.precompile(Tuple{typeof(series_annotations),Vector{Any}})
Base.precompile(Tuple{typeof(slice_arg),Base.ReshapedArray{Int64, 2, UnitRange{Int64}, Tuple{}},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{AbsoluteLength},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{Bool},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{Int64},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{PlotUtils.ContinuousColorGradient},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{RGBA{Float64}},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{String},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{Symbol},Int64})
Base.precompile(Tuple{typeof(spy),Any})
Base.precompile(Tuple{typeof(straightline_data),Tuple{Float64, Float64},Tuple{Float64, Float64},Vector{Float64},Vector{Float64},Int64})
Base.precompile(Tuple{typeof(stroke),Int64,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(title!),AbstractString})
Base.precompile(Tuple{typeof(unzip),Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64, Float64}}})
Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64}}})
Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}})
Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}})
Base.precompile(Tuple{typeof(vline!),Any})
Base.precompile(Tuple{typeof(warn_on_attr_dim_mismatch),Series,Vector{Float64},Vector{Float64},Nothing,Base.Iterators.Flatten{Vector{Tuple{SeriesSegment}}}})
Base.precompile(Tuple{typeof(xgrid!),Plot{GRBackend},Symbol,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(xlims),Subplot{PlotlyBackend}})
isdefined(Plots, Symbol("#add_major_or_minor_segments#120")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#120")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#add_major_or_minor_segments#121")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#121")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#4#8")) && Base.precompile(Tuple{getfield(Plots, Symbol("#4#8")),UnitRange{Int64}})
isdefined(Plots, Symbol("#add_major_or_minor_segments#122")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#122")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#add_major_or_minor_segments#123")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#123")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
let fbody = try __lookup_kwbody__(which(font, (Font,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(font),Font,Vararg{Any, N} where N,))
+6 -3
View File
@@ -25,13 +25,14 @@ using SparseArrays
using FFMPEG
@reexport using RecipesBase
import RecipesBase: plot, plot!, animate, is_explicit
import RecipesBase: plot, plot!, animate, is_explicit, grid
using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
import Showoff
import UnicodeFun
import StatsBase
import Downloads
import Showoff
import JSON
using Requires
@@ -41,7 +42,6 @@ export
grid,
bbox,
plotarea,
@layout,
KW,
wrap,
@@ -166,6 +166,8 @@ const BBox = Measures.Absolute2DBox
const px = AbsoluteLength(0.254)
const pct = Length{:pct,Float64}(1.0)
Base.convert(::Type{<:Measure}, x::Float64) = x * pct
Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
@@ -209,6 +211,7 @@ include("colorbars.jl")
include("axes.jl")
include("args.jl")
include("components.jl")
include("consts.jl")
include("themes.jl")
include("plot.jl")
include("pipeline.jl")
+57 -56
View File
@@ -77,64 +77,65 @@ const _arg_desc = KW(
:warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes",
# subplot args
:title => "String. Subplot title.",
:titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
:titlefontfamily => "String or Symbol. Font family of subplot title.",
:titlefontsize => "Integer. Font pointsize of subplot title.",
:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center",
:titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center",
:titlefontrotation => "Real. Font rotation of subplot title",
:titlefontcolor => "Color Type. Font color of subplot title",
:title => "String. Subplot title.",
:titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
:titlefontfamily => "String or Symbol. Font family of subplot title.",
:titlefontsize => "Integer. Font pointsize of subplot title.",
:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center",
:titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center",
:titlefontrotation => "Real. Font rotation of subplot title",
:titlefontcolor => "Color Type. Font color of subplot title",
:background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.",
:background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
:legend_background_color => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
:foreground_color_subplot => "Color Type or `:match` (matches `:foreground_color`). Base foreground color of the subplot.",
:foreground_color_legend => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.",
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.",
:legend => "Bool (show the legend?) or (x,y) tuple or Symbol (legend position) or angle or (angle,inout) tuple. Bottom left corner of legend is placed at (x,y). Symbol values: `:none`; `:best`; `:inline`; `:inside`; `:legend`; any valid combination of `:(outer ?)(top/bottom ?)(right/left ?)`, i.e.: `:top`, `:topright`, `:outerleft`, `:outerbottomright` ... (note: only some may be supported in each backend). Legend is positioned at (angle degrees) (so (90,:outer) is roughly equivalent to :outertop), close to the inside of the axes or the outside if inout=:outer.",
:legendfontfamily => "String or Symbol. Font family of legend entries.",
:legendfontsize => "Integer. Font pointsize of legend entries.",
:legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
:legendtitle => "String. Legend title.",
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
:legendtitlefontsize => "Integer. Font pointsize the legend title.",
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
:legendtitlefontrotation => "Real. Font rotation of the legend title",
:legendtitlefontcolor => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.",
:colorbar_fontfamily => "String or Symbol. Font family of colobar entries.",
:colorbar_ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
:colorbar_tickfontfamily => "String or Symbol. Font family of colorbar tick labels.",
:colorbar_tickfontsize => "Integer. Font pointsize of colorbar tick entries.",
:colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries",
:colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`",
:colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
:legendfont => "Font. Font of legend items.",
:legendtitlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String, PlotText (created with `text(args...)`), or a tuple of arguments to `text` (e.g., `(\"Label\", 8, :red, :top)`). Add one-off text annotations at the x,y coordinates.",
:annotationfontfamily => "String or Symbol. Font family of annotations.",
:annotationfontsize => "Integer. Font pointsize of annotations.",
:annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.",
:annotationvalign => "Symbol. Vertical alignment of annotations, :vcenter, :top, :bottom or :center.",
:annotationrotation => "Float. Rotation of annotations in degrees.",
:annotationcolor => "Colorant or :match. Color of annotations.",
:projection => "Symbol or String. '3d' or 'polar'",
:aspect_ratio => "Symbol (:equal or :none) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units. With `:none`, images inherit aspect ratio of the plot area.",
:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.",
:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.",
:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.",
:right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.",
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
:colorbar_title => "String. Title of colorbar.",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots",
:legend_foreground_color => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.",
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.",
:legend_position => "Bool (show the legend?) or (x,y) tuple or Symbol (legend position) or angle or (angle,inout) tuple. Bottom left corner of legend is placed at (x,y). Symbol values: `:none`; `:best`; `:inline`; `:inside`; `:legend`; any valid combination of `:(outer ?)(top/bottom ?)(right/left ?)`, i.e.: `:top`, `:topright`, `:outerleft`, `:outerbottomright` ... (note: only some may be supported in each backend)",
:legend_title_font => "Font. Font of the legend title.",
:legend_font_family => "String or Symbol. Font family of legend entries.",
:legend_font_pointsize => "Integer. Font pointsize of legend entries.",
:legend_font_halign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
:legend_font_valign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legend_font_rotation => "Real. Font rotation of legend entries",
:legend_font_color => "Color Type. Font color of legend entries",
:legend_title => "String. Legend title.",
:legend_title_font_family => "String or Symbol. Font family of the legend title.",
:legend_title_font_pointsize => "Integer. Font pointsize the legend title.",
:legend_title_font_halign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legend_title_font_valign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
:legend_title_font_rotation => "Real. Font rotation of the legend title",
:legend_title_font_color => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.",
:colorbar_fontfamily => "String or Symbol. Font family of colobar entries.",
:colorbar_ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
:colorbar_tickfontfamily => "String or Symbol. Font family of colorbar tick labels.",
:colorbar_tickfontsize => "Integer. Font pointsize of colorbar tick entries.",
:colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries",
:colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`",
:colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
:legend_font => "Font. Font of legend items.",
:legend_titlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String, PlotText (created with `text(args...)`), or a tuple of arguments to `text` (e.g., `(\"Label\", 8, :red, :top)`). Add one-off text annotations at the x,y coordinates.",
:annotationfontfamily => "String or Symbol. Font family of annotations.",
:annotationfontsize => "Integer. Font pointsize of annotations.",
:annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.",
:annotationvalign => "Symbol. Vertical alignment of annotations, :vcenter, :top, :bottom or :center.",
:annotationrotation => "Float. Rotation of annotations in degrees.",
:annotationcolor => "Colorant or :match. Color of annotations.",
:projection => "Symbol or String. '3d' or 'polar'",
:aspect_ratio => "Symbol (:equal or :none) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units. With `:none`, images inherit aspect ratio of the plot area.",
:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.",
:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.",
:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.",
:right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.",
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
:colorbar_title => "String. Title of colorbar.",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots",
# axis args
:guide => "String. Axis guide (label).",
+223 -155
View File
@@ -24,8 +24,9 @@ function add_aliases(sym::Symbol, aliases::Symbol...)
return nothing
end
function add_axes_aliases(sym::Symbol, aliases::Symbol...)
function add_axes_aliases(sym::Symbol, aliases::Symbol...; generic::Bool = true)
sym in keys(_axis_defaults) || throw(ArgumentError("Invalid `$sym`"))
generic && add_aliases(sym, aliases...)
for letter in (:x, :y, :z)
add_aliases(Symbol(letter, sym), (Symbol(letter, a) for a in aliases)...)
end
@@ -88,6 +89,8 @@ const _allTypes = vcat(
_3dTypes,
)
const _z_colored_series = [:contour, :contour3d, :heatmap, :histogram2d, :surface, :hexbin]
const _typeAliases = Dict{Symbol,Symbol}(
:n => :none,
:no => :none,
@@ -444,14 +447,10 @@ const _subplot_defaults = KW(
:titlefontrotation => 0.0,
:titlefontcolor => :match,
:background_color_subplot => :match, # default for other bg colors... match takes plot default
:background_color_legend => :match, # background of legend
:background_color_inside => :match, # background inside grid
:foreground_color_subplot => :match, # default for other fg colors... match takes plot default
:foreground_color_legend => :match, # foreground of legend
:foreground_color_title => :match, # title color
:color_palette => :auto,
:legend => :best,
:legendtitle => nothing,
:colorbar => :legend,
:clims => :auto,
:colorbar_fontfamily => :match,
@@ -466,18 +465,6 @@ const _subplot_defaults = KW(
:colorbar_formatter => :auto,
:colorbar_discrete_values => [],
:colorbar_continuous_values => zeros(0),
:legendfontfamily => :match,
:legendfontsize => 8,
:legendfonthalign => :hcenter,
:legendfontvalign => :vcenter,
:legendfontrotation => 0.0,
:legendfontcolor => :match,
:legendtitlefontfamily => :match,
:legendtitlefontsize => 11,
:legendtitlefonthalign => :hcenter,
:legendtitlefontvalign => :vcenter,
:legendtitlefontrotation => 0.0,
:legendtitlefontcolor => :match,
:annotations => [], # annotation tuples... list of (x,y,annotation)
:annotationfontfamily => :match,
:annotationfontsize => 14,
@@ -496,6 +483,7 @@ const _subplot_defaults = KW(
:colorbar_title => "",
:colorbar_titlefontsize => 10,
:colorbar_title_location => :center, # also :left or :right
:colorbar_fontfamily => :match,
:colorbar_titlefontfamily => :match,
:colorbar_titlefonthalign => :hcenter,
:colorbar_titlefontvalign => :vcenter,
@@ -565,80 +553,6 @@ const _suppress_warnings = Set{Symbol}([
:relative_bbox,
])
# add defaults for the letter versions
const _axis_defaults_byletter = KW()
function reset_axis_defaults_byletter!()
for letter in (:x, :y, :z)
_axis_defaults_byletter[letter] = KW()
for (k, v) in _axis_defaults
_axis_defaults_byletter[letter][k] = v
end
end
end
reset_axis_defaults_byletter!()
const _all_defaults = KW[_series_defaults, _plot_defaults, _subplot_defaults]
const _initial_defaults = deepcopy(_all_defaults)
const _initial_axis_defaults = deepcopy(_axis_defaults)
# to be able to reset font sizes to initial values
const _initial_plt_fontsizes =
Dict(:plot_titlefontsize => _plot_defaults[:plot_titlefontsize])
const _initial_sp_fontsizes = Dict(
:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize],
:legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:annotationfontsize => _subplot_defaults[:annotationfontsize],
:colorbar_tickfontsize => _subplot_defaults[:colorbar_tickfontsize],
:colorbar_titlefontsize => _subplot_defaults[:colorbar_titlefontsize],
)
const _initial_ax_fontsizes = Dict(
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize],
)
const _initial_fontsizes =
merge(_initial_plt_fontsizes, _initial_sp_fontsizes, _initial_ax_fontsizes)
const _internal_args =
[:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter]
const _axis_args = sort(union(collect(keys(_axis_defaults))))
const _series_args = sort(union(collect(keys(_series_defaults))))
const _subplot_args = sort(union(collect(keys(_subplot_defaults))))
const _plot_args = sort(union(collect(keys(_plot_defaults))))
const _magic_axis_args = [:axis, :tickfont, :guidefont, :grid, :minorgrid]
const _magic_subplot_args =
[:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont]
const _magic_series_args = [:line, :marker, :fill]
const _all_axis_args = sort(union([_axis_args; _magic_axis_args]))
const _all_subplot_args = sort(union([_subplot_args; _magic_subplot_args]))
const _all_series_args = sort(union([_series_args; _magic_series_args]))
const _all_plot_args = _plot_args
for letter in (:x, :y, :z)
_attrsymbolcache[letter] = Dict{Symbol,Symbol}()
for k in keys(_axis_defaults)
# populate attribute cache
lk = Symbol(letter, k)
_attrsymbolcache[letter][k] = lk
# allow the underscore version too: xguide or x_guide
add_aliases(lk, Symbol(letter, "_", k))
end
for k in (_magic_axis_args..., :(_discrete_indices))
_attrsymbolcache[letter][k] = Symbol(letter, k)
end
end
const _all_args =
sort(union([_all_axis_args; _all_subplot_args; _all_series_args; _all_plot_args]))
is_subplot_attr(k) = k in _all_subplot_args
is_series_attr(k) = k in _all_series_args
is_axis_attr(k) = Symbol(chop(string(k); head = 1, tail = 0)) in _all_axis_args
@@ -670,9 +584,46 @@ aliases(aliasMap::Dict{Symbol,Symbol}, val) =
sortedkeys(filter((k, v) -> v == val, aliasMap))
# -----------------------------------------------------------------------------
# legend
add_aliases(:legend_position, :legend, :leg, :key, :legends)
add_aliases(
:legend_background_color,
:bg_legend,
:bglegend,
:bgcolor_legend,
:bg_color_legend,
:background_legend,
:background_colour_legend,
:bgcolour_legend,
:bg_colour_legend,
:background_color_legend,
)
add_aliases(
:legend_foreground_color,
:fg_legend,
:fglegend,
:fgcolor_legend,
:fg_color_legend,
:foreground_legend,
:foreground_colour_legend,
:fgcolour_legend,
:fg_colour_legend,
:foreground_color_legend,
)
add_aliases(:legend_font_pointsize, :legendfontsize)
add_aliases(
:legend_title,
:key_title,
:keytitle,
:label_title,
:labeltitle,
:leg_title,
:legtitle,
)
add_aliases(:legend_title_font_pointsize, :legendtitlefontsize)
# margin
add_aliases(:left_margin, :leftmargin)
add_aliases(:top_margin, :topmargin)
add_aliases(:bottom_margin, :bottommargin)
add_aliases(:right_margin, :rightmargin)
@@ -695,17 +646,6 @@ add_aliases(
:bgcolour,
:bg_colour,
)
add_aliases(
:background_color_legend,
:bg_legend,
:bglegend,
:bgcolor_legend,
:bg_color_legend,
:background_legend,
:background_colour_legend,
:bgcolour_legend,
:bg_colour_legend,
)
add_aliases(
:background_color_subplot,
:bg_subplot,
@@ -749,17 +689,7 @@ add_aliases(
:fgcolour,
:fg_colour,
)
add_aliases(
:foreground_color_legend,
:fg_legend,
:fglegend,
:fgcolor_legend,
:fg_color_legend,
:foreground_legend,
:foreground_colour_legend,
:fgcolour_legend,
:fg_colour_legend,
)
add_aliases(
:foreground_color_subplot,
:fg_subplot,
@@ -771,6 +701,90 @@ add_aliases(
:fgcolour_subplot,
:fg_colour_subplot,
)
add_aliases(
:foreground_color_grid,
:fg_grid,
:fggrid,
:fgcolor_grid,
:fg_color_grid,
:foreground_grid,
:foreground_colour_grid,
:fgcolour_grid,
:fg_colour_grid,
:gridcolor,
)
add_aliases(
:foreground_color_minor_grid,
:fg_minor_grid,
:fgminorgrid,
:fgcolor_minorgrid,
:fg_color_minorgrid,
:foreground_minorgrid,
:foreground_colour_minor_grid,
:fgcolour_minorgrid,
:fg_colour_minor_grid,
:minorgridcolor,
)
add_aliases(
:foreground_color_title,
:fg_title,
:fgtitle,
:fgcolor_title,
:fg_color_title,
:foreground_title,
:foreground_colour_title,
:fgcolour_title,
:fg_colour_title,
:titlecolor,
)
add_aliases(
:foreground_color_axis,
:fg_axis,
:fgaxis,
:fgcolor_axis,
:fg_color_axis,
:foreground_axis,
:foreground_colour_axis,
:fgcolour_axis,
:fg_colour_axis,
:axiscolor,
)
add_aliases(
:foreground_color_border,
:fg_border,
:fgborder,
:fgcolor_border,
:fg_color_border,
:foreground_border,
:foreground_colour_border,
:fgcolour_border,
:fg_colour_border,
:bordercolor,
)
add_aliases(
:foreground_color_text,
:fg_text,
:fgtext,
:fgcolor_text,
:fg_color_text,
:foreground_text,
:foreground_colour_text,
:fgcolour_text,
:fg_colour_text,
:textcolor,
)
add_aliases(
:foreground_color_guide,
:fg_guide,
:fgguide,
:fgcolor_guide,
:fg_color_guide,
:foreground_guide,
:foreground_colour_guide,
:fgcolour_guide,
:fg_colour_guide,
:guidecolor,
)
add_aliases(
:foreground_color_title,
@@ -841,13 +855,20 @@ add_aliases(:markerstrokealpha, :msa, :msalpha, :msα, :markerstrokeopacity, :ms
add_aliases(:fillalpha, :fa, :falpha, :fα, :fillopacity, :fopacity)
# axes attributes
add_axes_aliases(:guide, :label, :lab, :l)
add_axes_aliases(:guide, :label, :lab, :l; generic = false)
add_axes_aliases(:lims, :lim, :limit, :limits, :range)
add_axes_aliases(:ticks, :tick)
add_axes_aliases(:rotation, :rot, :r)
add_axes_aliases(:guidefontsize, :labelfontsize)
add_axes_aliases(:gridalpha, :ga, :galpha, :gα, :gridopacity, :gopacity)
add_axes_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls, :gridls)
add_axes_aliases(
:gridstyle,
:grid_style,
:gridlinestyle,
:grid_linestyle,
:grid_ls,
:gridls,
)
add_axes_aliases(
:foreground_color_grid,
:fg_grid,
@@ -872,7 +893,14 @@ add_axes_aliases(
:fg_colour_minor_grid,
:minorgridcolor,
)
add_axes_aliases(:gridlinewidth, :gridwidth, :grid_linewidth, :grid_width, :gridlw, :grid_lw)
add_axes_aliases(
:gridlinewidth,
:gridwidth,
:grid_linewidth,
:grid_width,
:gridlw,
:grid_lw,
)
add_axes_aliases(
:minorgridstyle,
:minorgrid_style,
@@ -917,7 +945,19 @@ add_aliases(:group, :g, :grouping)
add_aliases(:bins, :bin, :nbin, :nbins, :nb)
add_aliases(:ribbon, :rib)
add_aliases(:annotations, :ann, :anns, :annotate, :annotation)
add_aliases(:xguide, :xlabel, :xlab, :xl)
add_aliases(:xlims, :xlim, :xlimit, :xlimits, :xrange)
add_aliases(:xticks, :xtick)
add_aliases(:xrotation, :xrot, :xr)
add_aliases(:yguide, :ylabel, :ylab, :yl)
add_aliases(:ylims, :ylim, :ylimit, :ylimits, :yrange)
add_aliases(:yticks, :ytick)
add_aliases(:yrotation, :yrot, :yr)
add_aliases(:zguide, :zlabel, :zlab, :zl)
add_aliases(:zlims, :zlim, :zlimit, :zlimits)
add_aliases(:zticks, :ztick)
add_aliases(:zrotation, :zrot, :zr)
add_aliases(:guidefontsize, :labelfontsize)
add_aliases(
:fill_z,
:fillz,
@@ -928,8 +968,6 @@ add_aliases(
:surfcolor,
:surfcolour,
)
add_aliases(:legend, :leg, :key)
add_aliases(:legendtitle, :legend_title, :labeltitle, :label_title, :leg_title, :key_title)
add_aliases(:colorbar, :cb, :cbar, :colorkey)
add_aliases(
:colorbar_title,
@@ -1005,13 +1043,6 @@ add_aliases(:camera, :cam, :viewangle, :view_angle)
add_aliases(:contour_labels, :contourlabels, :clabels, :clabs)
add_aliases(:warn_on_unsupported, :warn)
# add all pluralized forms to the _keyAliases dict
for arg in _all_args
add_aliases(arg, makeplural(arg))
end
# add all non_underscored forms to the _keyAliases
add_non_underscore_aliases!(_keyAliases)
# -----------------------------------------------------------------------------
function parse_axis_kw(s::Symbol)
@@ -1452,8 +1483,7 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
end
# fonts
for fontname in
(:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont)
for fontname in (:titlefont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont)
args = RecipesPipeline.pop_kw!(plotattributes, fontname, ())
for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg)
@@ -1520,8 +1550,9 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
# end
# legends
if haskey(plotattributes, :legend)
plotattributes[:legend] = convertLegendValue(plotattributes[:legend])
if haskey(plotattributes, :legend_position)
plotattributes[:legend_position] =
convertLegendValue(plotattributes[:legend_position])
end
if haskey(plotattributes, :colorbar)
plotattributes[:colorbar] = convertLegendValue(plotattributes[:colorbar])
@@ -1570,7 +1601,7 @@ function warn_on_unsupported_args(pkg::AbstractBackend, plotattributes)
end
if !isempty(_to_warn) &&
!get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
for k in sort(collect(_to_warn))
push!(already_warned, k)
@warn(
@@ -1652,15 +1683,18 @@ function convertLegendValue(val::Symbol)
:inline,
)
val
elseif val == :horizontal
-1
else
error("Invalid symbol for legend: $val")
end
end
convertLegendValue(val::Real) = val
convertLegendValue(val::Bool) = val ? :best : :none
convertLegendValue(val::Nothing) = :none
convertLegendValue(v::Union{Tuple,NamedTuple}) = convertLegendValue.(v)
convertLegendValue(v::Tuple{S,T}) where {S<:Real,T<:Real} = v
convertLegendValue(v::Tuple{<:Real,Symbol}) = v
convertLegendValue(v::Real) = v
convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
# -----------------------------------------------------------------------------
@@ -1709,7 +1743,7 @@ function slice_arg!(
)
v = get(plotattributes_in, k, plotattributes_out[k])
plotattributes_out[k] =
if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v)
if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v) && !(k in _plot_args)
slice_arg(v, idx)
else
v
@@ -1746,9 +1780,9 @@ end
# when a value can be `:match`, this is the key that should be used instead for value retrieval
const _match_map = KW(
:background_color_outside => :background_color,
:background_color_legend => :background_color_subplot,
:legend_background_color => :background_color_subplot,
:background_color_inside => :background_color_subplot,
:foreground_color_legend => :foreground_color_subplot,
:legend_foreground_color => :foreground_color_subplot,
:foreground_color_title => :foreground_color_subplot,
:left_margin => :margin,
:top_margin => :margin,
@@ -1756,10 +1790,10 @@ const _match_map = KW(
:bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot,
:legendfontfamily => :fontfamily_subplot,
:legendfontcolor => :foreground_color_subplot,
:legendtitlefontfamily => :fontfamily_subplot,
:legendtitlefontcolor => :foreground_color_subplot,
:legend_font_family => :fontfamily_subplot,
:legend_font_color => :foreground_color_subplot,
:legend_title_font_family => :fontfamily_subplot,
:legend_title_font_color => :foreground_color_subplot,
:colorbar_fontfamily => :fontfamily_subplot,
:colorbar_titlefontfamily => :fontfamily_subplot,
:colorbar_titlefontcolor => :foreground_color_subplot,
@@ -1890,10 +1924,10 @@ function _update_subplot_periphery(sp::Subplot, anns::AVec)
sp.attr[:annotations] = newanns
# handle legend/colorbar
sp.attr[:legend] = convertLegendValue(sp.attr[:legend])
sp.attr[:legend_position] = convertLegendValue(sp.attr[:legend_position])
sp.attr[:colorbar] = convertLegendValue(sp.attr[:colorbar])
if sp.attr[:colorbar] == :legend
sp.attr[:colorbar] = sp.attr[:legend]
sp.attr[:colorbar] = sp.attr[:legend_position]
end
return
end
@@ -1902,16 +1936,35 @@ function _update_subplot_colors(sp::Subplot)
# background colors
color_or_nothing!(sp.attr, :background_color_subplot)
sp.attr[:color_palette] = get_color_palette(sp.attr[:color_palette], 30)
color_or_nothing!(sp.attr, :background_color_legend)
color_or_nothing!(sp.attr, :legend_background_color)
color_or_nothing!(sp.attr, :background_color_inside)
# foreground colors
color_or_nothing!(sp.attr, :foreground_color_subplot)
color_or_nothing!(sp.attr, :foreground_color_legend)
color_or_nothing!(sp.attr, :legend_foreground_color)
color_or_nothing!(sp.attr, :foreground_color_title)
return
end
function _update_subplot_legend(sp::Subplot, plotattributes_in)
f_attr = NamedTuple(
k => plotattributes_in[Symbol(:legend_font_, k)] for
k in (:family, :pointsize, :valign, :halign, :rotation, :color) if
haskey(plotattributes_in, Symbol(:legend_font_, k))
)
match_attr = NamedTuple(
(
lk = Symbol(:legend_font_, k);
k =>
haskey(_match_map, lk) ? sp[lk] :
haskey(plotattributes_in, :legend_font) ?
getproperty(plotattributes_in[:legend_font], k) :
default(plotattributes_in, lk)
) for k in (:family, :pointsize, :valign, :halign, :rotation, :color)
)
sp.attr[:legend_font] = font(; merge(match_attr, f_attr)...)
end
function _update_axis(
plt::Plot,
sp::Subplot,
@@ -2018,7 +2071,6 @@ function _update_subplot_args(
lims_warned = true
end
end
_update_subplot_colorbars(sp)
end
# -----------------------------------------------------------------------------
@@ -2195,7 +2247,16 @@ end
#--------------------------------------------------
## inspired by Base.@kwdef
macro add_attributes(level, expr)
"""
add_attributes(level, expr, match_table)
Takes a `struct` definition and recurses into its fields to create keywords by chaining the field names with the structs' name with underscore.
Also creates pluralized and non-underscore aliases for these keywords.
- `level` indicates which group of `plot`, `subplot`, `series`, etc. the keywords belong to.
- `expr` is the struct definition with default values like `Base.@kwdef`
- `match_table` is an expression of the form `:match = (symbols)`, with symbols whose default value should be `:match`
"""
macro add_attributes(level, expr, match_table)
expr = macroexpand(__module__, expr) # to expand @static
expr isa Expr && expr.head === :struct || error("Invalid usage of @add_attributes")
T = expr.args[2]
@@ -2203,16 +2264,18 @@ macro add_attributes(level, expr)
T = T.args[1]
end
key_args = Any[]
value_args = Any[]
key_dict = KW()
_splitdef!(expr.args[3], value_args, key_args)
_splitdef!(expr.args[3], key_dict)
insert_block = Expr(:block)
for (key, value) in zip(key_args, value_args)
for (key, value) in key_dict
# e.g. _series_defualts[key] = value
exp_key = Symbol(lowercase(string(T)), "_", key)
pl_key = makeplural(exp_key)
if QuoteNode(exp_key) in match_table.args[2].args
value = QuoteNode(:match)
end
push!(
insert_block.args,
Expr(
@@ -2246,7 +2309,7 @@ macro add_attributes(level, expr)
end |> esc
end
function _splitdef!(blk, value_args, key_args)
function _splitdef!(blk, key_dict)
for i in eachindex(blk.args)
ei = blk.args[i]
if ei isa Symbol
@@ -2261,20 +2324,25 @@ function _splitdef!(blk, value_args, key_args)
elseif lhs isa Expr && lhs.head === :(::) && lhs.args[1] isa Symbol
# var::T = defexpr
var = lhs.args[1]
type = lhs.args[2]
if @isdefined type
for field in fieldnames(getproperty(Plots, type))
key_dict[Symbol(var, "_", field)] =
:(getfield($(ei.args[2]), $(QuoteNode(field))))
end
end
else
# something else, e.g. inline inner constructor
# F(...) = ...
continue
end
defexpr = ei.args[2] # defexpr
push!(value_args, defexpr)
push!(key_args, var)
key_dict[var] = defexpr
blk.args[i] = lhs
elseif ei.head === :(::) && ei.args[1] isa Symbol
# var::Typ
var = ei.args[1]
push!(value_args, var)
push!(key_args, var)
key_dict[var] = defexpr
elseif ei.head === :block
# can arise with use of @static inside type decl
_kwdef!(ei, value_args, key_args)
+89 -54
View File
@@ -310,10 +310,10 @@ _initialize_backend(pkg::GRBackend) = nothing
const _gr_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_grid,
:foreground_color_axis,
:foreground_color_text,
@@ -350,12 +350,12 @@ const _gr_attr = merge_with_base_supported([
:titlefontvalign,
:titlefontrotation,
:titlefontcolor,
:legendfontfamily,
:legendfontsize,
:legendfonthalign,
:legendfontvalign,
:legendfontrotation,
:legendfontcolor,
:legend_font_family,
:legend_font_pointsize,
:legend_font_halign,
:legend_font_valign,
:legend_font_rotation,
:legend_font_color,
:tickfontfamily,
:tickfontsize,
:tickfonthalign,
@@ -372,17 +372,13 @@ const _gr_attr = merge_with_base_supported([
:gridalpha,
:gridstyle,
:gridlinewidth,
:legend,
:legendtitle,
:legend_position,
:legend_title,
:colorbar,
:colorbar_title,
:colorbar_entry,
:colorbar_titlefontfamily,
:colorbar_titlefontsize,
:colorbar_titlefontvalign,
:colorbar_titlefonthalign,
:colorbar_titlefontrotation,
:colorbar_titlefontcolor,
:colorbar_scale,
:clims,
:fill_z,
:line_z,
:marker_z,
@@ -402,6 +398,7 @@ const _gr_attr = merge_with_base_supported([
:tick_direction,
:camera,
:contour_labels,
:connections,
])
const _gr_seriestype = [
:path,
@@ -438,10 +435,10 @@ end
const _plotly_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_guide,
:foreground_color_grid,
:foreground_color_axis,
@@ -474,9 +471,9 @@ const _plotly_attr = merge_with_base_supported([
:titlefonthalign,
:titlefontvalign,
:titlefontcolor,
:legendfontfamily,
:legendfontsize,
:legendfontcolor,
:legend_font_family,
:legend_font_pointsize,
:legend_font_color,
:tickfontfamily,
:tickfontsize,
:tickfontcolor,
@@ -521,6 +518,7 @@ const _plotly_attr = merge_with_base_supported([
:tick_direction,
:camera,
:contour_labels,
:connections,
])
const _plotly_seriestype = [
@@ -563,10 +561,10 @@ defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html"
const _pgfplots_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
# :background_color_outside,
# :foreground_color_legend,
# :legend_foreground_color,
:foreground_color_grid,
:foreground_color_axis,
:foreground_color_text,
@@ -686,11 +684,11 @@ end
const _pyplot_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
:foreground_color_grid,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_title,
:foreground_color_axis,
:foreground_color_border,
@@ -729,9 +727,9 @@ const _pyplot_attr = merge_with_base_supported([
:titlefontfamily,
:titlefontsize,
:titlefontcolor,
:legendfontfamily,
:legendfontsize,
:legendfontcolor,
:legend_font_family,
:legend_font_pointsize,
:legend_font_color,
:tickfontfamily,
:tickfontsize,
:tickfontcolor,
@@ -742,8 +740,8 @@ const _pyplot_attr = merge_with_base_supported([
:gridalpha,
:gridstyle,
:gridlinewidth,
:legend,
:legendtitle,
:legend_position,
:legend_title,
:colorbar,
:colorbar_title,
:colorbar_entry,
@@ -777,6 +775,7 @@ const _pyplot_attr = merge_with_base_supported([
:tick_direction,
:camera,
:contour_labels,
:connections,
])
const _pyplot_seriestype = [
:path,
@@ -793,6 +792,7 @@ const _pyplot_seriestype = [
:contour3d,
:path3d,
:scatter3d,
:mesh3d,
:surface,
:wireframe,
]
@@ -860,6 +860,7 @@ const _gaston_attr = merge_with_base_supported([
# :framestyle,
# :camera,
# :contour_labels,
:connections,
])
const _gaston_seriestype = [
@@ -910,16 +911,22 @@ const _gaston_scale = [:identity, :ln, :log2, :log10]
# unicodeplots
const _unicodeplots_attr = merge_with_base_supported([
:annotations,
:bins,
:guide,
# :grid,
:label,
:layout,
:legend,
:seriescolor,
:seriesalpha,
:lims,
:linealpha,
:linecolor,
:linestyle,
:markershape,
:bins,
:seriesalpha,
:seriescolor,
:scale,
:title,
:guide,
:lims,
])
const _unicodeplots_seriestype = [
:path,
@@ -932,7 +939,34 @@ const _unicodeplots_seriestype = [
:spy,
]
const _unicodeplots_style = [:auto, :solid]
const _unicodeplots_marker = [:none, :auto, :circle]
const _unicodeplots_marker = [
:none,
:auto,
:pixel,
# vvvvvvvvvv shapes
:circle,
:rect,
:star5,
:diamond,
:hexagon,
:cross,
:xcross,
:utriangle,
:dtriangle,
:rtriangle,
:ltriangle,
:pentagon,
# :heptagon,
# :octagon,
:star4,
:star6,
# :star7,
:star8,
:vline,
:hline,
:+,
:x,
]
const _unicodeplots_scale = [:identity, :ln, :log2, :log10]
# Additional constants
@@ -943,11 +977,11 @@ const _canvas_type = Ref(:auto)
const _hdf5_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
:foreground_color_grid,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_title,
:foreground_color_axis,
:foreground_color_border,
@@ -1045,11 +1079,11 @@ const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing)
const _inspectdr_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
# :foreground_color_grid,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_title,
:foreground_color_axis,
:foreground_color_border,
@@ -1082,9 +1116,9 @@ const _inspectdr_attr = merge_with_base_supported([
:titlefontfamily,
:titlefontsize,
:titlefontcolor,
:legendfontfamily,
:legendfontsize,
:legendfontcolor,
:legend_font_family,
:legend_font_pointsize,
:legend_font_color,
:tickfontfamily,
:tickfontsize,
:tickfontcolor,
@@ -1092,7 +1126,7 @@ const _inspectdr_attr = merge_with_base_supported([
:guidefontsize,
:guidefontcolor,
:grid,
:legend, #:colorbar,
:legend_position, #:colorbar,
# :marker_z,
# :line_z,
# :levels,
@@ -1148,10 +1182,10 @@ const _inspectdr_scale = [:identity, :ln, :log2, :log10]
const _pgfplotsx_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:legend_background_color,
:background_color_inside,
:background_color_outside,
:foreground_color_legend,
:legend_foreground_color,
:foreground_color_grid,
:foreground_color_axis,
:foreground_color_text,
@@ -1188,12 +1222,12 @@ const _pgfplotsx_attr = merge_with_base_supported([
:titlefontvalign,
:titlefontrotation,
:titlefontcolor,
:legendfontfamily,
:legendfontsize,
:legendfonthalign,
:legendfontvalign,
:legendfontrotation,
:legendfontcolor,
:legend_font_family,
:legend_font_pointsize,
:legend_font_halign,
:legend_font_valign,
:legend_font_rotation,
:legend_font_color,
:tickfontfamily,
:tickfontsize,
:tickfonthalign,
@@ -1210,8 +1244,8 @@ const _pgfplotsx_attr = merge_with_base_supported([
:gridalpha,
:gridstyle,
:gridlinewidth,
:legend,
:legendtitle,
:legend_position,
:legend_title,
:colorbar,
:colorbar_title,
:colorbar_entry,
@@ -1234,6 +1268,7 @@ const _pgfplotsx_attr = merge_with_base_supported([
:tick_direction,
:camera,
:contour_labels,
:connections,
])
const _pgfplotsx_seriestype = [
:path,
+7 -7
View File
@@ -227,7 +227,7 @@ function pgf_series(sp::Subplot, series::Series)
end
# add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if i == 1 && sp[:legend_position] != :none && should_add_to_legend(series)
if plotattributes[:fillrange] !== nothing
push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
@@ -590,12 +590,12 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
kw[:axisEqual] = "true"
end
legpos = sp[:legend]
legpos = sp[:legend_position]
if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos]
end
cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend]))
fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
cstr, bg_alpha = pgf_color(plot_color(sp[:legend_background_color]))
fg_alpha = alpha(plot_color(sp[:legend_foreground_color]))
push!(
style,
@@ -603,16 +603,16 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
"legend style = {",
pgf_linestyle(
pgf_thickness_scaling(sp),
sp[:foreground_color_legend],
sp[:legend_foreground_color],
fg_alpha,
"solid",
),
",",
"fill = $cstr,",
"fill opacity = $bg_alpha,",
"text opacity = $(alpha(plot_color(sp[:legendfontcolor]))),",
"text opacity = $(alpha(plot_color(sp[:legend_font_color]))),",
"font = ",
pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)),
pgf_font(sp[:legend_font_pointsize], pgf_thickness_scaling(sp)),
"}",
),
)
+6 -6
View File
@@ -290,7 +290,7 @@ function gaston_seriesconf!(
ps: pointscale
pt: pointtype
tc: textcolor
w: with
w: with
=#
gsp = sp.o
st = series[:seriestype]
@@ -307,7 +307,7 @@ function gaston_seriesconf!(
fr = series[:fillrange]
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i))
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
if fr !== nothing # filled curves, but not filled curves with markers
if fr !== nothing # filled curves, but not filled curves with markers
push!(
curveconf,
"w filledcurves fc $fc fs solid border lc $lc lw $lw dt $dt,'' w lines lc $lc lw $lw dt $dt",
@@ -505,8 +505,8 @@ function gaston_set_ticks!(axesconf, ticks, letter, maj_min, add)
end
function gaston_set_legend!(axesconf, sp, any_label)
leg = sp[:legend]
if sp[:legend] (:none, :inline) && any_label
leg = sp[:legend_position]
if sp[:legend_position] (:none, :inline) && any_label
leg == :best && (leg = :topright)
push!(
@@ -517,9 +517,9 @@ function gaston_set_legend!(axesconf, sp, any_label)
occursin(position, string(leg)) && push!(axesconf, "set key $position")
end
push!(axesconf, "set key $(gaston_font(legendfont(sp), rot=false, align=false))")
if sp[:legendtitle] !== nothing
if sp[:legend_title] !== nothing
# NOTE: cannot use legendtitlefont(sp) as it will override legendfont
push!(axesconf, "set key title '$(sp[:legendtitle])'")
push!(axesconf, "set key title '$(sp[:legend_title])'")
end
push!(axesconf, "set key box lw 1 opaque")
push!(axesconf, "set border back")
+190 -73
View File
@@ -104,6 +104,9 @@ function gr_color(c, ::Type{<:AbstractGray})
end
gr_color(c, ::Type) = gr_color(RGBA(c), RGB)
set_RGBA_alpha(alpha, c::RGBA) = RGBA(red(c), green(c), blue(c), alpha)
set_RGBA_alpha(alpha::Nothing, c::RGBA) = c
function gr_getcolorind(c)
gr_set_transparency(float(alpha(c)))
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
@@ -225,9 +228,8 @@ end
gr_inqtext(x, y, s) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s::AbstractString)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.inqmathtex(x, y, s[2:(end - 1)])
elseif occursin('\\', s) || occursin("10^{", s)
if (occursin('\\', s) || occursin("10^{", s)) &&
match(r".*\$[^\$]+?\$.*", String(s)) == nothing
GR.inqtextext(x, y, s)
else
GR.inqtext(x, y, s)
@@ -237,9 +239,8 @@ end
gr_text(x, y, s) = gr_text(x, y, string(s))
function gr_text(x, y, s::AbstractString)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.mathtex(x, y, s[2:(end - 1)])
elseif occursin('\\', s) || occursin("10^{", s)
if (occursin('\\', s) || occursin("10^{", s)) &&
match(r".*\$[^\$]+?\$.*", String(s)) == nothing
GR.textext(x, y, s)
else
GR.text(x, y, s)
@@ -570,6 +571,9 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims, viewport_plotare
ztick = 0.5 * GR.tick(zmin, zmax)
gr_set_line(1, :solid, plot_color(:black), sp)
if sp[:colorbar_scale] == :log10
GR.setscale(2)
end
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
title = if isa(sp[:colorbar_title], PlotText)
@@ -671,31 +675,19 @@ end
function gr_set_tickfont(sp, letter)
axis = sp[get_attr_symbol(letter, :axis)]
# invalidate alignment changes for small rotations (|θ| < 45°)
trigger(rot) = abs(sind(rot)) < abs(cosd(rot)) ? 0 : sign(rot)
rot = axis[:rotation]
if letter === :x || (RecipesPipeline.is3d(sp) && letter === :y)
halign = (:left, :hcenter, :right)[trigger(rot) + 2]
valign = (axis[:mirror] ? :bottom : :top, :vcenter)[trigger(abs(rot)) + 1]
else
halign = (axis[:mirror] ? :left : :right, :hcenter)[trigger(abs(rot)) + 1]
valign = (:top, :vcenter, :bottom)[trigger(rot) + 2]
end
gr_set_font(
tickfont(axis),
sp,
halign = halign,
valign = valign,
rotation = axis[:rotation],
color = axis[:tickfontcolor],
)
end
# size of the text with no rotation
function gr_text_size(str)
GR.savestate()
GR.selntran(0)
GR.setcharup(0, 1)
xs, ys = gr_inqtext(0, 0, string(str))
l, r = extrema(xs)
b, t = extrema(ys)
@@ -705,9 +697,11 @@ function gr_text_size(str)
return w, h
end
# size of the text with rotation applied
function gr_text_size(str, rot)
GR.savestate()
GR.selntran(0)
GR.setcharup(0, 1)
xs, ys = gr_inqtext(0, 0, string(str))
l, r = extrema(xs)
b, t = extrema(ys)
@@ -720,12 +714,21 @@ 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_3d_axis_angle(cvs, nt, ft, letter)
length(cvs) < 2 && return 0
tickpoints = [gr_w3tondc(sort_3d_axes(cv, nt, ft, letter)...) for cv in cvs]
dx = tickpoints[2][1] - tickpoints[1][1]
dy = tickpoints[2][2] - tickpoints[1][2]
return atand(dy, dx)
end
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)
w = NaNMath.max(w, wi)
h = NaNMath.max(h, hi)
end
return w, h
end
@@ -951,6 +954,9 @@ function get_z_normalized(z, clims...)
end
function gr_clims(args...)
if args[1][:clims] != :auto
return get_clims(args[1])
end
lo, hi = get_clims(args...)
if lo == hi
if lo == 0
@@ -1022,7 +1028,7 @@ end
## Legend
function gr_add_legend(sp, leg, viewport_plotarea)
if sp[:legend] (:none, :inline)
if !(sp[:legend_position] in (:none, :inline))
GR.savestate()
GR.selntran(0)
GR.setscale(0)
@@ -1030,14 +1036,14 @@ function gr_add_legend(sp, leg, viewport_plotarea)
if leg.w > 0
xpos, ypos = gr_legend_pos(sp, leg, viewport_plotarea)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
gr_set_fillcolor(sp[:background_color_legend])
gr_set_fillcolor(sp[:legend_background_color])
GR.fillrect(
xpos - leg.leftw,
xpos + leg.textw + leg.rightw,
ypos + leg.dy,
ypos - leg.h,
) # Allocating white space for actual legend width here
gr_set_line(1, :solid, sp[:foreground_color_legend], sp)
gr_set_line(1, :solid, sp[:legend_foreground_color], sp)
GR.drawrect(
xpos - leg.leftw,
xpos + leg.textw + leg.rightw,
@@ -1045,10 +1051,10 @@ function gr_add_legend(sp, leg, viewport_plotarea)
ypos - leg.h,
) # Drawing actual legend width here
i = 0
if sp[:legendtitle] !== nothing
if sp[:legend_title] !== nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_font(legendtitlefont(sp), sp)
gr_text(xpos - 0.03 + 0.5 * leg.w, ypos, string(sp[:legendtitle]))
gr_text(xpos - 0.03 + 0.5 * leg.w, ypos, string(sp[:legend_title]))
ypos -= leg.dy
gr_set_font(legendfont(sp), sp)
end
@@ -1057,7 +1063,7 @@ function gr_add_legend(sp, leg, viewport_plotarea)
should_add_to_legend(series) || continue
st = series[:seriestype]
lc = get_linecolor(series, clims)
gr_set_line(sp[:legendfontsize] / 8, get_linestyle(series), lc, sp)
gr_set_line(sp[:legend_font_pointsize] / 8, get_linestyle(series), lc, sp)
if (
(st == :shape || series[:fillrange] !== nothing) &&
@@ -1098,16 +1104,17 @@ function gr_add_legend(sp, leg, viewport_plotarea)
ms = first(series[:markersize])
msw = first(series[:markerstrokewidth])
s, sw = if ms > 0
0.8 * sp[:legendfontsize], 0.8 * sp[:legendfontsize] * msw / ms
0.8 * sp[:legend_font_pointsize],
0.8 * sp[:legend_font_pointsize] * msw / ms
else
0, 0.8 * sp[:legendfontsize] * msw / 8
0, 0.8 * sp[:legend_font_pointsize] * msw / 8
end
gr_draw_markers(series, xpos - leg.width_factor * 2, ypos, clims, s, sw)
end
lab = series[:label]
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
gr_set_textcolor(plot_color(sp[:legend_font_color]))
gr_text(xpos, ypos, string(lab))
ypos -= leg.dy
end
@@ -1118,7 +1125,7 @@ function gr_add_legend(sp, leg, viewport_plotarea)
end
function gr_legend_pos(sp::Subplot, leg, viewport_plotarea)
s = sp[:legend]
s = sp[:legend_position]
s isa Real && return gr_legend_pos(s, leg, viewport_plotarea)
if s isa Tuple{<:Real,Symbol}
if s[2] !== :outer
@@ -1235,24 +1242,29 @@ end
function gr_get_legend_geometry(viewport_plotarea, sp)
legendn = legendw = dy = 0
if sp[:legend] != :none
if sp[:legend_position] != :none
GR.savestate()
GR.selntran(0)
GR.setcharup(0, 1)
GR.setscale(0)
if sp[:legendtitle] !== nothing
if sp[:legend_title] !== nothing
gr_set_font(legendtitlefont(sp), sp)
legendn += 1
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
legendw = tbx[3] - tbx[1]
dy = tby[3] - tby[1]
tbx, tby = gr_inqtext(0, 0, string(sp[:legend_title]))
l, r = extrema(tbx)
b, t = extrema(tby)
legendw = r - l
dy = t - b
end
gr_set_font(legendfont(sp), sp)
for series in series_list(sp)
should_add_to_legend(series) || continue
legendn += 1
tbx, tby = gr_inqtext(0, 0, string(series[:label]))
legendw = max(legendw, tbx[3] - tbx[1]) # Holds text width right now
dy = max(dy, tby[3] - tby[1])
l, r = extrema(tbx)
b, t = extrema(tby)
legendw = max(legendw, r - l) # Holds text width right now
dy = max(dy, t - b)
end
GR.setscale(1)
@@ -1270,7 +1282,6 @@ function gr_get_legend_geometry(viewport_plotarea, sp)
y_legend_offset = (viewport_plotarea[4] - viewport_plotarea[3]) / 30
dy *= get(sp[:extra_kwargs], :legend_hfactor, 1)
legendh = dy * legendn
return (
@@ -1289,7 +1300,7 @@ end
## Viewport, window and scale
function gr_update_viewport_legend!(viewport_plotarea, sp, leg)
s = sp[:legend]
s = sp[:legend_position]
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
xmirror =
@@ -1338,7 +1349,7 @@ function gr_update_viewport_legend!(viewport_plotarea, sp, leg)
leg.h + leg.dy + leg.yoffset + !xmirror * gr_axis_height(sp, sp[:xaxis])
end
end
if s === :inline
if s == :inline
if sp[:yaxis][:mirror]
viewport_plotarea[1] += leg.w
else
@@ -1560,13 +1571,35 @@ function gr_label_ticks(sp, letter, ticks)
oamin, oamax = axis_limits(sp, oletter)
gr_set_tickfont(sp, letter)
out_factor = ifelse(axis[:tick_direction] === :out, 1.5, 1)
x_offset = isy ? -1.5e-2 * out_factor : 0
y_offset = isy ? 0 : -8e-3 * out_factor
x_base_offset = isy ? -1.5e-2 * out_factor : 0
y_base_offset = isy ? 0 : -8e-3 * out_factor
rot = axis[:rotation] % 360
ov = sp[:framestyle] == :origin ? 0 : xor(oaxis[:flip], axis[:mirror]) ? oamax : oamin
sgn = axis[:mirror] ? -1 : 1
sgn2 = iseven(Int(floor(rot / 90))) ? -1 : 1
sgn3 = if isy
-360 < rot < -180 || 0 < rot < 180 ? 1 : -1
else
rot < -270 || -90 < rot < 90 || rot > 270 ? 1 : -1
end
for (cv, dv) in zip(ticks...)
x, y = GR.wctondc(reverse_if((cv, ov), isy)...)
sz_rot = gr_text_size(dv, rot)
sz = gr_text_size(dv)
x_offset = x_base_offset
y_offset = y_base_offset
if isy
x_offset += -first(sz_rot) / 2
if rot % 90 != 0
y_offset += sgn2 * last(sz_rot) / 2 + sgn3 * last(sz) * cosd(rot) / 2
end
else
if rot % 90 != 0
x_offset += sgn2 * first(sz_rot) / 2 + sgn3 * last(sz) * sind(rot) / 2
end
y_offset += -last(sz_rot) / 2
end
gr_text(x + sgn * x_offset, y + sgn * y_offset, dv)
end
end
@@ -1577,6 +1610,9 @@ function gr_label_ticks_3d(sp, letter, ticks)
near_letter = letter in (:x, :z) ? :y : :x
far_letter = letter in (:x, :y) ? :z : :x
isy = letter === :y
isz = letter === :z
ax = sp[get_attr_symbol(letter, :axis)]
nax = sp[get_attr_symbol(near_letter, :axis)]
fax = sp[get_attr_symbol(far_letter, :axis)]
@@ -1584,7 +1620,7 @@ function gr_label_ticks_3d(sp, letter, ticks)
amin, amax = axis_limits(sp, letter)
namin, namax = axis_limits(sp, near_letter)
famin, famax = axis_limits(sp, far_letter)
n0, n1 = letter === :y ? (namax, namin) : (namin, namax)
n0, n1 = isy ? (namax, namin) : (namin, namax)
# find out which axes we are dealing with
i = findfirst(==(letter), (:x, :y, :z))
@@ -1601,27 +1637,57 @@ function gr_label_ticks_3d(sp, letter, ticks)
nt = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? n1 : n0
ft = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? famax : famin
xoffset = if letter === :x
(sp[:yaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:xaxis][:tick_direction] == :out ? 1.5 : 1)
elseif letter === :y
(sp[:yaxis][:mirror] ? -1 : 1) * 1e-2 * (sp[:yaxis][:tick_direction] == :out ? 1.5 : 1)
else
(sp[:zaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:zaxis][:tick_direction] == :out ? 1.5 : 1)
end
yoffset = if letter === :x
(sp[:xaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:xaxis][:tick_direction] == :out ? 1.5 : 1)
elseif letter === :y
(sp[:yaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:yaxis][:tick_direction] == :out ? 1.5 : 1)
else
0
end
rot = mod(ax[:rotation], 360)
sgn = ax[:mirror] ? -1 : 1
cvs, dvs = ticks
ax[:flip] && reverse!(cvs)
axisθ = isz ? 270 : mod(gr_get_3d_axis_angle(cvs, nt, ft, letter), 360) # issue: doesn't work with 1 tick
axisϕ = mod(axisθ - 90, 360)
out_factor = ifelse(ax[:tick_direction] === :out, 1.5, 1)
axisoffset = out_factor * 1.2e-2
x_base_offset = axisoffset * cosd(axisϕ)
y_base_offset = axisoffset * sind(axisϕ)
sgn2a = sgn2b = sgn3 = 0
if axisθ != 0 || rot % 90 != 0
sgn2a =
(axisθ != 90) && (axisθ == 0 && (rot < 90 || 180 rot < 270)) ||
(axisθ == 270) ||
(axisθ < 90 && (axisθ < rot < 90 || axisθ + 180 < rot < 270)) ||
(axisθ > 270 && (rot < 90 || axisθ - 180 < rot < 270 || rot > axisθ)) ? -1 : 1
end
if (axisθ - 90) % 180 != 0 || (rot - 90) % 180 != 0
sgn2b =
axisθ == 0 ||
(axisθ == 90 && (90 rot < 180 || 270 rot < 360)) ||
(axisθ == 270 && (rot < 90 || 180 rot < 270)) ||
(axisθ < 90 && (axisθ < rot < 180 || axisθ + 180 < rot)) ||
(axisθ > 270 && (rot < axisθ - 180 || 180 rot < axisθ)) ? -1 : 1
end
if !(axisθ == 0 && rot % 180 == 0) && ((rot - 90) % 180 != 0)
sgn3 =
(axisθ == 0 && 90 < rot < 270) ||
(axisθ == 90 && rot < 180) ||
(axisθ == 270 && rot > 180) ||
(axisθ < 90 && (rot < axisθ || 90 rot < 180 || axisθ + 180 < rot < 270)) ||
(axisθ > 270 && (90 rot < axisθ - 180 || 180 rot < 270 || rot > axisθ)) ?
-1 : 1
end
for (cv, dv) in zip((cvs, dvs)...)
xi, yi = gr_w3tondc(sort_3d_axes(cv, nt, ft, letter)...)
gr_text(xi + xoffset, yi + yoffset, dv)
sz_rot = gr_text_size(dv, rot)
sz = gr_text_size(dv)
x_offset =
x_base_offset + sgn2a * first(sz_rot) / 2 + sgn3 * last(sz) * sind(rot) / 2
y_offset =
y_base_offset + sgn2b * last(sz_rot) / 2 + sgn3 * last(sz) * cosd(rot) / 2
gr_text(xi + sgn * x_offset, yi + sgn * y_offset, dv)
end
end
@@ -1784,7 +1850,7 @@ function gr_add_series(sp, series)
elseif st in (:surface, :wireframe, :mesh3d)
gr_draw_surface(series, x, y, z, clims)
elseif st === :volume
sp[:legend] = :none
sp[:legend_position] = :none
GR.gr3.clear()
dmin, dmax = GR.gr3.volume(y.v, 0)
elseif st === :heatmap
@@ -1802,9 +1868,9 @@ function gr_add_series(sp, series)
gr_text(GR.wctondc(xi, yi)..., str)
end
if sp[:legend] == :inline && should_add_to_legend(series)
if sp[:legend_position] == :inline && should_add_to_legend(series)
gr_set_font(legendfont(sp), sp)
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
gr_set_textcolor(plot_color(sp[:legend_font_color]))
if sp[:yaxis][:mirror]
(_, i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x)
GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF)
@@ -1981,14 +2047,42 @@ function gr_draw_surface(series, x, y, z, clims)
GR.setfillcolorind(0)
GR.surface(x, y, z, get(e_kwargs, :display_option, GR.OPTION_FILLED_MESH))
elseif st === :mesh3d
@warn "GR: mesh3d is experimental (no face colors)"
gr_set_line(
get_linewidth(series),
get_linestyle(series),
get_linecolor(series),
series,
)
GR.polyline3d(mesh3d_triangles(x, y, z, series[:connections])...)
if series[:connections] isa AbstractVector{<:AbstractVector{Int}}
# Combination of any polygon types
cns = [[length(polyinds), polyinds...] for polyinds in series[:connections]]
elseif series[:connections] isa AbstractVector{NTuple{N,Int}} where {N}
# Only N-gons - connections have to be 1-based (indexing)
N = length(series[:connections][1])
cns = [[N, polyinds...] for polyinds in series[:connections]]
elseif series[:connections] isa NTuple{3,<:AbstractVector{Int}}
# Only triangles - connections have to be 0-based (indexing)
ci, cj, ck = series[:connections]
if !(length(ci) == length(cj) == length(ck))
throw(
ArgumentError(
"Argument connections must consist of equally sized arrays.",
),
)
end
cns = [([3, ci[i] + 1, cj[i] + 1, ck[i] + 1]) for i in eachindex(ci)]
else
throw(
ArgumentError(
"Unsupported `:connections` type $(typeof(series[:connections])) for seriestype=$st",
),
)
end
fillalpha = get_fillalpha(series)
n_polygons = length(cns)
facecolor = if series[:fillcolor] isa AbstractArray
series[:fillcolor]
else
fill(series[:fillcolor], n_polygons)
end
facecolor = map(fc -> set_RGBA_alpha(fillalpha, fc), facecolor)
GR.setborderwidth(get_linewidth(series))
GR.setbordercolorind(gr_getcolorind(get_linecolor(series)))
GR.polygonmesh3d(x, y, z, vcat(cns...), signed.(gr_color.(facecolor)))
else
throw(ArgumentError("Not handled !"))
end
@@ -2004,15 +2098,38 @@ function gr_draw_heatmap(series, x, y, z, clims)
# pdf output, and also supports alpha values.
# Note that drawimage draws uniformly spaced data correctly
# even on log scales, where it is visually non-uniform.
colors = plot_color.(get(fillgrad, z, clims), series[:fillalpha])
colors, _z = if series[:subplot][:colorbar_scale] == :identity
plot_color.(get(fillgrad, z, clims), series[:fillalpha]), z
elseif series[:subplot][:colorbar_scale] == :log10
z_log = replace(x -> isinf(x) ? NaN : x, log10.(z))
z_normalized = get_z_normalized.(z_log, log10.(clims)...)
plot_color.(map(z -> get(fillgrad, z), z_normalized), series[:fillalpha]), z_log
end
for i in eachindex(colors)
if isnan(_z[i])
colors[i] = set_RGBA_alpha(0, colors[i])
end
end
rgba = gr_color.(colors)
GR.drawimage(first(x), last(x), last(y), first(y), w, h, rgba)
else
if something(series[:fillalpha], 1) < 1
@warn "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored."
end
z_normalized = get_z_normalized.(z, clims...)
z_normalized, _z = if series[:subplot][:colorbar_scale] == :identity
get_z_normalized.(z, clims...), z
elseif series[:subplot][:colorbar_scale] == :log10
z_log = replace(x -> isinf(x) ? NaN : x, log10.(z))
get_z_normalized.(z_log, log10.(clims)...), z_log
end
rgba = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
background_color_ind =
gr_getcolorind(plot_color(series[:subplot][:background_color_inside]))
for i in eachindex(rgba)
if isnan(_z[i])
rgba[i] = background_color_ind
end
end
if !ispolar(series)
GR.nonuniformcellarray(x, y, w, h, rgba)
else
+9 -10
View File
@@ -70,7 +70,7 @@ function _inspectdr_add_annotations(plot, x, y, val::PlotText)
color = _inspectdr_mapcolor(val.font.color),
)
ann = InspectDR.atext(
val.str,
texmath2unicode(val.str),
x = x,
y = y,
font = fnt,
@@ -384,9 +384,9 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
_inspectdr_setticks(sp, plot, strip, xaxis, yaxis)
a = plot.annotation
a.title = sp[:title]
a.xlabel = xaxis[:guide]
a.ylabels = [yaxis[:guide]]
a.title = texmath2unicode(sp[:title])
a.xlabel = texmath2unicode(xaxis[:guide])
a.ylabels = [texmath2unicode(yaxis[:guide])]
#Modify base layout of new object:
l = plot.layout.defaults = deepcopy(InspectDR.defaults.plotlayout)
@@ -411,15 +411,14 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
_inspectdr_mapptsize(xaxis[:tickfontsize]),
color = _inspectdr_mapcolor(xaxis[:tickfontcolor]),
)
l.enable_legend = (sp[:legend] != :none)
l.enable_legend = (sp[:legend_position] != :none)
#l.halloc_legend = 150 #TODO: compute???
l.font_legend = InspectDR.Font(
sp[:legendfontfamily],
_inspectdr_mapptsize(sp[:legendfontsize]),
color = _inspectdr_mapcolor(sp[:legendfontcolor]),
sp[:legend_font_family],
_inspectdr_mapptsize(sp[:legend_font_pointsize]),
color = _inspectdr_mapcolor(sp[:legend_font_color]),
)
l.frame_legend.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
l.frame_legend.fillcolor = _inspectdr_mapcolor(sp[:legend_background_color])
#_round!() ensures values use integer spacings (looks better on screen):
InspectDR._round!(InspectDR.autofit2font!(l, legend_width = 10.0)) #10 "em"s wide
return
+63 -35
View File
@@ -141,9 +141,12 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
title_loc = sp[:titlelocation]
bgc_inside = plot_color(sp[:background_color_inside])
bgc_inside_a = alpha(bgc_inside)
update_clims(sp)
axis_opt = PGFPlotsX.Options(
"point meta max" => get_clims(sp)[2],
"point meta min" => get_clims(sp)[1],
"legend cell align" => "left",
"legend columns" => pgfx_legend_col(sp[:legend_position]),
"title" => sp[:title],
"title style" => PGFPlotsX.Options(
pgfx_get_title_pos(title_loc)...,
@@ -203,7 +206,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
if hascolorbar(sp)
cticks = get_colorbar_ticks(sp)[2]
colorbar_style = PGFPlotsX.Options("title" => sp[:colorbar_title])
colorbar_style = PGFPlotsX.Options("ylabel" => sp[:colorbar_title])
if sp[:colorbar] === :top
push!(
colorbar_style,
@@ -245,12 +248,18 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
extra_sp = wraptuple(extra_sp)
push!(axis, extra_sp...)
end
if sp[:legendtitle] !== nothing
if sp[:legend_title] !== nothing
legtfont = legendtitlefont(sp)
push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing))
push!(
axis,
PGFPlotsX.LegendEntry(
string("\\hspace{-.6cm}{\\textbf{", sp[:legendtitle], "}}"),
PGFPlotsX.Options(
"font" =>
pgfx_font(legtfont.pointsize, pgfx_thickness_scaling(sp)),
"text" => legtfont.color,
),
string("\\hspace{-.6cm}{\\textbf{", sp[:legend_title], "}}"),
false,
),
)
@@ -375,11 +384,9 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
)
end
end
if (
k == 1 &&
series[:subplot][:legend] != :none &&
pgfx_should_add_to_legend(series)
)
if i == 1 &&
series[:subplot][:legend_position] != :none &&
pgfx_should_add_to_legend(series)
pgfx_filllegend!(series_opt, opt)
end
end
@@ -512,10 +519,29 @@ function pgfx_add_series!(::Val{:heatmap}, axis, series_opt, series, series_func
end
function pgfx_add_series!(::Val{:mesh3d}, axis, series_opt, series, series_func, opt)
ptable = join(
[string(i, " ", j, " ", k, "\\\\") for (i, j, k) in zip(opt[:connections]...)],
"\n ",
)
if opt[:connections] isa Tuple{Array,Array,Array}
# 0-based indexing
ptable = join(
[string(i, " ", j, " ", k, "\\\\") for (i, j, k) in zip(opt[:connections]...)],
"\n ",
)
elseif typeof(opt[:connections]) <: AbstractVector{NTuple{3,Int}}
# 1-based indexing
ptable = join(
[
string(i - 1, " ", j - 1, " ", k - 1, "\\\\") for
(i, j, k) in opt[:connections]
],
"\n ",
)
else
throw(
ArgumentError(
"Argument connections has to be either a tuple of three arrays (0-based indexing)
or an AbstractVector{NTuple{3,Int}} (1-based indexing).",
),
)
end
push!(
series_opt,
"patch" => nothing,
@@ -633,7 +659,7 @@ function pgfx_add_series!(::Val{:xsticks}, axis, series_opt, series, series_func
end
function pgfx_add_legend!(axis, series, opt, i = 1)
if series[:subplot][:legend] != :none
if series[:subplot][:legend_position] != :none
leg_entry = if opt[:label] isa AVec
get(opt[:label], i, "")
elseif opt[:label] isa AbstractString
@@ -780,22 +806,22 @@ function pgfx_get_legend_pos(v::Tuple{S,Symbol}) where {S<:Real}
end
function pgfx_get_legend_style(sp)
cstr = plot_color(sp[:background_color_legend])
cstr = plot_color(sp[:legend_background_color])
a = alpha(cstr)
fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
fg_alpha = alpha(plot_color(sp[:legend_foreground_color]))
legfont = legendfont(sp)
PGFPlotsX.Options(
pgfx_linestyle(
pgfx_thickness_scaling(sp),
sp[:foreground_color_legend],
sp[:legend_foreground_color],
fg_alpha,
"solid",
) => nothing,
"fill" => cstr,
"fill opacity" => a,
"text opacity" => alpha(plot_color(sp[:legendfontcolor])),
"font" => pgfx_font(sp[:legendfontsize], pgfx_thickness_scaling(sp)),
"text" => plot_color(sp[:legendfontcolor]),
"text opacity" => alpha(plot_color(sp[:legend_font_color])),
"font" => pgfx_font(sp[:legend_font_pointsize], pgfx_thickness_scaling(sp)),
"text" => plot_color(sp[:legend_font_color]),
"cells" => PGFPlotsX.Options(
"anchor" => get(
(left = "west", right = "east", hcenter = "center"),
@@ -803,7 +829,7 @@ function pgfx_get_legend_style(sp)
"west",
),
),
pgfx_get_legend_pos(sp[:legend])...,
pgfx_get_legend_pos(sp[:legend_position])...,
)
end
@@ -929,6 +955,9 @@ function pgfx_linestyle(linewidth::Real, color, α = 1, linestyle = :solid)
)
end
pgfx_legend_col(s::Symbol) = s == :horizontal ? -1 : 1
pgfx_legend_col(n) = n
function pgfx_linestyle(plotattributes, i = 1)
lw = pgfx_thickness_scaling(plotattributes) * get_linewidth(plotattributes, i)
lc = single_color(get_linecolor(plotattributes, i))
@@ -950,21 +979,20 @@ function pgfx_font(fontsize::Nothing, thickness_scaling = 1, font = "\\selectfon
end
function pgfx_should_add_to_legend(series::Series)
series.plotattributes[:primary] &&
!(
series.plotattributes[:seriestype] in (
:hexbin,
:bins2d,
:histogram2d,
:hline,
:vline,
:contour,
:contourf,
:contour3d,
:heatmap,
:image,
)
series.plotattributes[:primary] && !(
series.plotattributes[:seriestype] in (
:hexbin,
:bins2d,
:histogram2d,
:hline,
:vline,
:contour,
:contourf,
:contour3d,
:heatmap,
:image,
)
)
end
function pgfx_marker(plotattributes, i = 1)
@@ -1425,7 +1453,7 @@ end
# Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PGFPlotsXBackend})
leg = sp[:legend]
leg = sp[:legend_position]
if leg in (:best, :outertopright, :outerright, :outerbottomright) ||
(leg isa Tuple && leg[1] >= 1)
sp.minpad = (0mm, 0mm, 5mm, 0mm)
+25 -13
View File
@@ -338,12 +338,12 @@ function plotly_layout(plt::Plot)
end
function plotly_add_legend!(plotattributes_out::KW, sp::Subplot)
plotattributes_out[:showlegend] = sp[:legend] != :none
legend_position = plotly_legend_pos(sp[:legend])
if sp[:legend] != :none
plotattributes_out[:legend] = KW(
:bgcolor => rgba_string(sp[:background_color_legend]),
:bordercolor => rgba_string(sp[:foreground_color_legend]),
plotattributes_out[:showlegend] = sp[:legend_position] != :none
legend_position = plotly_legend_pos(sp[:legend_position])
if sp[:legend_position] != :none
plotattributes_out[:legend_position] = KW(
:bgcolor => rgba_string(sp[:legend_background_color]),
:bordercolor => rgba_string(sp[:legend_foreground_color]),
:borderwidth => 1,
:traceorder => "normal",
:xanchor => legend_position.xanchor,
@@ -353,7 +353,7 @@ function plotly_add_legend!(plotattributes_out::KW, sp::Subplot)
:x => legend_position.coords[1],
:y => legend_position.coords[2],
:title => KW(
:text => sp[:legendtitle] === nothing ? "" : string(sp[:legendtitle]),
:text => sp[:legend_title] === nothing ? "" : string(sp[:legend_title]),
:font => plotly_font(legendtitlefont(sp)),
),
)
@@ -362,6 +362,7 @@ end
function plotly_legend_pos(pos::Symbol)
xleft = 0.07
xright = 1.0
ybot = 0.07
ytop = 1.0
xcenter = 0.55
@@ -372,14 +373,14 @@ function plotly_legend_pos(pos::Symbol)
xouterright = 1.05
xouterleft = -0.15
plotly_legend_position_mapping = (
right = (coords = [1.0, ycenter], xanchor = "right", yanchor = "middle"),
right = (coords = [xright, ycenter], xanchor = "right", yanchor = "middle"),
left = (coords = [xleft, ycenter], xanchor = "left", yanchor = "middle"),
top = (coords = [xcenter, ytop], xanchor = "center", yanchor = "top"),
bottom = (coords = [xcenter, ybot], xanchor = "center", yanchor = "bottom"),
bottomleft = (coords = [xleft, ybot], xanchor = "left", yanchor = "bottom"),
bottomright = (coords = [1.0, ybot], xanchor = "right", yanchor = "bottom"),
topright = (coords = [1.0, 1.0], xanchor = "right", yanchor = "top"),
topleft = (coords = [xleft, 1.0], xanchor = "left", yanchor = "top"),
bottomright = (coords = [xright, ybot], xanchor = "right", yanchor = "bottom"),
topright = (coords = [xright, ytop], xanchor = "right", yanchor = "top"),
topleft = (coords = [xleft, ytop], xanchor = "left", yanchor = "top"),
outertop = (coords = [center, youtertop], xanchor = "upper", yanchor = "middle"),
outerbottom = (coords = [center, youterbot], xanchor = "lower", yanchor = "middle"),
outerleft = (coords = [xouterleft, center], xanchor = "left", yanchor = "top"),
@@ -400,7 +401,7 @@ function plotly_legend_pos(pos::Symbol)
xanchor = "lower",
yanchor = "right",
),
default = (coords = [1.0, 1.0], xanchor = "auto", yanchor = "auto"),
default = (coords = [xright, ytop], xanchor = "auto", yanchor = "auto"),
)
legend_position =
@@ -678,6 +679,7 @@ function plotly_series(plt::Plot, series::Series)
if series[:connections] !== nothing
if typeof(series[:connections]) <: Tuple{Array,Array,Array}
# 0-based indexing
i, j, k = series[:connections]
if !(length(i) == length(j) == length(k))
throw(
@@ -689,10 +691,20 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:i] = i
plotattributes_out[:j] = j
plotattributes_out[:k] = k
elseif typeof(series[:connections]) <: AbstractVector{NTuple{3,Int}}
# 1-based indexing
i, j, k = broadcast(
i -> [inds[i] - 1 for inds in series[:connections]],
(1, 2, 3),
)
plotattributes_out[:i] = i
plotattributes_out[:j] = j
plotattributes_out[:k] = k
else
throw(
ArgumentError(
"Argument connections has to be a tuple of three arrays.",
"Argument connections has to be either a tuple of three arrays (0-based indexing)
or an AbstractVector{NTuple{3,Int}} (1-based indexing).",
),
)
end
+112 -39
View File
@@ -26,9 +26,25 @@ pyrcparams = PyPlot.PyDict(PyPlot.matplotlib."rcParams")
# "support" matplotlib v3.4
if PyPlot.version < v"3.4"
@warn("You are using Matplotlib $(PyPlot.version), which is no longer
@warn("""You are using Matplotlib $(PyPlot.version), which is no longer
officialy supported by the Plots community. To ensure smooth Plots.jl
integration update your Matplotlib library to a version >= 3.4.0")
integration update your Matplotlib library to a version >= 3.4.0
If you have used Conda.jl to install PyPlot (default installation),
upgrade your matplotlib via Conda.jl and rebuild the PyPlot.
If you are not sure, here are the default instructions:
In Julia REPL:
```
import Pkg;
Pkg.add("Conda")
import Conda
Conda.update()
Pkg.build("PyPlot")
```
""")
end
set_facecolor_sym = if PyPlot.version < v"2"
@@ -682,6 +698,50 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
end
if st == :mesh3d
polygons = if series[:connections] isa AbstractVector{<:AbstractVector{Int}}
# Combination of any polygon types
broadcast(inds -> broadcast(i -> [x[i], y[i], z[i]], inds), series[:connections])
elseif series[:connections] isa AbstractVector{NTuple{N,Int}} where {N}
# Only N-gons - connections have to be 1-based (indexing)
broadcast(inds -> broadcast(i -> [x[i], y[i], z[i]], inds), series[:connections])
elseif series[:connections] isa NTuple{3,<:AbstractVector{Int}}
# Only triangles - connections have to be 0-based (indexing)
ci, cj, ck = series[:connections]
if !(length(ci) == length(cj) == length(ck))
throw(
ArgumentError(
"Argument connections must consist of equally sized arrays.",
),
)
end
broadcast(
j -> broadcast(i -> [x[i], y[i], z[i]], [ci[j] + 1, cj[j] + 1, ck[j] + 1]),
eachindex(ci),
)
else
throw(
ArgumentError(
"Unsupported `:connections` type $(typeof(series[:connections])) for seriestype=$st",
),
)
end
col = mplot3d.art3d.Poly3DCollection(
polygons,
linewidths = py_thickness_scale(plt, series[:linewidth]),
edgecolor = py_color(get_linecolor(series)),
facecolor = py_color(series[:fillcolor]),
alpha = get_fillalpha(series),
zorder = series[:series_plotindex],
)
handle = ax."add_collection3d"(col)
# Fix for handle: https://stackoverflow.com/questions/54994600/pyplot-legend-poly3dcollection-object-has-no-attribute-edgecolors2d
# It seems there aren't two different alpha values for edge and face
handle._facecolors2d = py_color(series[:fillcolor])
handle._edgecolors2d = py_color(get_linecolor(series))
push!(handles, handle)
end
if st == :image
xmin, xmax = ignorenan_extrema(series[:x])
ymin, ymax = ignorenan_extrema(series[:y])
@@ -921,7 +981,7 @@ end
function py_set_spine_color(spines, color)
for loc in spines
spines[loc]."set_color"(color)
getproperty(spines, loc)."set_color"(color)
end
end
@@ -1146,7 +1206,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
if !ispolar(sp) && !RecipesPipeline.is3d(sp)
for pos in ("left", "right", "top", "bottom")
# Scale all axes by default first
ax.spines[pos]."set_linewidth"(py_thickness_scale(plt, 1))
getproperty(ax.spines, pos)."set_linewidth"(py_thickness_scale(plt, 1))
end
# Then set visible some of them
@@ -1154,28 +1214,32 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
intensity = 0.5
spine = sp[:yaxis][:mirror] ? "left" : "right"
ax.spines[spine]."set_alpha"(intensity)
ax.spines[spine]."set_linewidth"(py_thickness_scale(plt, intensity))
getproperty(ax.spines, spine)."set_alpha"(intensity)
getproperty(ax.spines, spine)."set_linewidth"(
py_thickness_scale(plt, intensity),
)
spine = sp[:xaxis][:mirror] ? "bottom" : "top"
ax.spines[spine]."set_linewidth"(py_thickness_scale(plt, intensity))
ax.spines[spine]."set_alpha"(intensity)
getproperty(ax.spines, spine)."set_linewidth"(
py_thickness_scale(plt, intensity),
)
getproperty(ax.spines, spine)."set_alpha"(intensity)
elseif sp[:framestyle] == :box
ax.tick_params(top = true) # Add ticks too
ax.tick_params(right = true) # Add ticks too
elseif sp[:framestyle] in (:axes, :origin)
sp[:xaxis][:mirror] ? ax.spines["bottom"]."set_visible"(false) :
ax.spines["top"]."set_visible"(false)
sp[:yaxis][:mirror] ? ax.spines["left"]."set_visible"(false) :
ax.spines["right"]."set_visible"(false)
sp[:xaxis][:mirror] ? ax.spines."bottom"."set_visible"(false) :
ax.spines."top"."set_visible"(false)
sp[:yaxis][:mirror] ? ax.spines."left"."set_visible"(false) :
ax.spines."right"."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)
if PyPlot.version >= v"3.4.1" # that is one where it worked, the API change may have some other value
for spine in ax.spines
ax.spines[string(spine)]."set_visible"(false)
getproperty(ax.spines, string(spine))."set_visible"(false)
end
else
for (loc, spine) in ax.spines
@@ -1219,7 +1283,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
end
py_set_scale(ax, sp, axis)
axis[:ticks] == :native ? nothing : py_set_lims(ax, sp, axis)
py_set_lims(ax, sp, axis)
if ispolar(sp) && letter == :y
ax."set_rlabel_position"(90)
end
@@ -1254,7 +1318,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
)
end
axis[:ticks] == :native ? nothing : py_set_ticks(sp, ax, ticks, letter)
py_set_ticks(sp, ax, ticks, letter)
if axis[:ticks] == :native # It is easier to reset than to account for this
py_set_lims(ax, sp, axis)
pyaxis.set_major_locator(pyticker.AutoLocator())
pyaxis.set_major_formatter(pyticker.ScalarFormatter())
end
# Tick marks
intensity = 0.5 # This value corresponds to scaling of other grid elements
pyaxis."set_tick_params"(
@@ -1339,11 +1410,11 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
if !sp[:xaxis][:showaxis]
kw = KW()
if ispolar(sp)
ax.spines["polar"].set_visible(false)
ax.spines."polar".set_visible(false)
end
for dir in (:top, :bottom)
if !ispolar(sp)
ax.spines[string(dir)].set_visible(false)
getproperty(ax.spines, string(dir)).set_visible(false)
end
kw[dir] = kw[get_attr_symbol(:label, dir)] = false
end
@@ -1353,7 +1424,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw = KW()
for dir in (:left, :right)
if !ispolar(sp)
ax.spines[string(dir)].set_visible(false)
getproperty(ax.spines, string(dir)).set_visible(false)
end
kw[dir] = kw[get_attr_symbol(:label, dir)] = false
end
@@ -1495,7 +1566,7 @@ end
py_legend_bbox(pos) = pos
function py_add_legend(plt::Plot, sp::Subplot, ax)
leg = sp[:legend]
leg = sp[:legend_position]
if leg != :none
# gotta do this to ensure both axes are included
labels = []
@@ -1556,7 +1627,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
),
linewidth = py_thickness_scale(
plt,
hasline * sp[:legendfontsize] / 8,
hasline * sp[:legend_font_pointsize] / 8,
),
linestyle = py_linestyle(:path, get_linestyle(series)),
solid_capstyle = "butt",
@@ -1564,7 +1635,10 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
dash_capstyle = "butt",
dash_joinstyle = "miter",
marker = py_marker(_cycle(series[:markershape], 1)),
markersize = py_thickness_scale(plt, 0.8 * sp[:legendfontsize]),
markersize = py_thickness_scale(
plt,
0.8 * sp[:legend_font_pointsize],
),
markeredgecolor = py_color(
single_color(get_markerstrokecolor(series)),
get_markerstrokealpha(series),
@@ -1575,8 +1649,9 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
),
markeredgewidth = py_thickness_scale(
plt,
0.8 * get_markerstrokewidth(series) * sp[:legendfontsize] /
first(series[:markersize]),
0.8 *
get_markerstrokewidth(series) *
sp[:legend_font_pointsize] / first(series[:markersize]),
), # retain the markersize/markerstroke ratio from the markers on the plot
)
push!(handles, handle)
@@ -1596,34 +1671,32 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
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])),
fontsize = py_thickness_scale(plt, sp[:legend_font_pointsize]),
facecolor = py_color(sp[:legend_background_color]),
edgecolor = py_color(sp[:legend_foreground_color]),
framealpha = alpha(plot_color(sp[:legend_background_color])),
fancybox = false, # makes the legend box square
borderpad = 0.8, # to match GR legendbox
)
frame = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000)
if sp[:legendtitle] !== nothing
leg."set_title"(sp[:legendtitle])
if sp[:legend_title] !== nothing
leg."set_title"(sp[:legend_title])
PyPlot.plt."setp"(
leg."get_title"(),
color = py_color(sp[:legendtitlefontcolor]),
family = sp[:legendtitlefontfamily],
math_fontfamily = py_get_matching_math_font(sp[:legendtitlefontfamily]),
fontsize = py_thickness_scale(plt, sp[:legendtitlefontsize]),
color = py_color(sp[:legend_title_font_color]),
family = sp[:legend_title_font_family],
fontsize = py_thickness_scale(plt, sp[:legend_title_font_pointsize]),
)
end
for txt in leg."get_texts"()
PyPlot.plt."setp"(
txt,
color = py_color(sp[:legendfontcolor]),
family = sp[:legendfontfamily],
math_fontfamily = py_get_matching_math_font(sp[:legendtitlefontfamily]),
fontsize = py_thickness_scale(plt, sp[:legendfontsize]),
color = py_color(sp[:legend_font_color]),
family = sp[:legend_font_family],
fontsize = py_thickness_scale(plt, sp[:legend_font_pointsize]),
)
end
end
+90 -60
View File
@@ -1,12 +1,10 @@
# https://github.com/JuliaPlots/UnicodePlots.jl
# don't warn on unsupported... there's just too many warnings!!
warn_on_unsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
warn_on_unsupported_args(::UnicodePlotsBackend, plotattributes) = nothing
# --------------------------------------------------------------------------------------
_canvas_map() = (
# ------------------------------------------------------------------------------------------
const _canvas_map = (
ascii = UnicodePlots.AsciiCanvas,
block = UnicodePlots.BlockCanvas,
braille = UnicodePlots.BrailleCanvas,
@@ -16,59 +14,78 @@ _canvas_map() = (
lookup = UnicodePlots.LookupCanvas,
)
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
# do all the magic here... build it all at once,
# since we need to know about all the series at the very beginning
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend})
plt.o = UnicodePlots.Plot[]
canvas_map = _canvas_map()
for sp in plt.subplots
xaxis = sp[:xaxis]
yaxis = sp[:yaxis]
xlim = axis_limits(sp, :x)
ylim = axis_limits(sp, :y)
xlim = collect(axis_limits(sp, :x))
ylim = collect(axis_limits(sp, :y))
# make vectors
xlim = [xlim[1], xlim[2]]
ylim = [ylim[1], ylim[2]]
# we set x/y to have a single point, since we need to create the plot with some data.
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown
# we set x/y to have a single point,
# since we need to create the plot with some data.
# since this point is at the bottom left corner of the plot,
# it shouldn't actually be shown
x = Float64[xlim[1]]
y = Float64[ylim[1]]
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
# create a plot window with xlim/ylim set,
# but the X/Y vectors are outside the bounds
canvas_type = if (ct = _canvas_type[]) == :auto
isijulia() ? :ascii : :braille
else
ct
end
o = UnicodePlots.Plot(
x,
y,
canvas_map[canvas_type];
title = sp[:title],
kw = (
compact = true,
title = texmath2unicode(sp[:title]),
xlabel = texmath2unicode(xaxis[:guide]),
ylabel = texmath2unicode(yaxis[:guide]),
xscale = xaxis[:scale],
yscale = yaxis[:scale],
border = isijulia() ? :ascii : :solid,
xlim = xlim,
ylim = ylim,
xlabel = xaxis[:guide],
ylabel = yaxis[:guide],
border = isijulia() ? :ascii : :solid,
)
o = UnicodePlots.Plot(x, y, _canvas_map[canvas_type]; kw...)
for series in series_list(sp)
o = addUnicodeSeries!(sp, o, series, sp[:legend] != :none, xlim, ylim)
o = addUnicodeSeries!(sp, o, kw, series, sp[:legend_position] != :none)
end
for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...)
o = UnicodePlots.annotate!(
o,
x,
y,
texmath2unicode(val.str);
color = up_color(val.font.color),
halign = val.font.halign,
valign = val.font.valign,
)
end
push!(plt.o, o) # save the object
end
end
up_color(col::UnicodePlots.UserColorType) = col
up_color(col::RGBA) =
(c = convert(ARGB32, col); map(Int, (red(c).i, green(c).i, blue(c).i)))
up_color(col) = :auto
# add a single series
function addUnicodeSeries!(
sp::Subplot{UnicodePlotsBackend},
up::UnicodePlots.Plot,
kw,
series,
addlegend::Bool,
xlim,
ylim,
)
st = series[:seriestype]
@@ -83,25 +100,29 @@ function addUnicodeSeries!(
# special handling (src/interface)
if st == :histogram2d
return UnicodePlots.densityplot(x, y)
kw[:xlim][:] .= kw[:ylim][:] .= 0
return UnicodePlots.densityplot(x, y; kw...)
elseif st == :heatmap
rng = range(0, 1, length = length(UnicodePlots.COLOR_MAP_DATA[:viridis]))
cmap = [(red(c), green(c), blue(c)) for c in get(get_colorgradient(series), rng)]
return UnicodePlots.heatmap(
series[:z].surf;
title = sp[:title],
zlabel = sp[:colorbar_title],
colormap = cmap,
kw...,
)
elseif st == :spy
return UnicodePlots.spy(series[:z].surf; title = sp[:title])
return UnicodePlots.spy(series[:z].surf; kw...)
end
series_kw = (;)
# now use the ! functions to add to the plot
if st in (:path, :straightline, :shape)
func = UnicodePlots.lineplot!
elseif st == :scatter || series[:markershape] != :none
func = UnicodePlots.scatterplot!
series_kw = (; marker = series[:markershape])
else
error("Series type $st not supported by UnicodePlots")
end
@@ -111,23 +132,35 @@ function addUnicodeSeries!(
for (n, segment) in enumerate(series_segments(series, st; check = true))
i, rng = segment.attr_index, segment.range
lc = get_linecolor(series, i)
if typeof(lc) <: UnicodePlots.UserColorType
color = lc
elseif typeof(lc) <: RGBA
lc = convert(ARGB32, lc)
color = map(Int, (red(lc).i, green(lc).i, blue(lc).i))
else
color = :auto
end
up = func(up, x[rng], y[rng]; color = color, name = n == 1 ? label : "")
up = func(
up,
x[rng],
y[rng];
color = up_color(lc),
name = n == 1 ? label : "",
series_kw...,
)
end
for (xi, yi, str, fnt) in EachAnn(series[:series_annotations], x, y)
up = UnicodePlots.annotate!(
up,
xi,
yi,
str;
color = up_color(fnt.color),
halign = fnt.halign,
valign = fnt.valign,
)
end
return up
end
# -------------------------------
# ------------------------------------------------------------------------------------------
# since this is such a hack, it's only callable using `png`... should error during normal `show`
# since this is such a hack, it's only callable using `png`...
# should error during normal `show`
function png(plt::Plot{UnicodePlotsBackend}, fn::AbstractString)
fn = addExtension(fn, "png")
@@ -135,17 +168,10 @@ function png(plt::Plot{UnicodePlotsBackend}, fn::AbstractString)
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
# BEGIN HACK
# wait while the plot gets drawn
sleep(0.5)
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
# use osx screen capture when my terminal is maximized
# and cursor starts at the bottom (I know, right?)
run(`screencapture -R50,600,700,420 $fn`)
# END HACK (phew)
return
elseif Sys.islinux()
run(`clear`)
@@ -155,12 +181,14 @@ function png(plt::Plot{UnicodePlotsBackend}, fn::AbstractString)
end
error(
"Can only savepng on MacOS or Linux with UnicodePlots (though even then I wouldn't do it)",
"Can only savepng on MacOS or Linux with UnicodePlots " *
"(though even then I wouldn't do it)",
)
end
# -------------------------------
Base.show(plt::Plot{UnicodePlotsBackend}) = _show(stdout, MIME("text/plain"), plt)
# ------------------------------------------------------------------------------------------
Base.show(plt::Plot{UnicodePlotsBackend}) = show(stdout, plt)
Base.show(io::IO, plt::Plot{UnicodePlotsBackend}) = _show(io, MIME("text/plain"), plt)
function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt)
@@ -168,9 +196,11 @@ function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
lines_colored = Array{Union{Nothing,Vector{String}}}(undef, nr, nc)
lines_uncolored = copy(lines_colored)
l_max = zeros(Int, nr)
w_max = zeros(Int, nc)
buf = IOBuffer()
cbuf = IOContext(buf, :color => true)
sps = wmax = 0
re_col = r"\x1B\[[0-9;]*[a-zA-Z]"
sps = 0
for r in 1:nr
lmax = 0
for c in 1:nc
@@ -184,27 +214,27 @@ function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
sp = plt.o[sps += 1]
show(cbuf, sp)
colored = String(take!(buf))
uncolored = replace(colored, r"\x1B\[[0-9;]*[a-zA-Z]" => "")
uncolored = replace(colored, re_col => "")
lines_colored[r, c] = lc = split(colored, "\n")
lines_uncolored[r, c] = lu = split(uncolored, "\n")
lmax = max(length(lc), lmax)
wmax = max(maximum(length.(lu)), wmax)
w_max[c] = max(maximum(length.(lu)), w_max[c])
end
end
end
l_max[r] = lmax
end
empty = ' '^wmax
empty = String[' '^w for w in w_max]
for r in 1:nr
for n in 1:l_max[r]
for c in 1:nc
pre = c == 1 ? '\0' : ' '
lc = lines_colored[r, c]
if lc === nothing || length(lc) < n
print(io, pre, empty)
print(io, pre, empty[c])
else
lu = lines_uncolored[r, c]
print(io, pre, lc[n], ' '^(wmax - length(lu[n])))
print(io, pre, lc[n], ' '^(w_max[c] - length(lu[n])))
end
end
println(io)
+38 -30
View File
@@ -5,50 +5,57 @@ process_clims(s::Union{Symbol,Nothing,Missing}) = ignorenan_extrema
# don't specialize on ::Function otherwise python functions won't work
process_clims(f) = f
function get_clims(sp::Subplot, op = process_clims(sp[:clims]))
get_clims(sp::Subplot)::Tuple{Float64,Float64} =
haskey(sp.attr, :clims_calculated) ? sp[:clims_calculated] : update_clims(sp)
get_clims(series::Series)::Tuple{Float64,Float64} =
haskey(series.plotattributes, :clims_calculated) ?
series[:clims_calculated]::Tuple{Float64,Float64} : update_clims(series)
get_clims(sp::Subplot, series::Series)::Tuple{Float64,Float64} =
series[:colorbar_entry] ? get_clims(sp) : get_clims(series)
function update_clims(sp::Subplot, op = process_clims(sp[:clims]))::Tuple{Float64,Float64}
zmin, zmax = Inf, -Inf
for series in series_list(sp)
if series[:colorbar_entry]
zmin, zmax = _update_clims(zmin, zmax, get_clims(series, op)...)
if series[:colorbar_entry]::Bool
zmin, zmax = _update_clims(zmin, zmax, update_clims(series, op)...)
else
update_clims(series, op)
end
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
function get_clims(sp::Subplot, series::Series, op = process_clims(sp[:clims]))
zmin, zmax = if series[:colorbar_entry]
get_clims(sp, op)
else
get_clims(series, op)
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
return sp[:clims_calculated] = zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
"""
get_clims(::Series, op=Plots.ignorenan_extrema)
update_clims(::Series, op=Plots.ignorenan_extrema)
Finds the limits for the colorbar by taking the "z-values" for the series and passing them into `op`,
which must return the tuple `(zmin, zmax)`. The default op is the extrema of the finite
values of the input.
values of the input. The value is stored as a series property, which is retrieved by `get_clims`.
"""
function get_clims(series::Series, op = ignorenan_extrema)
function update_clims(series::Series, op = ignorenan_extrema)::Tuple{Float64,Float64}
zmin, zmax = Inf, -Inf
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface, :hexbin)
for vals in (
series[:seriestype] in z_colored_series ? series[:z] : nothing,
series[:line_z],
series[:marker_z],
series[:fill_z],
)
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing,Real})
zmin, zmax = _update_clims(zmin, zmax, op(vals.surf)...)
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing,Real})
zmin, zmax = _update_clims(zmin, zmax, op(vals)...)
end
# keeping this unrolled has higher performance
if series[:seriestype] _z_colored_series && series[:z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:z], op)
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
if series[:line_z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:line_z], op)
end
if series[:marker_z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:marker_z], op)
end
if series[:fill_z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:fill_z], op)
end
return series[:clims_calculated] = zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
update_clims(zmin, zmax, vals::AbstractSurface, op)::Tuple{Float64,Float64} =
update_clims(zmin, zmax, vals.surf, op)
update_clims(zmin, zmax, vals::Any, op)::Tuple{Float64,Float64} =
_update_clims(zmin, zmax, op(vals)...)
update_clims(zmin, zmax, ::Nothing, ::Any)::Tuple{Float64,Float64} = zmin, zmax
_update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax)
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
@@ -94,4 +101,5 @@ end
function _update_subplot_colorbars(sp::Subplot)
# Dynamic callback from the pipeline if needed
update_clims(sp)
end
+21 -3
View File
@@ -246,6 +246,7 @@ function font(args...; kw...)
for arg in args
T = typeof(arg)
@assert arg !== :match
if T == Font
family = arg.family
@@ -269,12 +270,12 @@ function font(args...; kw...)
catch
family = string(arg)
end
elseif typeof(arg) <: Integer
elseif T <: Integer
pointsize = arg
elseif typeof(arg) <: Real
elseif T <: Real
rotation = convert(Float64, arg)
else
@warn "Unused font arg: $arg ($(typeof(arg)))"
@warn "Unused font arg: $arg ($T)"
end
end
@@ -772,3 +773,20 @@ function extrema_plus_buffer(v, buffmult = 0.2)
buffer = vdiff * buffmult
vmin - buffer, vmax + buffer
end
### Legend
@add_attributes subplot struct Legend
background_color = :match
foreground_color = :match
position = :best
title = nothing
font::Font = font(8)
title_font::Font = font(11)
column = 1
end :match = (
:legend_font_family,
:legend_font_color,
:legend_title_font_family,
:legend_title_font_color,
)
+87
View File
@@ -0,0 +1,87 @@
const _all_defaults = KW[_series_defaults, _plot_defaults, _subplot_defaults]
const _initial_defaults = deepcopy(_all_defaults)
const _initial_axis_defaults = deepcopy(_axis_defaults)
# add defaults for the letter versions
const _axis_defaults_byletter = KW()
function reset_axis_defaults_byletter!()
for letter in (:x, :y, :z)
_axis_defaults_byletter[letter] = KW()
for (k, v) in _axis_defaults
_axis_defaults_byletter[letter][k] = v
end
end
end
reset_axis_defaults_byletter!()
# to be able to reset font sizes to initial values
const _initial_plt_fontsizes =
Dict(:plot_titlefontsize => _plot_defaults[:plot_titlefontsize])
const _initial_sp_fontsizes = Dict(
:titlefontsize => _subplot_defaults[:titlefontsize],
:legend_font_pointsize => _subplot_defaults[:legend_font_pointsize],
:legend_title_font_pointsize => _subplot_defaults[:legend_title_font_pointsize],
:annotationfontsize => _subplot_defaults[:annotationfontsize],
:colorbar_tickfontsize => _subplot_defaults[:colorbar_tickfontsize],
:colorbar_titlefontsize => _subplot_defaults[:colorbar_titlefontsize],
)
const _initial_ax_fontsizes = Dict(
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize],
)
const _initial_fontsizes =
merge(_initial_plt_fontsizes, _initial_sp_fontsizes, _initial_ax_fontsizes)
const _internal_args =
[:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter]
const _axis_args = sort(union(collect(keys(_axis_defaults))))
const _series_args = sort(union(collect(keys(_series_defaults))))
const _subplot_args = sort(union(collect(keys(_subplot_defaults))))
const _plot_args = sort(union(collect(keys(_plot_defaults))))
const _magic_axis_args = [:axis, :tickfont, :guidefont, :grid, :minorgrid]
const _magic_subplot_args =
[:title_font, :legend_font, :legend_title_font, :plot_title_font, :colorbar_titlefont]
const _magic_series_args = [:line, :marker, :fill]
const _all_axis_args = sort(union([_axis_args; _magic_axis_args]))
const _all_subplot_args = sort(union([_subplot_args; _magic_subplot_args]))
const _all_series_args = sort(union([_series_args; _magic_series_args]))
const _all_plot_args = _plot_args
const _all_args = sort(union([
_all_axis_args
_all_subplot_args
_all_series_args
_all_plot_args
]))
# add all pluralized forms to the _keyAliases dict
for arg in _all_args
add_aliases(arg, makeplural(arg))
end
# fill symbol cache
for letter in (:x, :y, :z)
_attrsymbolcache[letter] = Dict{Symbol,Symbol}()
for k in _axis_args
# populate attribute cache
lk = Symbol(letter, k)
_attrsymbolcache[letter][k] = lk
# allow the underscore version too: xguide or x_guide
add_aliases(lk, Symbol(letter, "_", k))
end
for k in (_magic_axis_args..., :(_discrete_indices))
_attrsymbolcache[letter][k] = Symbol(letter, k)
end
end
# add all non_underscored forms to the _keyAliases
add_non_underscore_aliases!(_keyAliases)
+41 -7
View File
@@ -962,8 +962,10 @@ const _examples = PlotExample[
"""
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically.
You can also specify the connections using the connections keyword.
The connections are specified using a tuple of vectors. Each vector contains the 0-based indices of one point of a triangle,
such that elements at the same position of these vectors form a triangle.
The connections can be specified in two ways: Either as a tuple of vectors where each vector
contains the 0-based indices of one point of a triangle, such that elements at the same
position of these vectors form a triangle. Or as a vector of NTuple{3,Ints} where each element
contains the 1-based indices of the three points of a triangle.
""",
[
:(
@@ -979,13 +981,14 @@ const _examples = PlotExample[
i = [0, 0, 0, 1]
j = [1, 2, 3, 2]
k = [2, 3, 1, 3]
# Or: cns = [(1, 2, 3), (1, 3, 4), (1, 4, 2), (2, 3, 4)] (1-based indexing)
# the four triangles gives above give a tetrahedron
mesh3d(
x,
y,
z;
connections = (i, j, k),
connections = (i, j, k), # connections = cns
title = "triangles",
xlabel = "x",
ylabel = "y",
@@ -1229,13 +1232,45 @@ const _examples = PlotExample[
),
],
),
PlotExample( # 56
"Bar plot customizations",
"""
Width of bars may be specified as `bar_width`.
The bars' baseline may be specified as `fillto`.
Each may be scalar, or a vector spcifying one value per bar.
""",
[
:(
begin
plot(
bar(
[-1, 0, 2, 3],
[1, 3, 6, 2],
fill_z = 4:-1:1,
alpha = [1, 0.2, 0.8, 0.5],
label = "",
bar_width = 1:4,
),
bar(
rand(5),
bar_width = 1.2,
alpha = 0.8,
color = [:lightsalmon, :tomato, :crimson, :firebrick, :darkred],
fillto = 0:-0.1:-0.4,
label = "reds",
),
)
end
),
],
),
]
# Some constants for PlotDocs and PlotReferenceImages
_animation_examples = [2, 31]
_backend_skips = Dict(
:gr => [25, 30],
:pyplot => [2, 25, 30, 31, 47, 49, 55],
:pyplot => [2, 25, 30, 31, 49, 55],
:plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55],
:plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55],
:pgfplotsx => [
@@ -1250,14 +1285,14 @@ _backend_skips = Dict(
],
:inspectdr => [4, 6, 10, 22, 24, 28, 30, 38, 43, 45, 47, 48, 49, 50, 51, 55],
:unicodeplots => [
5, # limits issue
6, # embedded images unsupported
13, # markers unsupported
16, # nested layout unsupported
20, # annotations unsupported
21, # custom markers unsupported
22, # contours unsupported
24, # 3D unsupported
26, # nested layout unsupported
27, # polar plots unsupported
29, # nested layout unsupported
33, # grid lines unsupported
34, # framestyle unsupported
@@ -1265,7 +1300,6 @@ _backend_skips = Dict(
43, # heatmap with DateTime
45, # error bars
47, # mesh3D unsupported
48, # markershapes unsupported
49, # polar heatmap
50, # 3D surface unsupported
51, # embedded images unsupported
+17 -132
View File
@@ -269,6 +269,9 @@ Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r, c]
function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
layout.grid[r, c] = v
end
function Base.setindex!(layout::GridLayout, v, ci::CartesianIndex)
layout.grid[ci] = v
end
leftpad(layout::GridLayout) = layout.minpad[1]
toppad(layout::GridLayout) = layout.minpad[2]
@@ -491,6 +494,19 @@ function layout_args(sztup::NTuple{3,Integer})
GridLayout(nr, nc), n
end
layout_args(nt::NamedTuple) = EmptyLayout(;nt...), 1
function layout_args(m::AbstractVecOrMat)
sz = size(m)
nr = sz[1]
nc = get(sz, 2, 1)
gl = GridLayout(nr, nc)
for ci in CartesianIndices(m)
gl[ci] = layout_args(m[ci])[1]
end
layout_args(gl)
end
# compute number of subplots
function layout_args(layout::GridLayout)
# recursively get the size of the grid
@@ -498,7 +514,7 @@ function layout_args(layout::GridLayout)
layout, n
end
layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
layout_args(n_override::Integer, layout::Union{AbstractVecOrMat,GridLayout}) = layout_args(layout)
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
@@ -562,137 +578,6 @@ function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot})
layout, subplots, spmap
end
# ----------------------------------------------------------------------
# @layout macro
function add_layout_pct!(kw::AKW, v::Expr, idx::Integer, nidx::Integer)
# dump(v)
# something like {0.2w}?
if v.head == :call && v.args[1] == :*
num = v.args[2]
if length(v.args) == 3 && isa(num, Number)
units = v.args[3]
if units == :h
return kw[:h] = num * pct
elseif units == :w
return kw[:w] = num * pct
elseif units in (:pct, :px, :mm, :cm, :inch)
idx == 1 && (kw[:w] = v)
(idx == 2 || nidx == 1) && (kw[:h] = v)
# return kw[idx == 1 ? :w : :h] = v
end
end
end
error("Couldn't match layout curly (idx=$idx): $v")
end
function add_layout_pct!(kw::AKW, v::Number, idx::Integer)
# kw[idx == 1 ? :w : :h] = v*pct
idx == 1 && (kw[:w] = v * pct)
(idx == 2 || nidx == 1) && (kw[:h] = v * pct)
end
isrow(v) = isa(v, Expr) && v.head in (:hcat, :row)
iscol(v) = isa(v, Expr) && v.head == :vcat
rowsize(v) = isrow(v) ? length(v.args) : 1
function create_grid(expr::Expr)
if iscol(expr)
create_grid_vcat(expr)
elseif isrow(expr)
:(
let cell = GridLayout(1, $(length(expr.args)))
$(
[
:(cell[1, $i] = $(create_grid(v))) for
(i, v) in enumerate(expr.args)
]...
)
cell
end
)
elseif expr.head == :curly
create_grid_curly(expr)
else
# if it's something else, just return that (might be an existing layout?)
esc(expr)
end
end
function create_grid_vcat(expr::Expr)
rowsizes = map(rowsize, expr.args)
rmin, rmax = extrema(rowsizes)
if rmin > 0 && rmin == rmax
# we have a grid... build the whole thing
# note: rmin is the number of columns
nr = length(expr.args)
nc = rmin
body = Expr(:block)
for r in 1:nr
arg = expr.args[r]
if isrow(arg)
for (c, item) in enumerate(arg.args)
push!(body.args, :(cell[$r, $c] = $(create_grid(item))))
end
else
push!(body.args, :(cell[$r, 1] = $(create_grid(arg))))
end
end
:(
let cell = GridLayout($nr, $nc)
$body
cell
end
)
else
# otherwise just build one row at a time
:(
let cell = GridLayout($(length(expr.args)), 1)
$(
[
:(cell[$i, 1] = $(create_grid(v))) for
(i, v) in enumerate(expr.args)
]...
)
cell
end
)
end
end
function create_grid_curly(expr::Expr)
kw = KW()
for (i, arg) in enumerate(expr.args[2:end])
add_layout_pct!(kw, arg, i, length(expr.args) - 1)
end
s = expr.args[1]
if isa(s, Expr) && s.head == :call && s.args[1] == :grid
create_grid(
:(grid(
$(s.args[2:end]...),
width = $(get(kw, :w, QuoteNode(:auto))),
height = $(get(kw, :h, QuoteNode(:auto))),
)),
)
elseif isa(s, Symbol)
:(EmptyLayout(
label = $(QuoteNode(s)),
width = $(get(kw, :w, QuoteNode(:auto))),
height = $(get(kw, :h, QuoteNode(:auto))),
))
else
error("Unknown use of curly brackets: $expr")
end
end
function create_grid(s::Symbol)
:(EmptyLayout(label = $(QuoteNode(s)), blank = $(s == :_)))
end
macro layout(mat::Expr)
create_grid(mat)
end
# -------------------------------------------------------------------------
+15 -23
View File
@@ -8,24 +8,14 @@ function RecipesPipeline.warn_on_recipe_aliases!(
recipe_type::Symbol,
@nospecialize(args)
)
for k in keys(plotattributes)
if !is_default_attribute(k)
dk = get(_keyAliases, k, k)
if k !== dk
if recipe_type == :user
signature_string = RecipesPipeline.userrecipe_signature_string(args)
elseif recipe_type == :type
signature_string = RecipesPipeline.typerecipe_signature_string(args)
elseif recipe_type == :plot
signature_string = RecipesPipeline.plotrecipe_signature_string(args)
elseif recipe_type == :series
signature_string = RecipesPipeline.seriesrecipe_signature_string(args)
else
throw(ArgumentError("Invalid recipe type `$recipe_type`"))
end
@warn "Attribute alias `$k` detected in the $recipe_type recipe defined for the signature $signature_string. To ensure expected behavior it is recommended to use the default attribute `$dk`."
pkeys = keys(plotattributes)
for k in pkeys
dk = get(_keyAliases, k, nothing)
if dk !== nothing
kv = RecipesPipeline.pop_kw!(plotattributes, k)
if dk pkeys
plotattributes[dk] = kv
end
plotattributes[dk] = RecipesPipeline.pop_kw!(plotattributes, k)
end
end
end
@@ -253,12 +243,12 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
attr[get_attr_symbol(letter, k)] = v
end
end
for k in (:scale,), letter in (:x, :y, :z)
# Series recipes may need access to this information
lk = get_attr_symbol(letter, k)
if haskey(attr, lk)
kw[lk] = attr[lk]
end
end
for k in (:scale,), letter in (:x, :y, :z)
# Series recipes may need access to this information
lk = get_attr_symbol(letter, k)
if haskey(attr, lk)
kw[lk] = attr[lk]
end
end
sp_attrs[sp] = attr
@@ -273,6 +263,7 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
get(sp_attrs, sp, KW())
end
_update_subplot_args(plt, sp, attr, idx, false)
_update_subplot_legend(sp, attr)
end
# do we need to link any axes together?
@@ -416,4 +407,5 @@ function _add_the_series(plt, sp, plotattributes)
push!(plt.series_list, series)
push!(sp.series_list, series)
_series_added(plt, series)
_update_subplot_colorbars(sp)
end
+3 -3
View File
@@ -1,5 +1,7 @@
#! format: off
should_precompile = true
# Don't edit the following! Instead change the script for `snoop_bot`.
ismultios = false
ismultiversion = false
@@ -7,9 +9,7 @@ ismultiversion = false
@static if !should_precompile
# nothing
elseif !ismultios && !ismultiversion
@static if isfile(
joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_Plots.jl"),
)
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_Plots.jl"))
include("../deps/SnoopCompile/precompile/precompile_Plots.jl")
_precompile_()
end
+23 -5
View File
@@ -508,6 +508,18 @@ end
primary := true
x := xseg.pts
y := yseg.pts
# expand attributes to match indices in new series data
for k in _segmenting_vector_attributes _segmenting_array_attributes
v = get(plotattributes, k, nothing)
if v isa AVec
if eachindex(v) != eachindex(y)
@warn "Indices $(eachindex(v)) of attribute `$k` do not match data indices $(eachindex(y))."
end
# Each segment is 6 elements long, including the NaN separator.
# There is no trailing NaN, so the last repetition is dropped.
plotattributes[k] = @view repeat(v; inner = 6)[1:(end - 1)]
end
end
()
end
@@ -1025,14 +1037,14 @@ export lens!
throw(ArgumentError("Inset bounding box needs to in relative coordinates."))
end
sp = plt.subplots[sp_index]
xl1, xl2 = xlims(plt.subplots[sp_index])
xl1, xl2 = xlims(sp)
bbx1 = xl1 + left(inset_bbox).value * (xl2 - xl1)
bbx2 = bbx1 + width(inset_bbox).value * (xl2 - xl1)
yl1, yl2 = ylims(plt.subplots[sp_index])
yl1, yl2 = ylims(sp)
bby1 = yl1 + (1 - bottom(inset_bbox).value) * (yl2 - yl1)
bby2 = bby1 + height(inset_bbox).value * (yl2 - yl1)
bbx = bbx1 + width(inset_bbox).value * (xl2 - xl1) / 2
bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2
bbx = bbx1 + width(inset_bbox).value * (xl2 - xl1) / 2 * (sp[:xaxis][:flip] ? -1 : 1)
bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2 * (sp[:yaxis][:flip] ? -1 : 1)
lens_index = last(plt.subplots)[:subplot_index] + 1
x1, x2 = plotattributes[:x]
y1, y2 = plotattributes[:y]
@@ -1042,7 +1054,13 @@ export lens!
series_plotindex := backup[:series_plotindex]
seriestype := :path
primary := false
linecolor := :lightgray
linecolor := get(backup, :linecolor, :lightgray)
if haskey(backup, :linestyle)
linestyle := backup[:linestyle]
end
if haskey(backup, :linewidth)
linewidth := backup[:linewidth]
end
bbx_mag = (x1 + x2) / 2
bby_mag = (y1 + y2) / 2
xi_lens, yi_lens =
+58 -30
View File
@@ -103,7 +103,10 @@ function series_segments(series::Series, seriestype::Symbol = :path; check = fal
segments = if has_attribute_segments(series)
Iterators.flatten(map(nan_segments) do r
if seriestype in (:scatter, :scatter3d)
if seriestype == :shape
warn_on_inconsistent_shape_attr(series, x, y, z, r)
(SeriesSegment(r, first(r)),)
elseif seriestype in (:scatter, :scatter3d)
(SeriesSegment(i:i, i) for i in r)
else
(SeriesSegment(i:(i + 1), i) for i in first(r):(last(r) - 1))
@@ -140,6 +143,16 @@ function warn_on_attr_dim_mismatch(series, x, y, z, segments)
end
end
function warn_on_inconsistent_shape_attr(series, x, y, z, r)
for attr in _segmenting_vector_attributes
v = get(series, attr, nothing)
if v isa AVec && length(unique(v[r])) > 1
@warn "Different values of `$attr` specified for different shape vertices. Only first one will be used."
break
end
end
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> try
isnan(_cycle(a, i))
@@ -205,14 +218,15 @@ maketuple(x::Tuple{T,S}) where {T,S} = x
for i in 2:4
@eval begin
RecipesPipeline.unzip(
v::Union{AVec{<:Tuple{Vararg{T,$i} where T}},AVec{<:GeometryBasics.Point{$i}}},
v::Union{AVec{<:NTuple{$i,T} where {T}},AVec{<:GeometryBasics.Point{$i}}},
) = $(Expr(:tuple, (:([t[$j] for t in v]) for j in 1:i)...))
end
end
RecipesPipeline.unzip(
::Union{AVec{<:GeometryBasics.Point{N}},AVec{<:Tuple{Vararg{T,N} where T}}},
::Union{AVec{<:GeometryBasics.Point{N}},AVec{<:NTuple{N,T} where {T}}},
) where {N} = error("$N-dimensional unzip not implemented.")
RecipesPipeline.unzip(::Union{AVec{<:GeometryBasics.Point},AVec{<:Tuple}}) =
error("Can't unzip points of different dimensions.")
@@ -499,7 +513,7 @@ for comp in (:line, :fill, :marker)
end
end
$get_compcolor(series, clims, i::Int = 1) =
$get_compcolor(series, clims::Tuple{<:Number, <:Number}, i::Int = 1) =
$get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1)
@@ -572,7 +586,6 @@ const _segmenting_array_attributes = :line_z, :fill_z, :marker_z
function has_attribute_segments(series::Series)
# we want to check if a series needs to be split into segments just because
# of its attributes
series[:seriestype] == :shape && return false
# check relevant attributes if they have multiple inputs
return any(
series[attr] isa AbstractVector && length(series[attr]) > 1 for
@@ -647,7 +660,7 @@ function with(f::Function, args...; kw...)
newdefs[:xticks] = nothing
newdefs[:yticks] = nothing
newdefs[:grid] = false
newdefs[:legend] = false
newdefs[:legend_position] = false
end
# dict to store old and new keyword args for anything that changes
@@ -981,22 +994,15 @@ titlefont(sp::Subplot) = font(;
color = sp[:titlefontcolor],
)
legendfont(sp::Subplot) = font(;
family = sp[:legendfontfamily],
pointsize = sp[:legendfontsize],
valign = sp[:legendfontvalign],
halign = sp[:legendfonthalign],
rotation = sp[:legendfontrotation],
color = sp[:legendfontcolor],
)
legendfont(sp::Subplot) = sp[:legend_font]
legendtitlefont(sp::Subplot) = font(;
family = sp[:legendtitlefontfamily],
pointsize = sp[:legendtitlefontsize],
valign = sp[:legendtitlefontvalign],
halign = sp[:legendtitlefonthalign],
rotation = sp[:legendtitlefontrotation],
color = sp[:legendtitlefontcolor],
family = sp[:legend_title_font_family],
pointsize = sp[:legend_title_font_pointsize],
valign = sp[:legend_title_font_valign],
halign = sp[:legend_title_font_halign],
rotation = sp[:legend_title_font_rotation],
color = sp[:legend_title_font_color],
)
tickfont(ax::Axis) = font(;
@@ -1180,16 +1186,10 @@ end
_document_argument(S::AbstractString) =
_fmt_paragraph("`$S`: " * _arg_desc[Symbol(S)], leadingspaces = 6 + length(S))
function mesh3d_triangles(x, y, z, cns)
if typeof(cns) <: Tuple{Array,Array,Array}
ci, cj, ck = cns
if !(length(ci) == length(cj) == length(ck))
throw(
ArgumentError("Argument connections must consist of equally sized arrays."),
)
end
else
throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
function mesh3d_triangles(x, y, z, cns::Tuple{Array,Array,Array})
ci, cj, ck = cns
if !(length(ci) == length(cj) == length(ck))
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
end
X = zeros(eltype(x), 4length(ci))
Y = zeros(eltype(y), 4length(cj))
@@ -1215,8 +1215,36 @@ function mesh3d_triangles(x, y, z, cns)
return X, Y, Z
end
function mesh3d_triangles(x, y, z, cns::AbstractVector{NTuple{3,Int}})
X = zeros(eltype(x), 4length(cns))
Y = zeros(eltype(y), 4length(cns))
Z = zeros(eltype(z), 4length(cns))
@inbounds for I in 1:length(cns)
i = cns[I][1] # connections are 1-based
j = cns[I][2]
k = cns[I][3]
m = 4(I - 1) + 1
n = m + 1
o = m + 2
p = m + 3
X[m] = X[p] = x[i]
Y[m] = Y[p] = y[i]
Z[m] = Z[p] = z[i]
X[n] = x[j]
Y[n] = y[j]
Z[n] = z[j]
X[o] = x[k]
Y[o] = y[k]
Z[o] = z[k]
end
return X, Y, Z
end
# cache joined symbols so they can be looked up instead of constructed each time
const _attrsymbolcache = Dict{Symbol,Dict{Symbol,Symbol}}()
get_attr_symbol(letter::Symbol, keyword::String) = get_attr_symbol(letter, Symbol(keyword))
get_attr_symbol(letter::Symbol, keyword::Symbol) = _attrsymbolcache[letter][keyword]
texmath2unicode(s::AbstractString, pat = r"\$([^$]+)\$") =
replace(s, pat => m -> UnicodeFun.to_latex(m[2:(length(m) - 1)]))
+88 -78
View File
@@ -1,18 +1,20 @@
using Plots: guidefont, series_annotations, PLOTS_SEED
import ImageMagick
using VisualRegressionTests
using Plots
using Random
using StableRNGs
using Test
using TestImages
using FileIO
using Gtk
using LibGit2
import GeometryBasics
using Dates
using RecipesBase
using StableRNGs
using TestImages
using LibGit2
using Random
using FileIO
using Plots
using Dates
using JSON
using Test
using Gtk
import GeometryBasics
import ImageMagick
@testset "Infrastructure" begin
@test_nowarn JSON.Parser.parse(
@@ -33,7 +35,7 @@ end
end
Plots.plotly_local_file_path[] = nothing
Plots.use_local_dependencies[] = temp
end # testset
end
include("test_defaults.jl")
include("test_pipeline.jl")
@@ -55,7 +57,6 @@ function reference_file(backend, i, version)
refdir = reference_dir("Plots", string(backend))
fn = "ref$i.png"
versions = sort(VersionNumber.(readdir(refdir)), rev = true)
reffn = joinpath(refdir, string(version), fn)
for v in versions
tmpfn = joinpath(refdir, string(v), fn)
@@ -64,7 +65,6 @@ function reference_file(backend, i, version)
break
end
end
return reffn
end
@@ -79,9 +79,10 @@ if !isdir(reference_dir())
end
include("imgcomp.jl")
# don't actually show the plots
Random.seed!(PLOTS_SEED)
default(show = false, reuse = true)
default(show = false, reuse = true) # don't actually show the plots
is_ci() = get(ENV, "CI", "false") == "true"
const PLOTS_IMG_TOL = parse(Float64, get(ENV, "PLOTS_IMG_TOL", is_ci() ? "1e-4" : "1e-5"))
@@ -106,66 +107,8 @@ const PLOTS_IMG_TOL = parse(Float64, get(ENV, "PLOTS_IMG_TOL", is_ci() ? "1e-4"
# image_comparison_facts(:pgfplotsx, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:pgfplotsx])
# end
# 10 Histogram2D
##
@testset "Backends" begin
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@static if haskey(ENV, "APPVEYOR")
@info "Skipping GR image comparison tests on AppVeyor"
else
image_comparison_facts(
:gr,
tol = PLOTS_IMG_TOL,
skip = Plots._backend_skips[:gr],
)
end
end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = bar(randn(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([1, 2], [3, 4])
annotate!(p, [(1.5, 3.2, Plots.text("Test", :red, :center))])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
hline!(p, [3.1])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, Plots.text("Test", :red, :center))])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, :auto)])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
end
@testset "PlotlyJS" begin
@test plotlyjs() == Plots.PlotlyJSBackend()
@test backend() == Plots.PlotlyJSBackend()
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test_broken isa(display(p), Nothing) == true
end
end
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@@ -181,10 +124,12 @@ end
end
@testset "NoFail" begin
#ensure backend with tested display
# ensure backend with tested display
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
dsp = TextDisplay(IOContext(IOBuffer(), :color => true))
@testset "Plot" begin
plots = [
histogram([1, 0, 0, 0, 0, 0]),
@@ -197,15 +142,15 @@ end
plot(["a" "b"; missing "d"], [1 2; 3 4]),
]
for plt in plots
display(plt)
display(dsp, plt)
end
@test_nowarn plot(x -> x^2, 0, 2)
end
@testset "Bar" begin
p = bar([3, 2, 1], [1, 2, 3])
@test isa(p, Plots.Plot)
@test isa(display(p), Nothing) == true
@test p isa Plots.Plot
@test display(dsp, p) isa Nothing
end
end
@@ -254,4 +199,69 @@ end
@test Plots.process_clims(nothing) ==
Plots.process_clims(missing) ==
Plots.process_clims(:auto)
@test (==)(
Plots.texmath2unicode(
raw"Equation $y = \alpha \cdot x + \beta$ and eqn $y = \sin(x)^2$",
),
raw"Equation y = α ⋅ x + β and eqn y = sin(x)²",
)
end
@testset "Backends" begin
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
io = IOContext(IOBuffer(), :color => true)
# lets just make sure it runs without error
p = plot(rand(10))
@test p isa Plots.Plot
@test show(io, p) isa Nothing
p = bar(randn(10))
@test p isa Plots.Plot
@test show(io, p) isa Nothing
p = plot([1, 2], [3, 4])
annotate!(p, [(1.5, 3.2, Plots.text("Test", :red, :center))])
hline!(p, [3.1])
@test p isa Plots.Plot
@test show(io, p) isa Nothing
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
hline!(p, [3.1])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, Plots.text("Test", :red, :center))])
@test p isa Plots.Plot
@test show(io, p) isa Nothing
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, :auto)])
hline!(p, [3.1])
@test p isa Plots.Plot
@test show(io, p) isa Nothing
end
@testset "PlotlyJS" begin
@test plotlyjs() == Plots.PlotlyJSBackend()
@test backend() == Plots.PlotlyJSBackend()
p = plot(rand(10))
@test p isa Plots.Plot
@test_broken display(p) isa Nothing
end
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@static if haskey(ENV, "APPVEYOR")
@info "Skipping GR image comparison tests on AppVeyor"
else
image_comparison_facts(
:gr,
tol = PLOTS_IMG_TOL,
skip = Plots._backend_skips[:gr],
)
end
end
end
+41 -9
View File
@@ -64,7 +64,10 @@ end
@test twpl[:bottom_margin] == 2Plots.cm
end
@testset "aliases" begin
@testset "axis-aliases" begin
@test haskey(Plots._keyAliases, :xguideposition)
@test haskey(Plots._keyAliases, :x_guide_position)
@test !haskey(Plots._keyAliases, :xguide_position)
p = plot(1:2, xl = "x label")
@test p[1][:xaxis][:guide] === "x label"
p = plot(1:2, xrange = (0, 3))
@@ -73,18 +76,47 @@ end
@test p[1][:xaxis][:ticks] == [1.25, 1.5, 1.75]
p = plot(1:2, xlabelfontsize = 4)
@test p[1][:xaxis][:guidefontsize] == 4
p = plot(1:2, xgα = .07)
@test p[1][:xaxis][:gridalpha] .07
p = plot(1:2, xgα = 0.07)
@test p[1][:xaxis][:gridalpha] 0.07
p = plot(1:2, xgridls = :dashdot)
@test p[1][:xaxis][:gridstyle] === :dashdot
p = plot(1:2, xgridcolor = :red)
@test p[1][:xaxis][:foreground_color_grid] === RGBA{Float64}(1.,0.,0.,1.)
@test p[1][:xaxis][:foreground_color_grid] === RGBA{Float64}(1.0, 0.0, 0.0, 1.0)
p = plot(1:2, xminorgridcolor = :red)
@test p[1][:xaxis][:foreground_color_minor_grid] === RGBA{Float64}(1.,0.,0.,1.)
p = plot(1:2, xgrid_lw = .01)
@test p[1][:xaxis][:gridlinewidth] .01
p = plot(1:2, xminorgrid_lw = .01)
@test p[1][:xaxis][:minorgridlinewidth] .01
@test p[1][:xaxis][:foreground_color_minor_grid] === RGBA{Float64}(1.0, 0.0, 0.0, 1.0)
p = plot(1:2, xgrid_lw = 0.01)
@test p[1][:xaxis][:gridlinewidth] 0.01
p = plot(1:2, xminorgrid_lw = 0.01)
@test p[1][:xaxis][:minorgridlinewidth] 0.01
p = plot(1:2, xtickor = :out)
@test p[1][:xaxis][:tick_direction] === :out
end
@testset "aliases" begin
compare(p::Plots.Plot, s::Symbol, val, op) =
op(p[1][:xaxis][s], val) && op(p[1][:yaxis][s], val) && op(p[1][:zaxis][s], val)
p = plot(1:2, guide = "all labels")
@test compare(p, :guide, "all labels", ===)
p = plot(1:2, label = "test")
@test compare(p, :guide, "", ===)
p = plot(1:2, lim = (0, 3))
@test xlims(p) === ylims(p) === zlims(p) === (0, 3)
p = plot(1:2, tick = [1.25, 1.5, 1.75])
@test compare(p, :ticks, [1.25, 1.5, 1.75], ==)
p = plot(1:2, labelfontsize = 4)
@test compare(p, :guidefontsize, 4, ==)
p = plot(1:2, gα = 0.07)
@test compare(p, :gridalpha, 0.07, )
p = plot(1:2, gridls = :dashdot)
@test compare(p, :gridstyle, :dashdot, ===)
p = plot(1:2, gridcolor = :red)
@test compare(p, :foreground_color_grid, RGBA{Float64}(1.0, 0.0, 0.0, 1.0), ===)
p = plot(1:2, minorgridcolor = :red)
@test compare(p, :foreground_color_minor_grid, RGBA{Float64}(1.0, 0.0, 0.0, 1.0), ===)
p = plot(1:2, grid_lw = 0.01)
@test compare(p, :gridlinewidth, 0.01, )
p = plot(1:2, minorgrid_lw = 0.01)
@test compare(p, :minorgridlinewidth, 0.01, )
p = plot(1:2, tickor = :out)
@test compare(p, :tick_direction, :out, ===)
end
+72 -2
View File
@@ -1,4 +1,4 @@
using Plots, Test
using Plots, Test, Colors
const PLOTS_DEFAULTS = Dict(:theme => :wong2, :fontfamily => :palantino)
Plots.__init__()
@@ -6,8 +6,78 @@ Plots.__init__()
@testset "Loading theme" begin
pl = plot(1:5)
@test pl[1][1][:seriescolor] == RGBA(colorant"black")
@test guidefont(pl[1][:xaxis]).family == "palantino"
@test Plots.guidefont(pl[1][:xaxis]).family == "palantino"
end
empty!(PLOTS_DEFAULTS)
Plots.__init__()
@testset "Legend defaults" begin
p = plot()
@test p[1][:legend_font_family] == "sans-serif"
@test p[1][:legend_font_pointsize] == 8
@test p[1][:legend_font_halign] == :hcenter
@test p[1][:legend_font_valign] == :vcenter
@test p[1][:legend_font_rotation] == 0.0
@test p[1][:legend_font_color] == RGB{Colors.N0f8}(0.0, 0.0, 0.0)
@test p[1][:legend_position] == :best
@test p[1][:legend_title] == nothing
@test p[1][:legend_title_font_family] == "sans-serif"
@test p[1][:legend_title_font_pointsize] == 11
@test p[1][:legend_title_font_halign] == :hcenter
@test p[1][:legend_title_font_valign] == :vcenter
@test p[1][:legend_title_font_rotation] == 0.0
@test p[1][:legend_title_font_color] == RGB{Colors.N0f8}(0.0, 0.0, 0.0)
@test p[1][:legend_background_color] == RGBA{Float64}(1.0, 1.0, 1.0, 1.0)
@test p[1][:legend_foreground_color] == RGB{Colors.N0f8}(0.0, 0.0, 0.0)
end # testset
@testset "Legend API" begin
p = plot(;
legendfontfamily = "serif",
legendfontsize = 12,
legendfonthalign = :left,
legendfontvalign = :top,
legendfontrotation = 1,
legendfontcolor = :red,
legend = :outertopleft,
legendtitle = "The legend",
legendtitlefontfamily = "helvetica",
legendtitlefontsize = 3,
legendtitlefonthalign = :right,
legendtitlefontvalign = :bottom,
legendtitlefontrotation = -5.2,
legendtitlefontcolor = :blue,
background_color_legend = :cyan,
foreground_color_legend = :green,
)
@test p[1][:legend_font_family] == "serif"
@test p[1][:legend_font_pointsize] == 12
@test p[1][:legend_font_halign] == :left
@test p[1][:legend_font_valign] == :top
@test p[1][:legend_font_rotation] == 1.0
@test p[1][:legend_font_color] == :red
@test p[1][:legend_position] == :outertopleft
@test p[1][:legend_title] == "The legend"
@test p[1][:legend_title_font_family] == "helvetica"
@test p[1][:legend_title_font_pointsize] == 3
@test p[1][:legend_title_font_halign] == :right
@test p[1][:legend_title_font_valign] == :bottom
@test p[1][:legend_title_font_rotation] == -5.2
@test p[1][:legend_title_font_color] == :blue
@test p[1][:legend_background_color] == RGBA{Float64}(0.0, 1.0, 1.0, 1.0)
@test p[1][:legend_foreground_color] == RGBA{Float64}(0.0, 0.5019607843137255, 0.0, 1.0)
#setting whole font
sp = plot(
1:5,
legendfont = font(12),
legend_font_halign = :left,
foreground_color_subplot = :red,
)[1]
@test Plots.legendfont(sp).pointsize == 12
@test Plots.legendfont(sp).halign == :left
# match mechanism
@test sp[:legend_font_color] == sp[:foreground_color_subplot]
@test Plots.legendfont(sp).color == sp[:foreground_color_subplot]
end # testset
+12
View File
@@ -1,6 +1,18 @@
using Plots, Test
using OffsetArrays
@testset "User recipes" begin
struct LegendPlot end
@recipe function f(plot::LegendPlot)
legend --> :topleft
(1:3, 1:3)
end
pl = plot(LegendPlot(); legend = :right)
@test pl[1][:legend_position] == :right
pl = plot(LegendPlot())
@test pl[1][:legend_position] == :topleft
end
@testset "lens!" begin
pl = plot(1:5)
lens!(pl, [1, 2], [1, 2], inset = (1, bbox(0.0, 0.0, 0.2, 0.2)), colorbar = false)