Compare commits

...

696 Commits

Author SHA1 Message Date
mantaohuang
2a7a1f2e2a remove math font from tick font dict 2022-05-14 02:05:58 -04:00
github-actions[bot]
18b11a71e3
Update precompile_*.jl file [skip ci] (#4197)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-05-06 08:51:03 +02:00
Simon Christ
9e34ed0383
add permute, deprecate orientation (#4164)
* add series_permutation

* works for dates and categorical input, not vector of strings

* Update src/pipeline.jl

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update src/pipeline.jl

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* add test

* correct test

* make bar workign

* add deprecation

* rename series_permutation -> permute

* add Documentation

* fix uneccessary deprecation

* permute h/vlines

* Auto-format

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 1.29.0

* Update Project.toml [skip ci]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-05 15:15:56 +02:00
Simon Christ
561839a029
1.28.2 2022-05-05 11:40:46 +02:00
github-actions[bot]
88f2541288
Update precompile_*.jl file [skip ci] (#4194)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-05-04 21:37:19 +02:00
Simon Christ
92611ea3b4
reset marker_z for errorbars (#4193)
* reset marker_z for errorbars

* also reset line_z
2022-05-04 16:58:23 +02:00
Simon Christ
3e1bad0971
Update SnoopCompile.yml 2022-05-04 14:14:48 +02:00
Simon Christ
a13d4d8554
1.28.1 2022-05-02 17:11:46 +02:00
Jeremiah
b76dc2d7a3
quarto pdf fix? (#4188) 2022-05-02 14:25:17 +02:00
zhiyuanzhai
137d339e0b
Fixing the colorbar title for colorbars on the top. (#4191)
* To fix #4183.

* Providing my information according to #3503.
2022-05-02 11:00:50 +02:00
Simon Christ
e06143ce33
fix #4190 2022-05-02 09:28:55 +02:00
Simon Christ
06220420a3
1.28.0 2022-04-29 12:57:16 +02:00
Simon Christ
d8da3c60d9
update anshul's data 2022-04-28 09:05:49 +02:00
t-bltg
9e92ada61a
Update examples.jl 2022-04-26 16:29:08 +02:00
t-bltg
cebca5174b
UnicodePlots: support polarplot (#4185) 2022-04-26 15:36:23 +02:00
Stephan Antholzer
e3e86aa6cd
merge series extra_kwargs for plotly_series (#4172) 2022-04-22 11:12:55 +02:00
Simon Christ
add8364bbd
1.27.6 2022-04-20 17:39:10 +02:00
github-actions[bot]
09abf2e40f
Update precompile_*.jl file [skip ci] (#4174)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-04-20 09:12:50 +02:00
Benoit Pasquier
182d4683e6
Add areaplot example to gallery (#4178)
* Add areaplot example to gallery

Not sure this is the right way to add example to the gallery but hopefully this is helpful :)

* format files

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2022-04-19 16:03:50 +02:00
t-bltg
a681f3e307
Update SnoopCompile.yml 2022-04-16 15:17:41 +02:00
t-bltg
1c59b19343
Update SnoopCompile.yml 2022-04-16 15:13:29 +02:00
t-bltg
6773666549
Update SnoopCompile.yml 2022-04-16 14:59:00 +02:00
t-bltg
42bf100ad3
Update precompile_Plots.jl 2022-04-16 14:53:10 +02:00
t-bltg
e826c87114
Update SnoopCompile.yml 2022-04-16 14:27:59 +02:00
Jeff Bezanson
616d72476a
Add version check for 1.8 precompiles (#4179)
Co-authored-by: t-bltg <tf.bltg@gmail.com>
2022-04-14 13:32:59 +02:00
Simon Christ
4f9a708f66
fix empty segments in plotly (#4177)
* fix empty segment case

* fix failure on 1.6
2022-04-08 16:39:37 +02:00
t-bltg
4b73b8b5d5
Update docs build (#4175) 2022-04-05 20:08:31 +02:00
t-bltg
99ad317590
1.27.5 2022-04-05 16:27:46 +02:00
github-actions[bot]
90975d95f8
Update precompile_*.jl file [skip ci] (#4173)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-04-05 16:27:15 +02:00
t-bltg
f0a1ef8a0c
Update gaston.jl 2022-04-05 15:26:17 +02:00
t-bltg
49aee2d204
Update unicodeplots.jl 2022-04-05 15:02:56 +02:00
t-bltg
02351a45b4
UnicodePlots: rework png output (#4171) 2022-04-05 14:56:47 +02:00
Simon Christ
e691a42b90 add docs to scale, rotate 2022-04-05 14:52:51 +02:00
Simon Christ
8a584ceab4 add/ rearrange docstrings 2022-04-05 13:43:19 +02:00
t-bltg
cc1bd28ccd
Disable warnings on experimental backends (#4169) 2022-04-05 00:52:49 +02:00
t-bltg
4446a63135
Update docs CI (font) 2022-04-05 00:15:39 +02:00
github-actions[bot]
412a8993ad
Update precompile_*.jl file [skip ci] (#4167)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-04-05 00:03:07 +02:00
Fons van der Plas
d9fb8b8ef3
Remove Main.Plots dependency (#4168) 2022-04-04 23:36:52 +02:00
github-actions[bot]
37eb1db8d2
Update precompile_*.jl file [skip ci] (#4165)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-04-04 18:14:58 +02:00
t-bltg
dc3e3176f2
UnicodePlots: fix internal change 2022-04-04 18:10:58 +02:00
github-actions[bot]
2cd3331f30
Update precompile_*.jl file [skip ci] (#4163)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-04-01 11:22:07 +02:00
github-actions[bot]
db932d62f6
CompatHelper: bump compat for PlotThemes to 3, (keep existing compat) (#4162)
Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>
2022-04-01 11:17:47 +02:00
Simon Christ
caf4d1857c
1.27.4 2022-03-30 16:35:47 +02:00
github-actions[bot]
bbde8ad1b1
Update precompile_*.jl file [skip ci] (#4154)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-30 15:43:45 +02:00
Simon Christ
d3449331c9 remove Shape from _pgfplotsx_marker 2022-03-30 15:38:11 +02:00
Ian Butterworth
eb746d1641
Sort supported args (#4156)
* sort supported args

* Update src/args.jl

* sort all supported* functions

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2022-03-29 17:42:23 +02:00
Steve Leung
a33c0205b2
Restored plotly hover functionality for plots with multidimensional data (#4159)
* Restored hover functionality for plots with multidimensional data

* Renamed plotly_hover!() to plotly_adjust_hover_label!()

* Updated contributors list

* Update src/backends/plotly.jl [skip ci]

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

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
Co-authored-by: t-bltg <tf.bltg@gmail.com>
2022-03-29 17:42:01 +02:00
Simon Christ
65ab68c3b5
fix legends for arrows (#4161)
* fix legends for arrows

* Apply suggestions from code review [skip ci]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* raise tolerance on windows

* Update test/runtests.jl [skip ci]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-29 17:41:25 +02:00
t-bltg
0f4a0c7154
fix examples 2022-03-27 12:09:54 +02:00
t-bltg
02d08beb1e
improve coverage (#4155) 2022-03-27 01:42:05 +01:00
Simon Christ
d3817796a4
1.27.3 2022-03-25 17:41:01 +01:00
Simon Christ
dbe81dabd5
fix #4151 (#4153)
* letter and Set the consts

* use julia-code-style-suggesters

* remove superfluous name

* edit by copy of code-style-suggesters

* delete stuff

* remove using

* Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-25 17:39:54 +01:00
t-bltg
5c2cc926a6
docs: more verbosity 2022-03-24 13:13:38 +01:00
t-bltg
bcc66caf7d
1.27.2 [skip ci] 2022-03-23 20:07:36 +01:00
t-bltg
0686461686
UnicodePlots: png output (#4149) 2022-03-23 20:06:57 +01:00
github-actions[bot]
5c4fbc5e1a
Update precompile_*.jl file [skip ci] (#4143)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-22 10:35:19 +01:00
Simon Christ
5872bdefc4
1.27.1 2022-03-17 14:02:50 +01:00
Simon Christ
a4849da775 format [skip ci] 2022-03-17 12:07:54 +01:00
Simon Christ
afe24f46bc fix example 25 2022-03-17 12:04:47 +01:00
Simon Christ
79638b7789
Update examples.jl 2022-03-17 09:12:02 +01:00
github-actions[bot]
e82e95c8e3
Update precompile_*.jl file [skip ci] (#4140)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-17 09:05:56 +01:00
Simon Christ
843226bfe1
Revert "annotations over marksers in pgfplotsx backend (#3957)" (#4142)
This reverts commit 06bc99ef68dca50fd3f91cadff0b5d210ad3fdbf.
2022-03-17 09:05:29 +01:00
Simon Christ
317bfc918a
1.27.0 2022-03-11 20:52:22 +01:00
Simon Christ
4665f5caab
fix compat check 2022-03-11 20:51:43 +01:00
Simon Christ
1520705fa7
add z_order (#4139)
* add z_order

* format

* add missing ,

* fix testss

* this time for real

* format [skip ci]
2022-03-11 15:57:06 +01:00
Simon Christ
b60cf3cc53
1.26.1 [skip ci] 2022-03-11 11:35:22 +01:00
Simon Christ
092fb67017
Actually check if the loaded backend version mets the compat entries (#4137)
* implement checking backend compat

* format

* handle backends without compat entry

* get version for julia 1.6
2022-03-11 10:49:40 +01:00
github-actions[bot]
4ebadb7612
Update precompile_*.jl file [skip ci] (#4132)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-07 11:23:57 +01:00
Simon Christ
fcd3246e4a
Update .zenodo.json 2022-03-04 13:36:14 +01:00
Simon Christ
5f858fe6f6
1.26.0 2022-03-02 09:45:32 +01:00
github-actions[bot]
8a4aea1fc7
Update precompile_*.jl file [skip ci] (#4126)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-02 09:44:48 +01:00
Simon Christ
3483799cfc
add compat entries (#4122) 2022-03-01 16:36:41 +01:00
Simon Christ
a5f52be5c2
1.25.12 2022-03-01 15:38:29 +01:00
t-bltg
2b7e304c7e
revert constant legend box (#4117) 2022-03-01 14:53:45 +01:00
github-actions[bot]
6c77801835
Update precompile_*.jl file [skip ci] (#4124)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-03-01 14:28:27 +01:00
Simon Christ
b34f8b87c1
check loaded_modules instead of Main for warnings about StatsPlots recipes (#4123)
* check loaded_modules instead of Main

* format
2022-03-01 09:23:10 +01:00
github-actions[bot]
5130da5a40
Update precompile_*.jl file [skip ci] (#4121)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-02-26 18:26:28 +01:00
Simon Christ
95fd48ed9b
Bbs/legendfontx (#4119)
* revert legendfont being determant

* format

* fix precompiles
2022-02-26 17:26:14 +01:00
Simon Christ
e31d056820
1.25.11 2022-02-20 14:43:34 +01:00
github-actions[bot]
afe85207e1
Update precompile_*.jl file [skip ci] (#4110)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-02-20 14:42:57 +01:00
Simon Christ
204b2178d0
better line (#4085) 2022-02-18 21:13:16 +01:00
Simon Christ
51358717ee
add slicing of tuples of matrices for plotattributes (#4109)
* add slicing of tuples of matrices

* remove dot

* format files
2022-02-18 21:12:44 +01:00
github-actions[bot]
ed9f0bcab3
Update precompile_*.jl file [skip ci] (#4101)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-02-18 13:55:22 +01:00
t-bltg
d342672dd2
Allow color on txt io (#4102) 2022-02-17 22:33:09 +01:00
github-actions[bot]
64d275e7cb
CompatHelper: bump compat for NaNMath to 1 (#4104)
Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>
2022-02-17 15:27:00 +01:00
t-bltg
a919fe59d3
Center :image axes ticks (#4088) 2022-02-16 22:05:50 +01:00
Josef Heinen
88cd04b46a
Bump Plots version
Bump Plots version to 1.25.10
2022-02-15 16:45:19 +01:00
Josef Heinen
325d60e8b8
Bump GR version
Bump GR version to 0.64
2022-02-15 15:24:04 +01:00
Simon Christ
20f576211c
1.25.9 2022-02-11 17:45:18 +01:00
github-actions[bot]
bb99e7a5ce
Update precompile_*.jl file [skip ci] (#4096)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-02-11 17:44:40 +01:00
Simon Christ
0813b18d69
Fix regression in legend font size setting (#4100)
* take legend font attributes from existing font

* "format" file

* format remaining files

* better in the error box
2022-02-11 15:26:01 +01:00
t-bltg
6c67908a3a
UnicodePlots: allow setting width / height 2022-02-09 16:04:22 +01:00
t-bltg
a361ba60b8
UnicodePlots: support zoom (#4099) 2022-02-09 14:30:51 +01:00
t-bltg
34c22970f2
UnicodePlots: update hack for png 2022-02-08 23:41:12 +01:00
t-bltg
5d8acf5189
UnicodePlots: add more extra_kwargs (#4097) 2022-02-08 20:56:54 +01:00
t-bltg
59cd5c180e
temporarily disable nightly precomp (#4095) 2022-02-08 13:20:11 +01:00
t-bltg
77e465a453
1.25.8 [skip ci] 2022-02-07 21:52:56 +01:00
github-actions[bot]
eb3e10ffa6
Update precompile_*.jl file [skip ci] (#4074)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-02-07 21:51:24 +01:00
t-bltg
bf5d1aa060
Fix plotattributes in _add_plot_title! (#4090)
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2022-02-07 21:21:22 +01:00
t-bltg
ce70ec26a6
UnicodePlots: 3d support (#4089) 2022-02-07 20:22:39 +01:00
t-bltg
6e4cb5fedc
Fix example 41 (#4093) 2022-02-06 22:32:40 +01:00
Michael Krabbe Borregaard
2a7d2d710e
Merge pull request #4076 from JuliaPlots/mkb/fix_wand
fix the wand binning
2022-01-30 08:24:58 +01:00
t-bltg
e3ea97199f
Precompilation statements for nightly (#4082)
* enable precompilation on nightly

* update CompileBot, add precompile statements for nightly
2022-01-28 22:00:26 +01:00
t-bltg
2896c5a25a
Rework warn_on_unsupported (#4081) 2022-01-28 15:32:15 +01:00
t-bltg
824dbe9948
UnicodePlots: use more extra_kwargs (#4080) 2022-01-28 11:30:42 +01:00
t-bltg
3e8db4532b
UnicodePlots: toggle canvas blend with extra_kwargs 2022-01-28 10:30:27 +01:00
Michael Krabbe Borregaard
0ba580bcaa fix the wand binning 2022-01-26 17:28:56 +01:00
t-bltg
46e19d9ad5
Update docs.yml 2022-01-26 15:35:06 +01:00
t-bltg
b204918b23
Update docs.yml 2022-01-26 15:03:25 +01:00
Tom Gillam
5d5239834c
Example for vspan and hspan (#4062)
* Example for vspan and hspan

* Format

* First time contributor
2022-01-26 13:21:46 +01:00
github-actions[bot]
2ddedf97bf
Update precompile_*.jl file [skip ci] (#4071)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-01-26 11:12:38 +01:00
Simon Christ
5facd2bf55
1.25.7 2022-01-25 22:45:39 +01:00
Simon Christ
915df5d3ee
Fix ribbon slicing (#4068)
* move ribbon handling after slicing

* format file
2022-01-25 21:20:18 +01:00
Simon Christ
2eaf9f3b15
fix plotting empty plot for plotly (#4067) 2022-01-25 17:14:07 +01:00
github-actions[bot]
91bb983c08
Update precompile_*.jl file [skip ci] (#4056)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-01-25 11:06:47 +01:00
t-bltg
311831ca4e
UnicodePlots: do not show blank plots (on layouts) (#4058) 2022-01-22 18:26:13 +01:00
t-bltg
ab698da5a4
Add format check, reduce format PR frequency (#4053) 2022-01-22 16:10:28 +01:00
Tianyi Pu
34e581ff3f
Fix default docstring (#4057) 2022-01-22 15:58:30 +01:00
Zhanibek
acb5d5ac4b
gr-constant-legendbox (#4055) 2022-01-22 02:52:46 +09:00
Zhanibek
e8ac74a390
Revert "gr-constant-legendbox (#4043)" (#4054)
This reverts commit 806e7691851101b1586af2bc23f58b6415405631.
2022-01-22 01:27:28 +09:00
Zhanibek
806e769185
gr-constant-legendbox (#4043) 2022-01-22 01:27:01 +09:00
github-actions[bot]
bcd98737bb
Update precompile_*.jl file [skip ci] (#4050)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-01-19 21:13:01 +01:00
t-bltg
f333cb284a
UnicodePlots: basic quiver and contour support (#4031)
* basic quiver support

* toggle grid

* add contour

* add colorbar

* toggle contour example

* rework keywords
2022-01-19 18:58:11 +01:00
github-actions[bot]
1f49839529
Format .jl files [skip ci] (#4042)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-01-17 12:50:54 +01:00
Simon Christ
536712359c
Update README.md 2022-01-15 10:48:21 +01:00
Simon Christ
b13f3d5021
direct docs link to stable [skip ci] 2022-01-13 10:51:09 +01:00
Simon Christ
2e4344b9b5
Update Project.toml 2022-01-13 09:42:41 +01:00
Josef Heinen
16e5a49800
Bump GR version 2022-01-13 06:29:50 +01:00
Simon Christ
67bd08614a
1.25.6 2022-01-12 16:31:04 +01:00
Simon Christ
a24fb93ab1
Move fillrange and ribbon logic from RecipesPipeline and add tests for default function (#4030)
* add tests for default function

* remove fillrange and ribbon handling from RecipesPipeline

* adjust compat
2022-01-12 15:30:52 +01:00
github-actions[bot]
b1c11cca33
Update precompile_*.jl file [skip ci] (#4032)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-01-12 15:30:26 +01:00
Pearl Li
cffeba7609
Check if plot title already exists before adding again (#4027)
* Check if plot title already exists before adding again

* Add plot title tests
2022-01-12 14:52:43 +01:00
github-actions[bot]
2872c7a345
Update precompile_*.jl file [skip ci] (#4029)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2022-01-12 13:57:25 +01:00
Simon Christ
3313780b4e
add Downloads badge 2022-01-11 20:37:10 +01:00
t-bltg
47ca50d037
1.25.5 [skip ci] 2022-01-11 11:18:42 +01:00
github-actions[bot]
1014b8f494
Update precompile_*.jl file [skip ci] (#4022)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-01-05 14:17:55 +01:00
github-actions[bot]
ece53c5fd1
Format .jl files [skip ci] (#4023)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2022-01-05 14:17:40 +01:00
t-bltg
c34d4e950e
UnicodePlots: fix ansi regex 2022-01-01 10:35:55 +01:00
t-bltg
b6d7bd82e6
UnicodePlots: enhance display / show (#4021) 2021-12-31 16:04:02 +01:00
t-bltg
e5883a3447
1.25.4 [skip ci] 2021-12-29 16:17:50 +01:00
github-actions[bot]
ead9d87942
Update precompile_*.jl file [skip ci] (#4018)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-29 15:24:32 +01:00
t-bltg
0beba9d1c8
Update and rename SnoopCompile.yml to CompileBot.yml 2021-12-29 14:16:23 +01:00
t-bltg
6e79cf4a3e
Run SnoopCompile on master only 2021-12-29 14:04:38 +01:00
github-actions[bot]
693391e135
Update precompile_*.jl file [skip ci] (#4015)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-29 14:03:04 +01:00
Chris Elrod
95d1fa0001
Set max_methods=1 (#4010) 2021-12-29 13:31:29 +01:00
Diego Javier Zea
30d2f01d9d
Update boxplot doc (#4014)
Update and improve whisker_width documentation (boxplots).
2021-12-29 13:30:00 +01:00
Zhanibek
834a1523af add extrakw for colorbar positioning control in 3d 2021-12-27 23:44:37 +09:00
Josef Heinen
e0bc4b1406
[GR] bump version
bump GR version
2021-12-22 12:59:42 +01:00
Simon Christ
492f94bf10
Fix fillranges with OffsetVectors for plotly (#4006)
* don't mutate the Plot object

* remove show

* collect vectors to workaround vcat issue
2021-12-20 21:24:58 +01:00
Simon Christ
cb359c0d4e
1.25.3 [skip ci] 2021-12-20 21:01:25 +01:00
Yuval
3af92908ee
Merge pull request #3988 from yha/yha/boxplot-whisker-range
boxplots docs update: rename range->whisker_range
2021-12-20 18:48:36 +02:00
github-actions[bot]
5d97de1345
Format .jl files [skip ci] (#4012)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-19 23:21:41 +01:00
Simon Christ
f784010c29 add text/latex mimetype 2021-12-17 17:50:07 +01:00
Yuval
d618f2e2ca
Merge pull request #3998 from yha/yha/Unzip2
Use Unzip.unzip
2021-12-16 17:13:21 +02:00
github-actions[bot]
d970a6568e
Format .jl files [skip ci] (#3997)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-12 13:04:15 +01:00
yha
7de50f91de Undo unrelated change 2021-12-12 11:26:05 +02:00
yha
15ce6ebfeb Use Unzip.unzip 2021-12-12 11:16:42 +02:00
Simon Christ
75938bf747
give TagBot its own key [skip ci] 2021-12-10 14:59:14 +01:00
github-actions[bot]
b3e6e92698
Update precompile_*.jl file [skip ci] (#3995)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-12-09 16:23:45 +01:00
Simon Christ
b3002c5457
add manual trigger 2021-12-09 15:56:20 +01:00
Simon Christ
6b44955bc4
1.25.2 [skip ci] 2021-12-09 13:55:48 +01:00
Simon Christ
c28bf96c4a Merge branch 'master' of github.com:JuliaPlots/Plots.jl 2021-12-09 11:54:21 +01:00
Simon Christ
096d293550 fix gr fontcolor setting 2021-12-09 11:54:15 +01:00
Simon Christ
cab76f67e2
fix scale warnings for layouts (#3992)
* fix scale warnings for layouts

* don't run ci twice on PR

* use broadcasting for scalar case
2021-12-09 10:32:06 +01:00
github-actions[bot]
461476f4ed
Update precompile_*.jl file [skip ci] (#3990)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-12-08 16:53:39 +01:00
Simon Christ
11eea2453f
check ref in docs action 2021-12-08 16:08:58 +01:00
Simon Christ
b51cddceb5
add DOCUMENTER_KEY to TagBot action 2021-12-08 15:53:32 +01:00
yha
60222095b6 boxplots: rename range->whisker_range 2021-12-07 19:13:32 +02:00
Simon Christ
5dd0ca27a5
1.25.1 [skip ci] 2021-12-07 17:37:39 +01:00
github-actions[bot]
249ce48cb4
Update precompile_*.jl file [skip ci] (#3987)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-12-07 17:24:53 +01:00
Simon Christ
5f7c2a5eae Fix #3984 2021-12-07 17:05:40 +01:00
github-actions[bot]
9e23082a7d
Format .jl files [skip ci] (#3981)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-05 10:36:34 +01:00
github-actions[bot]
ef3038314d
Update precompile_*.jl file [skip ci] (#3979)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-12-02 20:58:24 +01:00
Jks Liu
c4752b786b
Fix #3967 (#3978)
Pluto do not use require.js, so Plotly is not renamed to Plotly2
2021-12-02 16:33:52 +01:00
t-bltg
a75b17e42f
Bump version to 1.25.0 (#3977) [skip ci]
* bump version
* deprecate NEWS.md
2021-12-02 13:40:25 +01:00
github-actions[bot]
c7e3049dac
Update precompile_*.jl file [skip ci] (#3976)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-12-02 12:03:05 +01:00
t-bltg
3405d2991a
Versioned precompile script - drop 1.5 - support 1.6 and 1.7 (#3972)
* versioned precompile script

* add explicit minor version in CI

* revert to supporting 1.5 - 1.7

* update precompile_includer

* drop support for 1.5, bump to 1.6

* Update ci.yml

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-12-02 11:38:45 +01:00
Simon Christ
ca0e52b622
test on 1.6 also (#3966)
* test on 1.6 also

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

live up to the claimed `[compat]`

* change matrix

* remove ifs

* update include

* split include array

Co-authored-by: Jerry Ling <proton@jling.dev>
2021-12-01 22:24:57 +01:00
t-bltg
b1c56126fb
Fix missing examples backend 2021-12-01 17:43:52 +01:00
t-bltg
e1f507b77f
Update doc examples 2021-12-01 17:30:24 +01:00
t-bltg
0b1ca841cd
1.24.4 [skip ci] 2021-12-01 14:31:41 +01:00
github-actions[bot]
b341df1cb8
Update precompile_*.jl file [skip ci] (#3963)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-12-01 14:30:42 +01:00
Jks Liu
79cf62cf91
Upgrade plotly.js to v2.6.3 (#3958)
* Upgrade plotly.js to version 2.6.3

* plotly polar support, api changed in plotly.js v2.x.x

https://plotly.com/javascript/polar-chart/
https://community.plotly.com/t/announcing-plotly-js-2-0/53675
2021-12-01 13:45:23 +01:00
Simon Christ
c32dbeef8a
1.24.3[skip ci] 2021-11-29 09:46:26 +01:00
chwons
06bc99ef68
annotations over marksers in pgfplotsx backend (#3957) 2021-11-29 09:36:08 +01:00
t-bltg
9305cd41ab
PGFPlotsX: fix log scale power with custom ticks (#3961) 2021-11-29 09:31:47 +01:00
github-actions[bot]
7427a85661
Update precompile_*.jl file [skip ci] (#3956)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-11-29 09:23:18 +01:00
t-bltg
8abae0c575
Formatter: use latest CSTParser tagged version 2021-11-28 13:40:49 +01:00
github-actions[bot]
3963957e70
Format .jl files [skip ci] (#3960)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-11-28 10:27:13 +01:00
Simon Christ
58381822d9
1.24.2 [skip ci] 2021-11-26 14:23:03 +01:00
github-actions[bot]
2472ce164b
Update precompile_*.jl file [skip ci] (#3955)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-11-26 13:34:09 +01:00
Simon Christ
c94cf1855d fix plotly 2021-11-26 13:32:29 +01:00
Simon Christ
6baa120245
fix transposing in plotlyjs (#3953)
* fix transposing

* fix plotly_series
2021-11-26 09:59:44 +01:00
Simon Christ
7e5ba301fd
add documentation for legend_column 2021-11-26 09:47:59 +01:00
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 d880d89ef66eb18731bc67d32d627dd690c6d9e5.

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
t-bltg
0a9d30f7ac
Fix invalid axes aliases (#3803)
* Fix invalid axes aliases

* Add test

* Enhance testing
2021-09-14 18:00:23 +02:00
github-actions[bot]
7da990b23f
Format .jl files [skip ci] (#3801)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-13 09:18:59 +02:00
github-actions[bot]
942fb38dcd
Update precompile_*.jl file [skip ci] (#3797)
Co-authored-by: isentropic <isentropic@users.noreply.github.com>
2021-09-13 09:18:18 +02:00
Zhanibek
7ba99d1b06
handling fonts better, moving to stable 3.4 (#3793)
* handling fonts better, moving to stable 3.4

* better math parent font matching
2021-09-11 13:43:42 +09:00
t-bltg
6b82a82d04
Update examples.jl 2021-09-06 13:18:22 +02:00
t-bltg
7c882a7288
Update Project.toml 2021-09-06 12:48:26 +02:00
github-actions[bot]
5343873f72
Update precompile_*.jl file [skip ci] (#3752)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-06 12:47:06 +02:00
t-bltg
e3a5f2b11e
UnicodePlots: support log scales (#3796) 2021-09-06 12:45:29 +02:00
github-actions[bot]
34758c82a3
Format .jl files [skip ci] (#3795)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-09-06 11:52:32 +02:00
t-bltg
748104c807
UnicodePlots: fix NaN segments plot (#3794) 2021-09-04 12:46:34 +02:00
t-bltg
0d2bc3f227
UnicodePlots: Update URL 2021-09-02 22:20:54 +02:00
t-bltg
c45352d153
fix UnicodePlots.jl/issues/125 (#3791) 2021-09-02 17:59:02 +02:00
Josef Heinen
b833b6582a
Update Project.toml
Bump GR version
2021-09-01 16:55:16 +02:00
t-bltg
b28a261b39
1.21.3 [skip ci] 2021-09-01 14:06:42 +02:00
t-bltg
1a1cc08992
UnicodePlots: fixes 2021-09-01 13:10:09 +02:00
t-bltg
31d33e6be4
UnicodePlots: Allow simple nesting 2021-09-01 12:48:31 +02:00
t-bltg
2dc812aa15
UnicodePlots: support layout (#3787) 2021-09-01 11:26:29 +02:00
t-bltg
bdbe300412
Pyplot: fix building docs (#3775) 2021-09-01 11:24:16 +02:00
Nicholas Bauer
70b635dbe1
Cache axis args in a dictionary (#3775)
Co-authored-by: t-bltg <tf.bltg@gmail.com>
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-08-31 21:36:58 +02:00
t-bltg
1e44dd7035
Unicodeplots: "join" subplots 2021-08-31 00:21:11 +02:00
t-bltg
4744152f86
Add newline between subplots 2021-08-30 23:25:19 +02:00
t-bltg
dc51f2c159
v1.21.2 [skip ci] 2021-08-30 22:22:05 +02:00
t-bltg
cc1f662b3a
UnicodePlots: rm forced width/height (arbitrary) 2021-08-30 17:50:41 +02:00
t-bltg
7b77527f80
UnicodePlots: display fix, simplify axis labels 2021-08-30 14:04:00 +02:00
github-actions[bot]
8b6073c088
Format .jl files [skip ci] (#3780)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-08-29 10:53:46 +02:00
t-bltg
09d35d7b9f
UnicodePlots: heatmap support (#3774)
* UnicodePlots: heatmap support

* Fix type check
2021-08-28 21:29:04 +02:00
Simon Christ
0a9da21443
sanitize axis strings (#3772) 2021-08-28 21:08:21 +02:00
Simon Christ
ea686c331b
improve axis decorations (#3756)
* improve handling of LaTeXStrings in tick labels

* respect guidefonthalign
2021-08-28 21:08:03 +02:00
t-bltg
25a36bab85
merge root codecov.yml [skip ci] 2021-08-28 17:05:13 +02:00
t-bltg
b227fb8943
move codecov.yml 2021-08-28 00:12:43 +02:00
t-bltg
22651e8728
UnicodePlots: disable some unsupported examples 2021-08-26 19:54:58 +02:00
Nicholas Bauer
5acf967a9e
v1.21.1 | No exception thrown in apply_recipe fallback (#3765)
* No exception thrown in `apply_recipe` fallback

Throwing an exception here can vastly slow down plotting, as it happens frequently. Returning an error value instead, which the calling function can check, can speed up plotting 2x. An accompanying change is necessary in RecipesPipeline.jl, assuming this value is suitable.

* Bumped compat for RecipesPipeline, tentative

* Bump patch version

* Fix wrong versioning

Co-authored-by: t-bltg <tf.bltg@gmail.com>
2021-08-26 17:46:28 +02:00
Simon Christ
5afeba656b check if .zenodo.json is valid 2021-08-26 17:17:26 +02:00
LukasKrumwiede
7b8bd5b253
Implementation of filling the space between and under curves for gaston (#3755) 2021-08-26 16:58:05 +02:00
Pearl Li
ded808477d
Add hatched fill for GR and PyPlot (#3107) 2021-08-26 16:55:56 +02:00
Simon Christ
854d5ba5c9
1.21.0 [skip ci] 2021-08-26 16:21:47 +02:00
t-bltg
07a619e5ae
Replace deprecated Base.download with Downloads.download (#3766)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-08-26 00:12:33 +02:00
t-bltg
1426c95fd4
fix formatting action 2021-08-25 22:42:23 +02:00
Andy Nowacki
52ec432cfa
Plotly: Enable specified contour values for ranges; warn otherwise (#3757) 2021-08-25 13:40:54 +02:00
t-bltg
0742d475bc
CI: julia-uploadcodecov is deprecated (#3761) 2021-08-22 12:00:12 +02:00
Josef Heinen
10802baf6e Added support for 3d surface meshes 2021-08-22 09:17:42 +02:00
t-bltg
c67da7d7b8
UnicodePlots: allow passing arbitrary colors (RGBA, symbols, integers, ...) (#3758) 2021-08-19 22:19:38 +02:00
t-bltg
f85f668f18
Merge pull request #3759 from t-bltg/fmt
CI: run JuliaFormatter on schedule
2021-08-19 22:17:47 +02:00
Simon Christ
c4208c7560
fix broken file 2021-08-19 21:07:04 +02:00
t-bltg
35fd604e07 run JuliaFormatter on schedule 2021-08-19 17:51:53 +02:00
t-bltg
214663aa4b
Merge pull request #3750 from t-bltg/col
UnicodePlots: fix setting linecolor
2021-08-15 12:40:19 +02:00
t-bltg
d56a03975f UnicodePlots: fix setting linecolor 2021-08-15 00:39:04 +02:00
t-bltg
ede106073f
1.20.1 [skip ci] 2021-08-12 21:58:21 +02:00
t-bltg
6e8228826d
Merge pull request #3747 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles [skip ci]
2021-08-12 21:57:16 +02:00
t-bltg
8147c59b2f Update precompile_*.jl file [skip ci] 2021-08-12 17:16:25 +00:00
t-bltg
54a6518d59
Merge pull request #3749 from t-bltg/format
Code style - format
2021-08-12 18:48:42 +02:00
t-bltg
c5db139bbb run format(["src", "test"]) 2021-08-11 08:14:51 +02:00
t-bltg
a3eca8244e disable formatting on exports 2021-08-11 07:54:35 +02:00
t-bltg
9164ee09cb fix wrong method signature 2021-08-08 23:18:30 +02:00
t-bltg
ffca3c1305 update JuliaFormatter config file 2021-08-08 20:38:23 +02:00
t-bltg
1c84704a81 move format to separate action 2021-08-08 20:24:18 +02:00
t-bltg
9e824367bb add configuration file 2021-08-08 20:23:22 +02:00
t-bltg
10e9325635 avoid ambiguous += 2021-08-08 20:23:22 +02:00
t-bltg
13141feb4f
Fix #3462 2021-08-04 13:11:15 +02:00
t-bltg
f9833214ce
Merge pull request #3740 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles [skip ci]
2021-08-03 22:02:32 +02:00
t-bltg
a67a006501 Update precompile_*.jl file [skip ci] 2021-08-03 19:20:52 +00:00
t-bltg
40b5df38f4
Merge pull request #3743 from t-bltg/ann
Allow passing collection of tuples to series_annotations
2021-08-03 20:58:12 +02:00
t-bltg
c171cd0cf5
Merge pull request #3745 from t-bltg/mesh3d
Move mesh3d triangle to utils - gaston: implement :mesh3d
2021-08-03 20:57:45 +02:00
t-bltg
b7b4c850b6 move mesh3d triangle to utils - gaston: implement :mesh3d 2021-08-03 20:07:56 +02:00
t-bltg
ba4c4d7bfb
Update backends.jl 2021-08-03 17:58:50 +02:00
t-bltg
62b6075407
Gaston: support :arrow for :quiver 2021-08-03 17:56:54 +02:00
t-bltg
c0ff6e3dee
Gaston: initial :quiver support 2021-08-03 17:55:52 +02:00
t-bltg
67f441f152
Gaston: swap :image axes 2021-08-03 17:54:49 +02:00
t-bltg
ed7b6f7f64
examples, missing number 2021-08-03 17:26:23 +02:00
t-bltg
1ccd4ae699
Gaston: remove :histogram2d 2021-08-03 17:19:40 +02:00
t-bltg
bd70951afa
Gaston: flip y for :image series 2021-08-03 17:19:09 +02:00
t-bltg
39cb596868 allow passing vectors/tuples of vectors to series_annotations 2021-08-03 13:39:20 +02:00
t-bltg
5c13f00716 cleanup 2021-08-03 10:37:05 +02:00
t-bltg
f331bfa010 allow passing tuple to series_annotations 2021-08-03 10:34:53 +02:00
Simon Christ
c4681682a1
1.20.0 [skip ci] 2021-08-03 09:58:28 +02:00
t-bltg
a72b4a3481
specify relative coordinates 2021-08-02 23:30:54 +02:00
t-bltg
ff2ae4fe4f
typo 2021-08-02 21:54:35 +02:00
t-bltg
2df85eb0fd
Update examples.jl 2021-08-02 20:14:40 +02:00
t-bltg
508c47895c
Merge pull request #3634 from t-bltg/annotate
Allow relative positioning of annotations
2021-08-02 17:28:30 +02:00
t-bltg
07d32197a1 add regression test 2021-08-02 16:55:51 +02:00
t-bltg
d6878a8ea0 remove the need for Plots.pct in annotations 2021-08-02 13:06:02 +02:00
Daniel Schwabeneder
b79a2d32fe
fix series_annotations for bar (#3742)
* fix series_annotations for bar

* fix my typos in bar recipe

* fix fillrange of annotation series for groupedbar

* fix series_annotations for bar

* fix my typos in bar recipe

* fix fillrange of annotation series for groupedbar

* fix series_annotations for bar

* fix my typos in bar recipe

* fix fillrange of annotation series for groupedbar

* fix series_annotations for bar

* fix fillrange of annotation series for groupedbar
2021-08-02 12:58:16 +02:00
t-bltg
7b1941b129
Typo 2021-08-01 18:04:10 +02:00
t-bltg
c6d9332cf1
Gaston: fix polar ticks 2021-08-01 18:03:44 +02:00
t-bltg
670fba56a7
Update examples.jl 2021-08-01 17:55:35 +02:00
t-bltg
9985157eb8
Update backends.jl 2021-08-01 17:54:54 +02:00
t-bltg
9308dd74a8
Update gaston.jl 2021-08-01 17:54:15 +02:00
t-bltg
52be7387f2
Gaston: support polar 2021-08-01 17:53:08 +02:00
t-bltg
a94c49ab95
Gaston: remove unsupported :line, :vline markers 2021-08-01 16:19:16 +02:00
t-bltg
b7c6a65921
Gaston: remove :vline, :hline markers 2021-08-01 16:18:19 +02:00
t-bltg
d8a40f5400
Gaston: remove debug show(...) 2021-08-01 16:12:07 +02:00
t-bltg
e4c8921ae9
Gaston: remove more key entries (e.g. :shape) 2021-08-01 16:11:17 +02:00
t-bltg
fe8d08123c
Gaston: fix wrong series_list causing segfault 2021-08-01 16:00:43 +02:00
t-bltg
defe808619
Gaston: update attributes 2021-08-01 15:23:42 +02:00
t-bltg
85fa05464d
Gaston: reset key on contours 2021-08-01 15:16:46 +02:00
t-bltg
a9a24841fe
Gaston: remove debug 2021-08-01 15:04:52 +02:00
t-bltg
0b989cd33e
Gaston: rework multiplot 2021-08-01 15:04:09 +02:00
t-bltg
773c7a90b4
Gaston: conditional add_to_legend 2021-08-01 14:16:07 +02:00
t-bltg
f49f5d1638
Update gaston.jl 2021-08-01 09:47:36 +02:00
t-bltg
478868a6a2
Merge pull request #3741 from t-bltg/scalefontsizes
Rework fontscales - cleanup
2021-08-01 09:31:34 +02:00
t-bltg
806dc3aa43 rework fontscales - cleanup 2021-08-01 09:07:29 +02:00
t-bltg
0f54c86865
Gaston: update examples 2021-08-01 08:46:38 +02:00
t-bltg
5a5864d087
Gaston: rework margins, terminal fontsize and size 2021-08-01 08:35:16 +02:00
t-bltg
baac498532
Merge pull request #3739 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles [skip ci]
2021-08-01 08:07:35 +02:00
t-bltg
9fba70db5e Update precompile_*.jl file [skip ci] 2021-08-01 06:00:06 +00:00
t-bltg
af610735eb
Gaston: fix legend font 2021-08-01 07:38:28 +02:00
t-bltg
204adc3e36
Gaston: add flip - add :log2, :ln scales 2021-08-01 07:22:20 +02:00
t-bltg
603dc10788
Gaston: fix broken multiplot 2021-08-01 01:23:44 +02:00
t-bltg
bf16a97cd5
Gaston: fix legendtitle 2021-08-01 01:16:41 +02:00
t-bltg
8ebe9e8204
Gaston: allow additional series 2021-08-01 00:59:02 +02:00
t-bltg
40cc74bea6
Gaston: fix :steppre, :steppost, add histeps 2021-08-01 00:32:33 +02:00
t-bltg
92cad5376b
Update gaston.jl 2021-08-01 00:21:13 +02:00
t-bltg
a3e1a43358
Merge pull request #3738 from t-bltg/segments
Gaston: add support for img - rework fonts - fix undef
2021-08-01 00:09:28 +02:00
t-bltg
2fcd907165 Gaston: add support for img - rework fonts - fix undef 2021-08-01 00:08:24 +02:00
t-bltg
2769702687
Merge pull request #3734 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles [skip ci]
2021-07-31 22:13:31 +02:00
t-bltg
bf43b9ecec Update precompile_*.jl file [skip ci] 2021-07-31 19:31:14 +00:00
t-bltg
80748eb5e9
Merge pull request #3735 from JuliaPlots/t-bltg-patch-1
GR: remove obsolete method
2021-07-31 21:13:59 +02:00
t-bltg
7863ab9b3b
Update gaston.jl 2021-07-31 20:46:03 +02:00
t-bltg
5bc96cfe68
GR: remove obsolete method 2021-07-31 20:31:58 +02:00
t-bltg
2938950bda
Gaston: missing markers 2021-07-31 20:30:05 +02:00
t-bltg
88b86be17a
Gaston: :hline and :vline are now valid markers 2021-07-31 20:28:37 +02:00
t-bltg
aa6b636793
Gaston: add support for :hline, :vline markers 2021-07-31 20:27:26 +02:00
t-bltg
dc3d302353
Gaston: typo 2021-07-31 19:44:57 +02:00
t-bltg
4ed13644c4
Gaston: minor fixes 2021-07-31 19:21:55 +02:00
t-bltg
34bf55c033
Gaston: blank plot fixes 2021-07-31 19:09:26 +02:00
t-bltg
982c79baa7
Gaston: drop setting termopts in _create_backend_figure 2021-07-31 19:02:29 +02:00
t-bltg
e9b3208d41
Gaston: typo on eval _show 2021-07-31 18:59:49 +02:00
t-bltg
77a9fe3b47
Gaston: add support for background color 2021-07-31 18:50:35 +02:00
t-bltg
4078424f3c
Gaston: add support for annotations 2021-07-31 18:14:40 +02:00
t-bltg
b45400b1d3
Merge pull request #3731 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/t-bltg-patch-1
[AUTO] Update precompiles [skip ci]
2021-07-31 16:43:54 +02:00
t-bltg
dc3e15b4c9
Merge pull request #3730 from JuliaPlots/t-bltg-patch-1
gr_draw_minorgrid should read minorgrid not grid
2021-07-31 16:06:30 +02:00
t-bltg
1e3cb4b4ea Update precompile_*.jl file [skip ci] 2021-07-31 13:07:29 +00:00
t-bltg
57b48da670
Gaston: conditional label in legend 2021-07-31 15:02:40 +02:00
t-bltg
e9e95968a9
GR: code style 2021-07-31 14:50:16 +02:00
t-bltg
1889f5b7f9
Gaston: add support for major/minor grids 2021-07-31 14:44:34 +02:00
t-bltg
2c72882865
gr_draw_minorgrid should read minorgrid not grid 2021-07-31 14:40:51 +02:00
t-bltg
36a9e3b386
Merge pull request #3729 from t-bltg/minor_ticks
Gaston: add minor ticks
2021-07-31 14:35:51 +02:00
t-bltg
03fbc25b33 Gaston: add minor ticks 2021-07-31 14:35:30 +02:00
t-bltg
cbb83e9820
Merge pull request #3728 from t-bltg/markers
Gaston: rework markers (filled, empty) - cleanup
2021-07-31 13:57:04 +02:00
t-bltg
4420e2009f Gaston: rework markers (filled, empty) - cleanup 2021-07-31 13:54:32 +02:00
t-bltg
f394698458
Typo, cleanup 2021-07-31 13:05:23 +02:00
t-bltg
3ec86e983a
Gaston: swap pos and size 2021-07-30 13:29:59 +02:00
t-bltg
5dab21e9ba
Gaston: multiplot, add position 2021-07-30 13:28:22 +02:00
t-bltg
330d3231f6
Gaston: gaston_init_subplot should accept nothing 2021-07-30 13:11:39 +02:00
t-bltg
74b70fc039
Gaston: handle multiple colors 2021-07-30 13:09:59 +02:00
t-bltg
01d5ff1580
Gaston: move update ratios to _update_plot_object 2021-07-30 00:20:38 +02:00
t-bltg
95804039f4
Gaston: Recursive update width/heights from layout 2021-07-29 23:57:58 +02:00
t-bltg
2dec8c1192
Gaston: typo 2021-07-29 22:18:31 +02:00
t-bltg
d3380f4ee8
Gaston: try to respect the layout ratio 2021-07-29 22:16:37 +02:00
t-bltg
cbc0417cea
Gaston: disable legends in contour plots 2021-07-29 21:49:10 +02:00
t-bltg
914ea027d0
Gaston: Unset set size for subplots - Follow Plots.DPI - Cleanup 2021-07-29 19:13:00 +02:00
t-bltg
434656def6
Merge pull request #3727 from t-bltg/debug_mplot
Gaston: debug mplot
2021-07-29 18:42:06 +02:00
t-bltg
e16e46db47 Gaston: debug mplot 2021-07-29 18:40:55 +02:00
t-bltg
9e66eb5737
Merge pull request #3725 from johnnychen94/patch-1
add "no changelog" label for SnoopCompile CI
2021-07-29 15:48:56 +02:00
Johnny Chen
5c02648cdd
add "no changelog" label for SnoopCompile CI
This excludes PRs created by SnoopCompile CI from the release notes.
2021-07-29 13:57:04 +08:00
t-bltg
fd46fd4add
1.19.4 [skip ci] 2021-07-28 19:21:13 +02:00
t-bltg
ac6c7fda11
Merge pull request #3724 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles [skip ci]
2021-07-28 19:09:51 +02:00
t-bltg
4755635fbd Update precompile_*.jl file [skip ci] 2021-07-28 17:08:56 +00:00
t-bltg
c82a3c35ee
Update SnoopCompile.yml 2021-07-28 18:47:15 +02:00
t-bltg
83bce6e895
Update SnoopCompile.yml 2021-07-28 18:45:27 +02:00
t-bltg
07c5019259
Merge pull request #3719 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-28 18:36:57 +02:00
t-bltg
093181d358
Merge pull request #3721 from t-bltg/inset2
Gaston: update inset_subplots
2021-07-28 18:18:14 +02:00
t-bltg
0085706f6f Gaston: update inset_subplots 2021-07-28 18:17:43 +02:00
t-bltg
31359610bd
Merge pull request #3720 from t-bltg/inset
Gaston: fix lens example
2021-07-28 18:03:45 +02:00
t-bltg
34c6c76cb8 Gaston: fix lens example 2021-07-28 18:02:41 +02:00
t-bltg
734b301abc Update precompile_*.jl file 2021-07-28 15:38:02 +00:00
t-bltg
e2907b973f
Gaston: change @assert to @error 2021-07-28 17:17:44 +02:00
t-bltg
9e3ff15522
Skip more Gaston unsupported examples 2021-07-28 17:01:05 +02:00
t-bltg
ce8255a462
Merge pull request #3717 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-28 16:53:53 +02:00
t-bltg
aedb1fbb0b Update precompile_*.jl file 2021-07-28 13:12:51 +00:00
t-bltg
cebcdfb3b5
Merge pull request #3711 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-28 14:52:57 +02:00
t-bltg
b4632c8b48 Update precompile_*.jl file 2021-07-28 11:37:41 +00:00
t-bltg
cd4ab0fd24
Merge pull request #3713 from bernd1995/bernd1995-gr-cbarfont
Added colorbar font attributes for GR
2021-07-28 13:18:25 +02:00
BerndR
e3cd14944c Also added supported args 2021-07-28 12:54:11 +02:00
t-bltg
cac0c8d8d3
Gaston: Remove missing debug leftovers 2021-07-28 12:38:49 +02:00
t-bltg
4f352d8e7c
Update docs.yml 2021-07-28 12:07:52 +02:00
t-bltg
aa32561fe8
Merge pull request #3709 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-28 11:59:22 +02:00
t-bltg
f470e6a590 Update precompile_*.jl file 2021-07-28 09:53:56 +00:00
t-bltg
ca0041639b
Merge pull request #3699 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-28 11:32:17 +02:00
t-bltg
73208ac3bd Update precompile_*.jl file 2021-07-28 09:24:48 +00:00
t-bltg
0112e78c50
Merge pull request #3667 from t-bltg/gaston_add
Add new gnuplot capabilities (surface, contour, contour3d, scatter3d, wireframe, heatmap, ...)
2021-07-28 11:04:57 +02:00
t-bltg
a3f209b100
Merge pull request #3681 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-27 21:19:02 +02:00
t-bltg
573c0cf1bf
Merge pull request #3695 from bernd1995/bernd1995-gr-cbarfont
Added colorbar font settings for GR
2021-07-27 21:18:36 +02:00
t-bltg
a0c939b7c7
Update gr.jl 2021-07-27 20:42:29 +02:00
BerndR
f4ed35c3b6 Added colorbar font settings 2021-07-27 13:10:25 +02:00
t-bltg
50b0ae3b0f Update precompile_*.jl file 2021-07-27 10:04:34 +00:00
t-bltg
f049f56e0b
Fix building docs (JuliaPlots/Plots.jl/issues/3664) 2021-07-27 11:41:07 +02:00
t-bltg
6a459d4c22
Update docs.yml 2021-07-27 11:27:19 +02:00
t-bltg
f576456617
Update docs.yml 2021-07-27 11:21:02 +02:00
t-bltg
a7c4eef861
Update docs.yml 2021-07-26 22:28:25 +02:00
t-bltg
741684251c
Update docs.yml 2021-07-26 22:11:21 +02:00
t-bltg
75bd9dbd01
Update docs.yml 2021-07-26 21:54:16 +02:00
t-bltg
42c60a4fd6
Update docs.yml 2021-07-26 21:47:57 +02:00
t-bltg
92caf2e15f
Update docs.yml 2021-07-26 21:25:14 +02:00
t-bltg
99188f7a7e
Update docs.yml 2021-07-26 20:56:29 +02:00
t-bltg
a9d11cb2be
Update docs.yml 2021-07-26 19:15:26 +02:00
t-bltg
8a3fd8f77e
Merge pull request #3679 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-26 12:02:39 +02:00
t-bltg
bb29abb8a4 Update precompile_*.jl file 2021-07-26 09:52:21 +00:00
t-bltg
b801b2b272 explicit function return, decl - add comments - cleanup 2021-07-26 11:52:13 +02:00
t-bltg
371d9f8dd7
Merge pull request #3677 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-26 11:27:34 +02:00
t-bltg
49f8e48399 Update precompile_*.jl file 2021-07-25 22:25:42 +00:00
t-bltg
dbc14ac761
Merge pull request #3675 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-26 00:04:03 +02:00
t-bltg
c0e35f2358 add new gnuplot capabilities (surface, scatter3d, wireframe, ...) 2021-07-25 23:21:09 +02:00
t-bltg
3ce4e23f1b Update precompile_*.jl file 2021-07-25 19:05:52 +00:00
t-bltg
d4d4d5732b
Update docs.yml 2021-07-25 20:45:59 +02:00
t-bltg
86a732e9c5
Update docs.yml 2021-07-25 19:42:38 +02:00
t-bltg
530768064e
Update docs.yml 2021-07-25 19:33:20 +02:00
t-bltg
89f59532c1
Merge pull request #3672 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-25 18:53:50 +02:00
t-bltg
c41e586385
revert tol changes [skip ci] 2021-07-25 18:52:45 +02:00
t-bltg
8cbfe74863
Update docs.yml 2021-07-25 18:51:46 +02:00
t-bltg
27032a3e21 Update precompile_*.jl file 2021-07-25 16:33:31 +00:00
t-bltg
07a786a946
Update runtests.jl 2021-07-25 18:05:54 +02:00
t-bltg
ad0f623386
Merge pull request #3670 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-25 17:59:45 +02:00
t-bltg
4fa567aa5b
Update docs.yml 2021-07-25 17:58:39 +02:00
t-bltg
c5ae99374a
Update runtests.jl 2021-07-25 17:54:52 +02:00
t-bltg
e79740d3bd Update precompile_*.jl file 2021-07-25 15:49:34 +00:00
t-bltg
dbe6c8dc57
Update docs.yml 2021-07-25 17:47:15 +02:00
t-bltg
9bd075d06b
Merge pull request #3655 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-25 17:29:39 +02:00
t-bltg
1c68a13d2c
Update docs.yml 2021-07-25 17:24:17 +02:00
t-bltg
86d3097123
Merge pull request #3659 from daschw/gr-tickmarks
Make tickmarks the same length for both axes in GR 2D plots
2021-07-25 17:16:12 +02:00
t-bltg
6c2d969316 Update precompile_*.jl file 2021-07-25 12:54:31 +00:00
t-bltg
30e728213e
Merge pull request #3666 from t-bltg/gaston_sp
Fix Gaston layout
2021-07-25 14:32:25 +02:00
t-bltg
4c9fd4e4b7 fix gaston layout 2021-07-25 10:52:20 +02:00
Daniel Schwabeneder
458d72b36b reduce tickmark length 2021-07-24 10:59:06 +02:00
t-bltg
26ddb62a27
Merge pull request #3665 from t-bltg/tol2
More strict on tolerance - drop tol for obsolete version
2021-07-23 20:41:49 +02:00
t-bltg
4aa9d74a28 more strict on tolerance - drop tol for obsolete version 2021-07-23 20:07:08 +02:00
t-bltg
878e590125
Merge pull request #3661 from t-bltg/rng
Use a stable RNG in fakedata
2021-07-23 19:50:54 +02:00
Daniel Schwabeneder
4e5b490b6c make tick length independent of plot size 2021-07-23 19:38:04 +02:00
t-bltg
f3aa61293b change fakedata rng in tests 2021-07-23 14:47:16 +02:00
t-bltg
cd06648ec3
Switch to Random.GLOBAL_RNG
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-07-23 11:02:22 +02:00
t-bltg
fe7d957be3 use a stable RNG in fakedata 2021-07-22 13:00:07 +02:00
t-bltg
a39582c06e
Preempt IMG_TOL with env variable 2021-07-22 02:05:48 +02:00
t-bltg
86fbb39723
Merge pull request #3660 from t-bltg/anim_glob
Avoid using global variables in animation.jl
2021-07-22 01:57:03 +02:00
t-bltg
6f49ec112c avoid using global variables 2021-07-22 01:31:59 +02:00
t-bltg
6594b93126
Add gnuplot to the system dependencies (docs) 2021-07-21 23:49:13 +02:00
Daniel Schwabeneder
f9a1e2e92d
Merge pull request #3656 from JuliaPlots/compathelper/new_version/2021-07-21-00-05-42-160-4162151670
CompatHelper: bump compat for "GeometryBasics" to "0.4"
2021-07-21 22:52:16 +02:00
Daniel Schwabeneder
e58bd8b657 fix minor tick length 2021-07-21 22:39:48 +02:00
Daniel Schwabeneder
5f31ab7169 fix gr tickmarks lengths for 2D plots 2021-07-21 22:30:56 +02:00
t-bltg
b85468162c
Skip failing gaston examples 2021-07-21 21:38:33 +02:00
t-bltg
0550033065
Prepare gaston (gnuplot) for PlotDocs.jl 2021-07-21 19:34:32 +02:00
t-bltg
89db9025c5
1.19.3 [skip ci] 2021-07-21 12:10:19 +02:00
t-bltg
10ed39cf83
Merge pull request #3644 from t-bltg/marker_log
Fix computing marker coordinates with log scales
2021-07-21 12:09:34 +02:00
github-actions[bot]
237fa4be7b CompatHelper: bump compat for "GeometryBasics" to "0.4" 2021-07-21 00:05:47 +00:00
t-bltg
192eb6ffbb
Debugging docs generation 2021-07-20 15:20:03 +02:00
t-bltg
4fc0f85cf1
Merge pull request #3654 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-20 09:59:27 +02:00
t-bltg
aecce08a0f Update precompile_*.jl file 2021-07-19 21:37:24 +00:00
t-bltg
3ad2e0674a
Merge pull request #3653 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-07-19 23:17:39 +02:00
t-bltg
05f585f8ad Update precompile_*.jl file 2021-07-19 19:25:33 +00:00
t-bltg
c6ba6dd899
Merge pull request #3652 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/t-bltg-patch-1
[AUTO] Update precompiles
2021-07-19 21:05:57 +02:00
t-bltg
fcf75a195a
Merge pull request #3651 from JuliaPlots/t-bltg-patch-1
Take series alpha into account when drawing contours
2021-07-19 14:31:02 +02:00
t-bltg
3195a67915 Update precompile_*.jl file 2021-07-19 12:22:01 +00:00
t-bltg
aa837bb027
Take series alpha into account when drawing contours 2021-07-19 14:04:01 +02:00
Simon Christ
7bb2a29356
1.19.2 [skip ci] 2021-07-16 12:18:26 +02:00
github-actions[bot]
f0afadf43a
Update precompile_*.jl file (#3648)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-16 12:02:04 +02:00
github-actions[bot]
0525ade990
Update precompile_*.jl file (#3647)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-16 10:52:29 +02:00
Daniel Schwabeneder
6b22f45dd5
fix dpi for GR (#3646) 2021-07-16 10:30:41 +02:00
Jks Liu
fc0e9a1245
Fix #3440 subplots attributes out of order (#3645) 2021-07-16 10:29:50 +02:00
Josef Heinen
2ec78be9a1
Update Project.toml
bump GR version
2021-07-16 10:28:49 +02:00
github-actions[bot]
4449398614
Update precompile_*.jl file (#3627)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-16 10:26:39 +02:00
t-bltg
946f90d3e4 fix computing marker coordinates with log scales 2021-07-15 12:08:53 +02:00
Simon Christ
c046e6461f
1.19.1 [skip ci] 2021-07-15 09:33:28 +02:00
t-bltg
411de69765
fix plot_title for pyplot (#3642)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-14 22:01:20 +02:00
Simon Christ
4bc6412b46
1.19.0 [skip ci] 2021-07-14 15:51:23 +02:00
Simon Christ
798de8b17c
add the plot_title (#2690)
* add the plot_title

* Update bbs/plot_title (#3604)

* add the plot_title

* update plot_title for multiple subplots, fix GR warning

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>

* Update plot_title (#3608)

* add the plot_title

* update plot_title for multiple subplots, fix GR warning

* update plot_title

* consistency with _subplot_defaults

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>

* custom implementation for pgfplotsx backend

* remove `@show`

* remove superfluous plot_titleindex

Co-authored-by: t-bltg <13423344+t-bltg@users.noreply.github.com>
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-14 15:45:53 +02:00
t-bltg
b0ff0e58b3
InspectDR: Skip more unsupported examples 2021-07-11 21:43:39 +02:00
t-bltg
5cca5e9148
GR: mesh3d, take into account series line attributes 2021-07-11 04:36:22 +02:00
t-bltg
90e0074f44
1.18.2 [skip ci] 2021-07-10 00:55:01 +02:00
t-bltg
3e14a47e17
Update examples.jl
Update skipped examples for auto-gen in PlotDocs
2021-07-09 23:40:17 +02:00
t-bltg
5d608d1e77
Merge pull request #3612 from t-bltg/mesh3d
GR: add support for mesh3d
2021-07-09 23:15:17 +02:00
t-bltg
20e24cfa8d
Merge pull request #3636 from t-bltg/ins_uni
Autogen unicodeplots and inspectdr
2021-07-09 22:11:38 +02:00
t-bltg
2d0191cd70 autogen unicodeplots and inspectdr 2021-07-09 21:40:21 +02:00
t-bltg
12d5accf0a
Update pgfplotsx.jl
Typo
2021-07-09 21:27:48 +02:00
t-bltg
c02dbca31d
Merge pull request #3628 from anowacki/an/annotation-docs
Document use of tuples in annotations attribute
2021-07-08 19:09:22 +02:00
t-bltg
bb493a872a allow relative positioning of annotations 2021-07-08 18:50:46 +02:00
Andy Nowacki
0e25767cd3 Document use of tuples in annotate! shorthand
Include a description of the use of vectors of plain tuples in
the docstring for `annotate!`.
2021-07-08 11:22:44 +01:00
Andy Nowacki
5d935d29c5 Document use of tuples in annotations attribute
The `annotations` attribute (and `annotate!` function) has supported
the use of plain tuples containing arguments which are passed to
`text` since v0.22.2.  Document this option in the list of SubPlot
attributes and in example 20.

Closes (mostly) https://github.com/JuliaPlots/RecipesBase.jl/issues/72
but note that `series_annotations` does not yet support passing tuples
of arguments for `Plots.text`.
2021-07-08 11:04:51 +01:00
t-bltg
f5e6ae9f98 add warning - enhance example 2021-07-08 11:26:49 +02:00
Simon Christ
4a18098944
1.18.1 [skip ci] 2021-07-07 15:58:45 +02:00
Michael Krabbe Borregaard
3994e47d3c
add mkborregaard orcid 2021-07-07 14:26:20 +02:00
github-actions[bot]
39d52a5c57
Update precompile_*.jl file (#3622)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-07 13:03:49 +02:00
t-bltg
91e91ac821
Reduce number of warnings on invalid log values 2021-07-07 00:45:53 +02:00
t-bltg
e9949251a6
Merge pull request #3577 from t-bltg/log_bis
GR: rework automatic major/minor ticks for log scales
2021-07-06 20:49:06 +02:00
t-bltg
16e41f0690 rework phantom ticks for log scales - add minorgrid to ex5 2021-07-06 19:15:34 +02:00
t-bltg
6f4400411e
Merge pull request #3619 from t-bltg/pipeline
Don't propagate widening axis limits for pipeline recipes
2021-07-06 17:21:44 +02:00
github-actions[bot]
1bba6afde5
Update precompile_*.jl file (#3617)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-06 13:53:03 +02:00
t-bltg
909ad3314a fix test 2021-07-05 22:59:22 +02:00
t-bltg
68a56fee91 fix when ticks is nothing - format - minor updates 2021-07-05 22:47:21 +02:00
t-bltg
9f4e32aa4d add regression test 2021-07-05 22:29:38 +02:00
t-bltg
434e189f1e fix JuliaPlots/Plots.jl/issues/3451 2021-07-05 22:12:09 +02:00
Simon Christ
c9f7c6b45d
1.18.0 [skip ci] 2021-07-05 17:53:42 +02:00
Zhanibek
e58fdf970f
Gnuplot (GASTON) backend testing (#3177)
* gnuplot

* minimal working gnuplot

* more params

* new series and axis params

* saving figures

* gnuplot version 0.1
2021-07-05 17:52:59 +02:00
github-actions[bot]
c97900f7ee
Update precompile_*.jl file (#3616)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-05 15:19:03 +02:00
Simon Christ
1b881619e3
1.17.0 [skip ci] 2021-07-05 15:16:19 +02:00
t-bltg
fbd5d79d49
Merge pull request #3590 from t-bltg/warn
GR: 3D, warn on invalid rotation or tilt
2021-07-05 15:01:53 +02:00
Simon Christ
db7420fd5f
fix dispatches for plot and plot! (#3602)
* fix dispatches

* fix tests
2021-07-05 13:25:20 +02:00
t-bltg
09356ee3b5
Merge pull request #3609 from t-bltg/simplify_layouts
Simplify build_layout logic
2021-07-05 12:50:14 +02:00
t-bltg
0122d70640
Merge pull request #3601 from t-bltg/warn_log
Warn on invalid value for log scale based series
2021-07-05 12:13:36 +02:00
t-bltg
5974d0ac31
revert fix for failing CI (#3611)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-05 11:24:22 +02:00
t-bltg
81170b4342 GR: add support for mesh3d 2021-07-05 02:15:51 +02:00
t-bltg
ee316e2913 GR: rework automatic major/minor ticks for log scales 2021-07-04 21:58:13 +02:00
t-bltg
ef93aa87be
Merge pull request #3610 from t-bltg/dist_bug
Bypass JuliaStats/Distributions.jl/issues/1358
2021-07-04 19:22:33 +02:00
t-bltg
88ebb8152d bypass JuliaStats/Distributions.jl/issues/1358 2021-07-04 19:00:28 +02:00
t-bltg
124d2d6aa3 issue warning only once - apply to other backends 2021-07-04 15:48:16 +02:00
t-bltg
cdbafd60c8
Merge pull request #3598 from t-bltg/legend
Fix Latex sub/super-scripts in legends
2021-07-04 15:34:44 +02:00
t-bltg
5eb62abb25 simplify build_layout logic 2021-07-04 15:07:09 +02:00
t-bltg
3f110d6a6c
Merge pull request #3591 from t-bltg/surf_opts
GR: expose surface(...) display options, fix hardcoded constants
2021-07-04 12:50:55 +02:00
t-bltg
293b43013b allow spacing via extra_kwargs 2021-07-03 20:05:53 +02:00
t-bltg
3536acbcc8 warn on invalid value for log scale based series 2021-07-03 14:44:53 +02:00
Simon Christ
0ca5bc9124
1.16.8 [skip ci] 2021-07-02 21:27:21 +02:00
t-bltg
14b38354da fix #3558 2021-07-02 20:26:24 +02:00
t-bltg
06c551ba51
Skip example 55 for PyPlot, Plotlyjs and Plotly
PgfPlotsX looks ok
2021-07-02 16:57:35 +02:00
t-bltg
f63ee6d79e
enhance example 55 (#3596)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-07-02 15:06:36 +02:00
github-actions[bot]
b3f698c460
Update precompile_*.jl file (#3592)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-02 09:42:25 +02:00
Simon Christ
829860fa2d
use sinc in example 55 2021-07-02 09:17:56 +02:00
Simon Christ
1523ef67d5
simplify example 55 2021-07-01 21:41:35 +02:00
github-actions[bot]
e049b082f3
[AUTO] Update precompiles (#3573)
* add tests for series_annotations in layouts

* add methods for matrices of annotations

* defensive copy on plot(plots)

* seperate in plot(plots) and plot!(plots)

* Update precompile_*.jl file

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-07-01 18:40:58 +02:00
Simon Christ
f78899a1ef
return plot object 2021-07-01 18:28:50 +02:00
t-bltg
e42b4ad34d GR: surface, add the possibility to override the hardcoded nx and ny in GR.gridit(...) 2021-07-01 16:54:07 +02:00
t-bltg
a7c629f775 GR: expose surface(...) display options 2021-07-01 15:08:36 +02:00
t-bltg
1ddc673201 GR: 3D, warn on invalid rotation or tilt 2021-07-01 14:02:30 +02:00
t-bltg
bba971f7ea
GR: fix axis flip / mirror in 3D plots (#3584)
* fix axis flip in 3D plots

* add mwe as example - fix needs_3d_axes

* fix major / minor grids when mirroring

Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-06-30 22:50:09 +02:00
Simon Christ
3f9105054c
1.16.7 [skip ci] 2021-06-30 11:30:37 +02:00
t-bltg
a64ae3d13c
GR: fix alignment of ticks label when rotating (#3587)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-06-30 09:30:55 +02:00
t-bltg
7b0066c433
simplify major / minor grid segments (#3586)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-06-25 21:10:35 +02:00
Simon Christ
d657c0cb33
1.16.6 [skip ci] 2021-06-25 16:57:10 +02:00
t-bltg
50f63cf1eb
Ignore :blank plots (#3585) 2021-06-25 15:40:49 +02:00
Simon Christ
2b22dae757
Handle matrices of annotations and copy for plot(plots) (#3572)
* add tests for series_annotations in layouts

* add methods for matrices of annotations

* defensive copy on plot(plots)

* seperate in plot(plots) and plot!(plots)
2021-06-17 09:29:39 +02:00
Simon Christ
7ca32b5edd
show ekwargs on show (#3567) 2021-06-12 09:38:10 +02:00
Simon Christ
3f5a1287be
1.16.5[skip ci] 2021-06-10 15:48:03 +02:00
Simon Christ
990e0f3f7f
Better twinx (#3564)
* improve twinx

* add tests, disable gridlines of twinx
2021-06-10 15:00:19 +02:00
Simon Christ
849d31d57f markers -> mark for older pgfplots version 2021-06-09 16:54:55 +02:00
Simon Christ
cfe5ba24a6
1.16.4 [skip ci] 2021-06-09 15:54:34 +02:00
Simon Christ
be1c263df9
no markers on fillranges (#3563) 2021-06-09 15:53:52 +02:00
Fons van der Plas
203af856cd
embeddable_html (#3559) 2021-06-09 09:01:40 +02:00
Fred Callaway
019a742c84
Respect :widen when passing :lims (#3552)
* Respect :widen when passing :lims

Previously, the limits were not widened when passing a tuple or
:round to lims (ignoring the widen argument). Fixes #3339

* Add default widen=:auto, which matches default before 43e9a342

* If widen is a Bool, it always determines whether widening occurs.
* If widen is :auto (the defualt), widening occurs for appropriate
  seriestypes, unless lims were set manually

* Update test/test_axes.jl

Co-authored-by: Simon Christ <SimonChrist@gmx.de>

* fix docs for lims and widen interaction

* Update .zenodo.json

* Update test/test_axes.jl

xlims != ylims

Co-authored-by: Simon Christ <SimonChrist@gmx.de>

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2021-06-07 20:46:49 +02:00
Simon Christ
5330776040
1.16.3 [skip ci] 2021-06-07 19:56:24 +02:00
Simon Christ
fcdb3c1c0d
remove markers from fillranges (#3553) 2021-06-07 18:29:36 +02:00
Simon Christ
cc290818d7
fix setting marker = :none without seriestype (#3550) 2021-06-07 15:55:43 +02:00
Simon Christ
14b3852060
add :symmetric docs 2021-06-04 22:09:51 +02:00
Simon Christ
387f918080
[skip ci] 2021-06-04 17:29:13 +02:00
Simon Christ
d0d95c6cc7
1.16.2 [skip ci] 2021-06-04 17:09:25 +02:00
Simon Christ
d51059f0e9
set projection for 3dquivers (#3544)
* set projection for 3dquivers

* fix test
2021-06-04 17:08:33 +02:00
Simon Christ
4723c513be
1.16.1 [skip ci] 2021-06-04 15:39:51 +02:00
Simon Christ
d1373d8b89
fix fontfamily (#3542)
* fix fontfamily

* Update test_defaults.jl
2021-06-04 15:36:40 +02:00
Simon Christ
9f51b96269
1.16.0 [skip ci] 2021-06-03 19:00:39 +02:00
t-bltg
601df0c9a9
GR: allow explicit guidefontrotation (#3529)
Co-authored-by: t-bltg <t-bltg@users.noreply.github.com>
2021-06-03 19:00:06 +02:00
github-actions[bot]
700b5782ec
Update precompile_*.jl file (#3536)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-06-03 17:36:51 +02:00
Simon Christ
6a62d96751
axis limits = :symmetric (#2600)
* allow axis-lims = :symmetric

* remove show

* add test
2021-06-03 17:35:42 +02:00
Simon Christ
25b57cfb55
Run tests of GraphRecipes and StatsPlots (#3519)
* run tests of StatsPlots and GraphRecipes

* one environment each

* correct paths
2021-06-03 11:08:37 +02:00
github-actions[bot]
fb390d1872
Update precompile_*.jl file (#3535)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-06-03 10:58:38 +02:00
Simon Christ
5fafddb995
fix fontrotation being interpreted as fontsize (#3533)
* fix convenience font functions

* correct size argument
2021-06-02 22:12:30 +02:00
Simon Christ
697e5a87cf
1.15.3 [skip ci] 2021-06-02 16:29:59 +02:00
github-actions[bot]
77ba81de19
Update precompile_*.jl file (#3530) [skip ci]
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-06-02 16:14:02 +02:00
Simon Christ
e43f3ee373
Drop compat for older GR versions (#3526) 2021-06-02 08:24:42 +02:00
Simon Christ
8f055fef3d
1.15.2 [skip ci] 2021-05-20 20:43:29 +02:00
Simon Christ
ce530ef518
fix vector of shapes (#3517) 2021-05-20 20:42:31 +02:00
BerndR
827462dc21
NaN checking in backends/gr.jl (#3514)
* Updated .zenodo.json infos

* resolved NaN-checking
2021-05-19 20:33:33 +02:00
github-actions[bot]
1ecec912a1
Update precompile_*.jl file (#3508) [skip ci]
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-05-19 08:53:17 +02:00
Simon Christ
ca8e775b83
1.15.1[skip ci] 2021-05-19 08:29:08 +02:00
Fons van der Plas
c0e50588d3
Minor cleanup plotlyjs (#3510) 2021-05-19 08:28:03 +02:00
Simon Christ
de7717b85f
Fix too many legend entries (#3511)
* add test

* fix legend entries
2021-05-19 08:27:41 +02:00
Simon Christ
a1311e5c60 all the names [skip ci] 2021-05-18 18:21:45 +02:00
Simon Christ
4069b73563
Update .zenodo.json 2021-05-17 17:58:12 +02:00
Simon Christ
a7d6e93af3
1.15.0 [skip ci] 2021-05-17 09:57:18 +02:00
Simon Christ
058983165e
change DOI [skip ci] 2021-05-17 09:55:47 +02:00
Simon Christ
97036e689e
Create .zenodo.json (#3482)
* Create .zenodo.json

* Update .zenodo.json

Co-authored-by: Daniel Schwabeneder <daschw@disroot.org>

* add members, classify contributors

* Apply suggestions from code review

Co-authored-by: Daniel Schwabeneder <daschw@disroot.org>

* add all names

Co-authored-by: Daniel Schwabeneder <daschw@disroot.org>
2021-05-17 09:43:23 +02:00
github-actions[bot]
d3589db840
Update precompile_*.jl file (#3484)
Co-authored-by: daschw <daschw@users.noreply.github.com>
2021-05-14 22:03:29 +02:00
Simon Christ
15bd9c537d
Create docs on pushing to master (#3494)
* Create docs.yml

* Update docs.yml

* Update docs.yml

* Create docs.yml

* Update docs.yml

* [skip ci]

* [skip ci]

* [skip ci]

* [skip ci]

* Update docs.yml

* Update docs.yml

* Update docs.yml

* Update docs.yml

* fix pgfplotsx

* fix pyplot

* remove push workflow (should work without)

* conditionally fix pyplot

* change env-vars

* fix

* fix ref

* clean up and cache artifacts

* add Documenter_key to environment

* fix parentheses

* "one last fix"

* dev => add

* fix marker example

* exclude 50 for plotly

* install ms fonts

* only trigger on master

* remove REF pretending
2021-05-14 22:00:09 +02:00
Daniel Schwabeneder
27764bbc67
Merge pull request #3497 from giordano/mg/animate-while
Allow `while`-block in at-animate macro
2021-05-14 19:19:05 +02:00
Mosè Giordano
788e28d18a Allow while-block in at-animate macro 2021-05-13 10:14:03 +01:00
Asim H Dar
d544647b1b
Update plotly.jl (#3491)
Tiny typo
2021-05-12 18:36:14 +02:00
Simon Christ
3cb81d6d04
fix alpha for surface (#3489) 2021-05-12 18:35:19 +02:00
Yuval
61f2d825b6
Merge pull request #3468 from yha/several-nans-fix
Fix for plotting a vector of (at least two) NaNs
2021-05-11 17:56:33 +03:00
Daniel Schwabeneder
5df64bd45b
Merge pull request #3463 from gustaphe/fontdefaults
Add annotation font defaults/settings
2021-05-11 01:03:09 +02:00
Simon Christ
7e997da6bd
1.14.0 [skip ci] 2021-05-10 19:53:10 +02:00
Simon Christ
35658bf4fe fix tests 2021-05-07 08:14:37 +02:00
Simon Christ
f355ff9904 clean up pgfx-legends duplications 2021-05-06 21:27:24 +02:00
github-actions[bot]
8893782b13
[AUTO] Update precompiles (#3471)
* add legend stylings

* fix center and default case

* Update precompile_*.jl file

Co-authored-by: Simon Christ <simonchrist@gmx.de>
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-05-04 20:54:43 +02:00
Simon Christ
78f7db138f
add legend stylings (#3470)
* add legend stylings

* fix center and default case
2021-05-04 20:54:11 +02:00
yha
23567964e7 undo accidental change 2021-05-03 19:45:48 +03:00
yha
0c7f7ba011 Fix for plotting a vector of (at least two) NaNs 2021-05-03 19:44:11 +03:00
David Gustavsson
4731477920 Add annotation font defaults 2021-05-01 20:39:55 +02:00
Daniel Schwabeneder
57ba6aa5a9
Merge pull request #3458 from daschw/tickmarks
add `tick_direction=:none` option to hide tick marks
2021-04-29 10:54:54 +02:00
Simon Christ
3c472f24b5
add DOI badge 2021-04-28 22:20:34 +02:00
Daniel Schwabeneder
5a4651a0ec clean changes in recipes.jl 2021-04-28 20:35:00 +02:00
Daniel Schwabeneder
7bb2132b18 add tick_direction=:none option to hide tick labels 2021-04-28 20:27:50 +02:00
Daniel Schwabeneder
fd50469e20
Merge pull request #3430 from ma-laforge/idr_layout
Update plot areas for the given font sizes.
2021-04-28 18:42:14 +02:00
Daniel Schwabeneder
e3d13aa17a
Merge pull request #3436 from gustaphe/master
Generalize Shape
2021-04-28 18:40:57 +02:00
Simon Christ
476de3d2a2
1.13.2 [skip ci] 2021-04-28 09:52:54 +02:00
Yuval
c986bfa1e6
Merge pull request #3443 from yha/plotly-shapes-fix
Fix shapes series on plotly
2021-04-27 13:05:32 +03:00
github-actions[bot]
dfd8fada9d
[AUTO] Update precompiles (#3455)
* incorporate colorbar ticks and ticklabel styles

* fix colorbar showing

* Update precompile_*.jl file

Co-authored-by: Simon Christ <SimonChrist@gmx.de>
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2021-04-27 10:35:28 +02:00
Simon Christ
d4298bf1cc
1.13.1 [skip ci] 2021-04-27 10:35:12 +02:00
Simon Christ
02437562a7
colorbar improvements for pgfplotsx (#3441)
* incorporate colorbar ticks and ticklabel styles

* fix colorbar showing
2021-04-27 09:50:49 +02:00
Benoit Pasquier
8cf268a390
Add ticks getter functions (#3435)
* Add ticks getter functions

* Add tick-getter functions for Plot objects

* Fix boiler-plate code in get_ticks

* Bump minor version + add tests

* Remove kwargs and add subplot test

* Add docstrings

* bump minor version
2021-04-23 08:52:17 +02:00
Simon Christ
fbf3878ca5
1.12.0 [skip ci] 2021-04-20 11:21:54 +02:00
yha
e449d3221c Fix shapes series on plotly 2021-04-18 13:41:10 +03:00
David Gustavsson
a359f21325 Generalize Shape 2021-04-14 09:34:06 +02:00
MA Laforge
9da550ba3b Update plot areas for the given font sizes.
Also:
Layout changes are made to defaults instead of user-overwrites.
2021-04-10 14:57:39 -04:00
Daniel Schwabeneder
0a7035979f
Merge pull request #3412 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-04-10 12:59:18 +02:00
Daniel Schwabeneder
6376d40ae2
Merge pull request #3423 from matthieugomez/master
correct scatterpath + add linearfit
2021-04-10 12:58:26 +02:00
matthieugomez
67f4d79c4a simpler formula for yhat 2021-04-08 10:11:09 -07:00
matthieugomez
50adb6cd9c Update recipes.jl 2021-04-07 14:42:12 -07:00
matthieugomez
64f3d589b6 correct scatterpath + add linearfit
correct scatterpath so that color does not change (see https://github.com/JuliaPlots/Plots.jl/issues/1495). Add linearfit.
2021-04-07 14:39:41 -07:00
isentropic
07b05e075e Update precompile_*.jl file 2021-04-05 05:16:17 +00:00
Zhanibek
1ceb3a561f pyplot, rawticklabels extra_kwarg added 2021-04-05 13:56:00 +09:00
Daniel Schwabeneder
e1e0f8d1c9
Merge pull request #3411 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-04-01 19:59:59 +02:00
Daniel Schwabeneder
f39ba03da5
Merge pull request #3409 from daschw/bar
fix multiple legend in pgfplotsx bar plots
2021-04-01 19:59:06 +02:00
daschw
7d7212ba3e Update precompile_*.jl file 2021-04-01 17:56:06 +00:00
Daniel Schwabeneder
17a942998d
Merge pull request #3407 from JuliaPlots/Test_SnoopCompile_AutoPR_refs/heads/master
[AUTO] Update precompiles
2021-04-01 19:29:45 +02:00
Daniel Schwabeneder
6a829e2b1a
Merge pull request #3405 from JuliaPlots/compathelper/new_version/2021-04-01-00-46-46-673-1268091602
CompatHelper: bump compat for "Latexify" to "0.15"
2021-04-01 19:29:28 +02:00
Daniel Schwabeneder
c56654c6cf fix multiple legend in pgfplotsx bar plots 2021-04-01 17:21:29 +02:00
daschw
90255913a4 Update precompile_*.jl file 2021-04-01 15:09:56 +00:00
75 changed files with 11294 additions and 5020 deletions

12
.JuliaFormatter.toml Normal file
View File

@ -0,0 +1,12 @@
always_for_in = true
import_to_using = false
align_pair_arrow = true
align_assignment = true
align_conditional = true
always_use_return = false
conditional_to_if = false
whitespace_in_kwargs = true
remove_extra_newlines = true
whitespace_ops_in_indices = true
short_to_long_function_def = false
annotate_untyped_fields_with_any = false

View File

@ -20,13 +20,14 @@ Backend | yes | no | untested
-------------|-----|-----|--------- -------------|-----|-----|---------
gr (default) | | | gr (default) | | |
pyplot | | | pyplot | | |
plotly | | |
plotlyjs | | | plotlyjs | | |
pgfplotsx | | | pgfplotsx | | |
unicodeplots | | |
inspectdr | | | inspectdr | | |
gaston | | |
### Versions ### Versions
Plots.jl version: Plots.jl version:
Backend version (`]st -m`): Backend version (`]st -m <backend(s)>`):
Output of `versioninfo()`: Output of `versioninfo()`:

View File

@ -1,9 +1,11 @@
# NOTE: this file should be named 'SnoopCompile.yml', cf github.com/aminya/CompileBot.jl/blob/master/src/CompileBot.jl#L57
name: SnoopCompile name: SnoopCompile
on: on:
push: push:
branches: branches:
# - 'master' # NOTE: to run the bot only on pushes to master - master # NOTE: to run the bot only on pushes to master
defaults: defaults:
run: run:
@ -14,14 +16,19 @@ jobs:
if: "!contains(github.event.head_commit.message, '[skip ci]')" if: "!contains(github.event.head_commit.message, '[skip ci]')"
env: env:
GKS_ENCODING: "utf8" GKS_ENCODING: "utf8"
GKSwstype: "100" GKSwstype: "nul"
PLOTS_TEST: "true" PLOTS_TEST: "true"
runs-on: ${{ matrix.os }} runs-on: ${{matrix.os}}
continue-on-error: ${{ matrix.version == '~1.8.0-0' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
version: # NOTE: the versions below should match those in your botconfig version: # NOTE: the versions below should match those in your botconfig
- '1' - '1.6' # ⎤
- '1.7' # |
- '~1.8.0-0' # |
# - 'nightly' # ⎦ <<< keep these versions in sync with deps/SnoopCompile/snoop_bot_config.jl
# ^^^^^^^^^ for 'nightly', see github.com/JuliaPlots/Plots.jl/issues/4079
os: # NOTE: should match the os setting of your botconfig os: # NOTE: should match the os setting of your botconfig
- ubuntu-latest - ubuntu-latest
arch: arch:
@ -31,13 +38,22 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest - uses: julia-actions/setup-julia@latest
with: with:
version: ${{ matrix.version }} version: ${{matrix.version}}
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10 # required (not enough memory on github actions virtual machine)
- name: Install dependencies - name: Install dependencies
run: | run: |
julia --project -e 'using Pkg; Pkg.instantiate();' cat /proc/cpuinfo
julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); Pkg.develop(PackageSpec(; path=pwd())); using CompileBot; CompileBot.addtestdep();' cat /proc/meminfo
cat /proc/swaps
free
df -h
julia --project -e 'using Pkg; Pkg.instantiate()'
julia -e 'using Pkg; Pkg.add(PackageSpec(name="CompileBot", version="1")); Pkg.develop(PackageSpec(; path=pwd())); using CompileBot; CompileBot.addtestdep()'
# TESTCMD # TESTCMD
- name: Default TESTCMD - name: Default TESTCMD
@ -69,18 +85,21 @@ jobs:
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
- name: CompileBot postprocess - name: CompileBot postprocess
run: julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();' run: |
if ! grep -m1 -q 'format: off' 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 - name: Create Pull Request
uses: peter-evans/create-pull-request@v3 uses: peter-evans/create-pull-request@v3
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update precompile_*.jl file commit-message: Update precompile_*.jl file [skip ci]
title: "[AUTO] Update precompiles" title: "[AUTO] Update precompiles [skip ci]"
labels: SnoopCompile labels: |
SnoopCompile
no changelog
branch: "Test_SnoopCompile_AutoPR_${{ github.ref }}" branch: "Test_SnoopCompile_AutoPR_${{ github.ref }}"
Skip: Skip:
if: "contains(github.event.head_commit.message, '[skip ci]')" if: "contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -12,3 +12,4 @@ jobs:
- uses: JuliaRegistries/TagBot@v1 - uses: JuliaRegistries/TagBot@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.TAGBOT_KEY }}

View File

@ -1,4 +1,4 @@
name: Run benchmarks name: benchmarks
on: on:
pull_request: pull_request:
@ -6,17 +6,14 @@ on:
jobs: jobs:
Benchmark: Benchmark:
if: "!contains(github.event.head_commit.message, '[skip ci]')" if: "!contains(github.event.head_commit.message, '[skip ci]')"
env:
GKS_ENCODING: "utf8"
GKSwstype: "100"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest - uses: julia-actions/setup-julia@latest
with: with:
version: 1 version: '1.7'
## Setup # Setup
- name: Ubuntu TESTCMD - name: Ubuntu TESTCMD
run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV
- name: Install Plots dependencies - name: Install Plots dependencies

View File

@ -2,6 +2,8 @@ name: ci
on: on:
push: push:
branches:
- master
pull_request: pull_request:
defaults: defaults:
@ -13,7 +15,7 @@ jobs:
if: "!contains(github.event.head_commit.message, '[skip ci]')" if: "!contains(github.event.head_commit.message, '[skip ci]')"
env: env:
GKS_ENCODING: "utf8" GKS_ENCODING: "utf8"
GKSwstype: "100" GKSwstype: "nul"
name: Julia ${{ matrix.version }} - ${{ matrix.os }} name: Julia ${{ matrix.version }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -22,8 +24,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
version: version:
- '1' - '1.6' # LTS
- 'nightly' - '1.7' # latest stable
os: os:
- ubuntu-latest - ubuntu-latest
- windows-latest - windows-latest
@ -31,9 +33,11 @@ jobs:
arch: arch:
- x64 - x64
# - x86 # - x86
include:
- version: 'nightly'
os: ubuntu-latest
steps: steps:
# Setup environment # Setup environment
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest - uses: julia-actions/setup-julia@latest
@ -51,19 +55,16 @@ jobs:
${{ runner.os }}-test- ${{ runner.os }}-test-
${{ runner.os }}- ${{ runner.os }}-
## maybe required if we ever want to run graphical tests for plotly
# OS Dependencies
# - name: Ubuntu OS dependencies
# if: startsWith(matrix.os,'ubuntu')
# run: |
# ./test/install_wkhtmltoimage.sh
# TESTCMD # TESTCMD
- name: Default TESTCMD - name: Default TESTCMD
run: echo "TESTCMD=julia" >> $GITHUB_ENV run: echo "TESTCMD=julia" >> $GITHUB_ENV
- name: Ubuntu TESTCMD - name: Ubuntu TESTCMD
if: startsWith(matrix.os,'ubuntu') if: startsWith(matrix.os,'ubuntu')
run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV run: |
echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV
sudo apt-get -y update
sudo apt-get -y install gnuplot poppler-utils texlive-{latex-base,latex-extra,luatex}
sudo fc-cache -vr
# Julia Dependencies # Julia Dependencies
- name: Install Julia dependencies - name: Install Julia dependencies
@ -71,12 +72,18 @@ jobs:
# Run tests # Run tests
- name: Run Graphical test - name: Run Graphical test
run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true);' run: |
$TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true)'
$TESTCMD -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("StatsPlots"); Pkg.test("StatsPlots")'
$TESTCMD -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("GraphRecipes"); Pkg.test("GraphRecipes")'
- name: Codecov # Codecov
uses: julia-actions/julia-uploadcodecov@latest - uses: julia-actions/julia-processcoverage@v1
env: if: startsWith(matrix.os,'ubuntu')
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - uses: codecov/codecov-action@v2
if: startsWith(matrix.os,'ubuntu')
with:
file: lcov.info
Skip: Skip:
if: "contains(github.event.head_commit.message, '[skip ci]')" if: "contains(github.event.head_commit.message, '[skip ci]')"

34
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: docs
on:
workflow_dispatch:
push:
branches:
- master
tags: '*'
jobs:
Build_docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
repository: JuliaPlots/PlotDocs.jl
- uses: julia-actions/setup-julia@v1
- name: Cache artifacts
uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{runner.os}}-test-${{env.cache-name}}-${{hashFiles('**/Project.toml')}}
restore-keys: |
${{runner.os}}-test-${{env.cache-name}}-
${{runner.os}}-test-
${{runner.os}}-
- name: Build documentation
env:
PYTHON: ""
DOCUMENTER_KEY: ${{secrets.DOCUMENTER_KEY}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: bash docs/ci_build.sh

54
.github/workflows/format_check.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: format
on:
pull_request:
push:
branches:
- 'master'
jobs:
code-style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- name: Install dependencies
run: |
using Pkg
Pkg.add([
PackageSpec("JuliaFormatter"),
PackageSpec(url = "https://github.com/tkf/JuliaProjectFormatter.jl.git"),
])
shell: julia --color=yes {0}
- name: Format Julia files
run: |
using JuliaFormatter
format(["src", "test"])
shell: julia --color=yes --compile=min -O0 {0}
- name: suggester / JuliaFormatter
uses: reviewdog/action-suggester@v1
with:
tool_name: JuliaFormatter
fail_on_error: true
# reviewdog/action-suggester not using `cleanup` flag?
- name: Cleanup
if: success() || failure()
run: |
git checkout -- .
git clean --force
shell: bash
- name: Format Julia project files
if: success() || failure()
run: |
using JuliaProjectFormatter
format_projects()
shell: julia --color=yes --compile=min -O0 {0}
- name: suggester / JuliaProjectFormatter
if: success() || failure()
uses: reviewdog/action-suggester@v1
with:
tool_name: JuliaProjectFormatter
fail_on_error: true

35
.github/workflows/format_pr.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: format
on:
schedule:
- cron: '0 0 1 * *'
jobs:
pr:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install JuliaFormatter and format
run: |
julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))'
julia -e 'using JuliaFormatter; [format(["src", "test"]) for _ in 1:2]'
git diff --exit-code
- name: Create Pull Request
if: ${{ failure() }}
id: cpr
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Format .jl files [skip ci]"
title: 'Automatic JuliaFormatter.jl run'
branch: auto-juliaformatter-pr
delete-branch: true
labels: formatting, automated pr, no changelog
- name: Check outputs
if: ${{ failure() }}
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ dev/
test/tmpplotsave.hdf5 test/tmpplotsave.hdf5
/.benchmarkci /.benchmarkci
/benchmark/*.json /benchmark/*.json
.vscode/

722
.zenodo.json Normal file
View File

@ -0,0 +1,722 @@
{
"title": "Plots.jl",
"license": "MIT",
"creators": [
{
"affiliation": "Headlands Technologies",
"name": "Tom Breloff"
}
],
"contributors":[
{
"affiliation": "TU Wien",
"name": "Daniel Schwabeneder",
"orcid": "0000-0002-0412-0777",
"type": "ProjectLeader"
},
{
"affiliation": "GLOBE Institute, University of Copenhagen",
"name": "Michael Krabbe Borregaard",
"orcid": "0000-0002-8146-8435",
"type": "ProjectLeader"
},
{
"affiliation": "Leibniz Universit\u00e4t Hannover",
"name": "Simon Christ",
"orcid": "0000-0002-5866-1472",
"type": "ProjectLeader"
},
{
"affiliation": "Forschungszentrum J\u00fclich",
"name": "Josef Heinen",
"orcid": "0000-0001-6509-1925",
"type": "ProjectMember"
},
{
"name": "Yuval",
"type": "Other"
},
{
"name": "Andrew Palugniok",
"type": "ProjectMember"
},
{
"affiliation": "@beacon-biosignals",
"name": "Simon Danisch",
"type": "Other"
},
{
"affiliation": "Veos Digital (https://veos.digital/)",
"name": "Pietro Vertechi",
"type": "ProjectMember"
},
{
"affiliation": "Korea Advanced Inst. of Science and Technology (KAIST)",
"name": "Zhanibek Omarov",
"type": "ProjectMember",
"orcid": "0000-0002-8783-8791"
},
{
"name": "Thatcher Chamberlin",
"type": "Other"
},
{
"name": "@ma-laforge",
"type": "ProjectMember"
},
{
"affiliation": "Massachusetts Institute of Technology",
"name": "Christopher Rackauckas",
"orcid": "0000-0001-5850-0663",
"type": "Other"
},
{
"affiliation": "Max Planck Institute for Physics",
"name": "Oliver Schulz",
"type": "Other"
},
{
"affiliation": "@JuliaComputing",
"name": "Sebastian Pfitzner",
"type": "Other"
},
{
"name": "Takafumi Arakaki",
"type": "Other"
},
{
"affiliation": "University of Manitoba",
"name": "Amin Yahyaabadi",
"type": "Other"
},
{
"name": "Jack Devine",
"type": "Other"
},
{
"name": "Sebastian Pech",
"type": "Other"
},
{
"affiliation": "@JuliaComputing",
"name": "Patrick Kofod Mogensen",
"type": "Other",
"orcid": "0000-0002-4910-1932"
},
{
"name": "Samuel S. Watson",
"type": "Other"
},
{
"affiliation": "UC Davis",
"name": "Naoki Saito",
"orcid": "0000-0001-5234-4719",
"type": "Other"
},
{
"affiliation": "University of Southern California (USC)",
"name": "Benoit Pasquier",
"orcid": "0000-0002-3838-5976",
"type": "Other"
},
{
"affiliation": "NTNU Trondheim",
"name": "Ronny Bergmann",
"orcid": "0000-0001-8342-7218",
"type": "Other"
},
{
"name": "Andy Nowacki",
"affiliation": "University of Leeds",
"orcid": "0000-0001-7669-7383",
"type": "Other"
},
{
"name": "Ian Butterworth",
"type": "Other"
},
{
"affiliation": "Lund University",
"name": "David Gustavsson",
"type": "Other"
},
{
"name": "Anshul Singhvi",
"affiliation": "Columbia University",
"orcid": "0000-0001-6055-1291",
"type": "Other"
},
{
"name": "david-macmahon",
"type": "Other"
},
{
"name": "Fredrik Ekre",
"type": "Other"
},
{
"name": "Maaz Bin Tahir Saeed",
"type": "Other"
},
{
"name": "Kristoffer Carlsson",
"type": "Other"
},
{
"name": "Will Kearney",
"type": "Other"
},
{
"name": "Niklas Korsbo",
"type": "Other"
},
{
"name": "Miles Lucas",
"type": "Other"
},
{
"name": "@Godisemo",
"type": "Other"
},
{
"name": "Florian Oswald",
"type": "Other"
},
{
"name": "Diego Javier Zea",
"type": "Other"
},
{
"name": "@WillRam",
"type": "Other"
},
{
"name": "Fedor Bezrukov",
"type": "Other"
},
{
"name": "Spencer Lyon",
"type": "Other"
},
{
"name": "Darwin Darakananda",
"type": "Other"
},
{
"name": "Lukas Hauertmann",
"type": "Other"
},
{
"name": "Huckleberry Febbo",
"type": "Other"
},
{
"name": "@H-M-H",
"type": "Other"
},
{
"name": "Josh Day",
"type": "Other"
},
{
"name": "@wfgra",
"type": "Other"
},
{
"name": "Sheehan Olver",
"type": "Other"
},
{
"name": "Jerry Ling",
"type": "Other"
},
{
"name": "Jks Liu",
"type": "Other"
},
{
"name": "Seth Axen",
"type": "Other"
},
{
"name": "@o01eg",
"type": "Other"
},
{
"name": "Sebastian Micluța-Câmpeanu",
"type": "Other"
},
{
"name": "Tim Holy",
"type": "Other"
},
{
"name": "Tony Kelman",
"type": "Other"
},
{
"name": "Antoine Levitt",
"type": "Other"
},
{
"name": "Iblis Lin",
"type": "Other"
},
{
"name": "Harry Scholes",
"type": "Other"
},
{
"name": "@djsegal",
"type": "Other"
},
{
"name": "Goran Nakerst",
"type": "Other"
},
{
"name": "Felix Hagemann",
"type": "Other"
},
{
"name": "Matthieu Gomez",
"type": "Other"
},
{
"name": "@biggsbiggsby",
"type": "Other"
},
{
"name": "Jonathan Anderson",
"type": "Other"
},
{
"name": "Michael Kraus",
"type": "Other"
},
{
"name": "Carlo Lucibello",
"type": "Other"
},
{
"name": "Robin Deits",
"type": "Other"
},
{
"name": "Misha Mkhasenko",
"type": "Other"
},
{
"name": "Benoît Legat",
"type": "Other"
},
{
"name": "Steven G. Johnson",
"type": "Other"
},
{
"name": "John Verzani",
"type": "Other"
},
{
"name": "Mattias Fält",
"type": "Other"
},
{
"name": "Rashika Karki",
"type": "Other"
},
{
"name": "Morten Piibeleht",
"type": "Other"
},
{
"name": "Filippo Vicentini",
"type": "Other"
},
{
"name": "David Anthoff",
"type": "Other"
},
{
"name": "Leon Wabeke",
"type": "Other"
},
{
"name": "Yusuke Kominami",
"type": "Other"
},
{
"name": "Oscar Dowson",
"type": "Other"
},
{
"name": "Max G",
"type": "Other"
},
{
"name": "Fabian Greimel",
"type": "Other"
},
{
"name": "Jérémy",
"type": "Other"
},
{
"name": "Pearl Li",
"type": "Other"
},
{
"name": "David P. Sanders",
"type": "Other"
},
{
"name": "Asbjørn Nilsen Riseth",
"type": "Other"
},
{
"name": "Jan Weidner",
"type": "Other"
},
{
"name": "@jakkor2",
"type": "Other"
},
{
"name": "Pablo Zubieta",
"type": "Other"
},
{
"name": "Hamza Yusuf Çakır",
"type": "Other"
},
{
"name": "John Rinehart",
"type": "Other"
},
{
"name": "Martin Biel",
"type": "Other"
},
{
"name": "Moritz Schauer",
"type": "Other"
},
{
"name": "Mosè Giodano",
"type": "Other"
},
{
"name": "@olegshtch",
"type": "Other"
},
{
"name": "Leon Shen",
"type": "Other"
},
{
"name": "Jeff Fessler",
"type": "Other"
},
{
"name": "@hustf",
"type": "Other"
},
{
"name": "Asim H Dar",
"type": "Other"
},
{
"name": "@8uurg",
"type": "Other"
},
{
"name": "Abel Siqueira",
"type": "Other"
},
{
"name": "Adrian Dawid",
"type": "Other"
},
{
"name": "Alberto Lusiani",
"type": "Other"
},
{
"name": "Balázs Mezei",
"type": "Other"
},
{
"name": "Ben Ide",
"type": "Other"
},
{
"name": "Benjamin Lungwitz",
"type": "Other"
},
{
"affiliation": "University of Graz",
"name": "Bernd Riederer",
"type": "Other",
"orcid": "0000-0001-8390-0087"
},
{
"name": "Christina Lee",
"type": "Other"
},
{
"name": "Christof Stocker",
"type": "Other"
},
{
"name": "Christoph Finkensiep",
"type": "Other"
},
{
"name": "@Cornelius-G",
"type": "Other"
},
{
"name": "Daniel Høegh",
"type": "Other"
},
{
"name": "Denny Biasiolli",
"type": "Other"
},
{
"name": "Dieter Castel",
"type": "Other"
},
{
"name": "Elliot Saba",
"type": "Other"
},
{
"name": "Fengyang Wang",
"type": "Other"
},
{
"name": "Fons van der Plas",
"type": "Other"
},
{
"name": "Fredrik Bagge Carlson",
"type": "Other"
},
{
"name": "Graham Smith",
"type": "Other"
},
{
"name": "Hayato Ikoma",
"type": "Other"
},
{
"name": "Hessam Mehr",
"type": "Other"
},
{
"name": "@InfiniteChai",
"type": "Other"
},
{
"name": "Jack Dunn",
"type": "Other"
},
{
"name": "Jeff Bezanson",
"type": "Other"
},
{
"name": "Jeff Eldredge",
"type": "Other"
},
{
"name": "Jinay Jain",
"type": "Other"
},
{
"name": "Johan Blåbäck",
"type": "Other"
},
{
"name": "@jmert",
"type": "Other"
},
{
"name": "Lakshya Khatri",
"type": "Other"
},
{
"name": "Lia Siegelmann",
"type": "Other"
},
{
"name": "@marekkukan-tw",
"type": "Other"
},
{
"affiliation": "ETH Zurich",
"name": "Mauro Werder",
"type": "Other",
"orcid": "0000-0003-0137-9377"
},
{
"name": "Maxim Grechkin",
"type": "Other"
},
{
"name": "Michael Cawte",
"type": "Other"
},
{
"name": "@milesfrain",
"type": "Other"
},
{
"name": "Nicholas Bauer",
"type": "Other"
},
{
"name": "Nicolau Leal Werneck",
"type": "Other"
},
{
"name": "@nilshg",
"type": "Other"
},
{
"name": "Oliver Evans",
"type": "Other"
},
{
"name": "Peter Gagarinov",
"type": "Other"
},
{
"name": "Páll Haraldsson",
"type": "Other"
},
{
"name": "Rik Huijzer",
"type": "Other"
},
{
"name": "Romain Franconville",
"type": "Other"
},
{
"name": "Ronan Pigott",
"type": "Other"
},
{
"name": "Roshan Shariff",
"type": "Other"
},
{
"name": "Scott Thomas",
"type": "Other"
},
{
"name": "Sebastian Rollén",
"type": "Other"
},
{
"name": "Seth Bromberger",
"type": "Other"
},
{
"name": "Siva Swaminathan",
"type": "Other"
},
{
"name": "Tim DuBois",
"type": "Other"
},
{
"name": "Travis DePrato",
"type": "Other"
},
{
"name": "Will Thompson",
"type": "Other"
},
{
"name": "Yakir Luc Gagnon",
"type": "Other"
},
{
"name": "Benjamin Chislett",
"type": "Other"
},
{
"name": "@hhaensel",
"type": "Other"
},
{
"name": "@improbable22",
"type": "Other"
},
{
"name": "Johannes Fleck",
"type": "Other"
},
{
"name": "Peter Czaban",
"type": "Other"
},
{
"name": "@innerlee",
"type": "Other"
},
{
"name": "Mats Cronqvist",
"type": "Other"
},
{
"name": "Shi Pengcheng",
"type": "Other"
},
{
"name": "@wg030",
"type": "Other"
},
{
"affiliation": "University of Cambridge",
"name": "Will Tebbutt",
"type": "Other"
},
{
"name": "@t-bltg",
"type": "Other"
},
{
"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"
},
{
"name": "Tom Gillam",
"type": "Other"
},
{
"name": "Steve Leung",
"type": "Other"
},
{
"name": "Xu Zhi-Yuan",
"type": "Other"
}
],
"upload_type": "software"
}

View File

@ -3,7 +3,7 @@
#### notes on release changes, ongoing development, and future planned work #### notes on release changes, ongoing development, and future planned work
## (current master) ## NOTE: this file is deprecated, see the [TagBot](https://github.com/marketplace/actions/julia-tagbot) auto-generated changelogs instead
## 0.28.3 ## 0.28.3
- support generalized array interface - support generalized array interface

View File

@ -1,12 +1,13 @@
name = "Plots" name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"] author = ["Tom Breloff (@tbreloff)"]
version = "1.11.2" version = "1.29.0"
[deps] [deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
@ -16,6 +17,7 @@ Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e" Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
@ -31,39 +33,53 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
UnicodeFun = "1cfade01-22cf-5700-b092-accc4b62d6e1"
Unzip = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d"
[compat] [compat]
Contour = "0.5" Contour = "0.5"
FFMPEG = "0.2, 0.3, 0.4" FFMPEG = "0.2 - 0.4"
FixedPointNumbers = "0.6, 0.7, 0.8" FixedPointNumbers = "0.6 - 0.8"
GR = "0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.57" GR = "0.64"
GeometryBasics = "0.2, 0.3.1" GeometryBasics = "0.2, 0.3.1, 0.4"
JSON = "0.21, 1" JSON = "0.21, 1"
Latexify = "0.14, 0.15" Latexify = "0.14 - 0.15"
Measures = "0.3" Measures = "0.3"
NaNMath = "0.3" NaNMath = "0.3, 1"
PlotThemes = "2" PGFPlotsX = "1"
PlotThemes = "2, 3"
PlotUtils = "1" PlotUtils = "1"
RecipesBase = "1" PlotlyBase = "0.7"
RecipesPipeline = "0.3" PlotlyJS = "0.18"
PyPlot = "2"
RecipesBase = "1.2"
RecipesPipeline = "0.5"
Reexport = "0.2, 1.0" Reexport = "0.2, 1.0"
Requires = "1" Requires = "1"
Scratch = "1" Scratch = "1"
Showoff = "0.3.1, 1.0" Showoff = "0.3.1, 1.0"
StatsBase = "0.32, 0.33" StatsBase = "0.32 - 0.33"
julia = "1.5" UnicodeFun = "0.4"
UnicodePlots = "2.10"
Unzip = "0.1"
julia = "1.6"
[extras] [extras]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
Gaston = "4b11ee91-296f-5714-9832-002c20994614"
Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44" Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d"
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925" PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925"
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
@ -74,4 +90,4 @@ UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
[targets] [targets]
test = ["Distributions", "FileIO", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"] test = ["Colors", "Distributions", "FileIO", "Gaston", "Gtk", "ImageMagick", "Images", "InspectDR", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PyPlot", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"]

View File

@ -10,13 +10,17 @@
[gitter-url]: https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge [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-img]: https://img.shields.io/badge/docs-stable-blue.svg
[docs-url]: http://docs.juliaplots.org/latest/ [docs-url]: https://docs.juliaplots.org/stable/
[![][gh-ci-img]][gh-ci-url] [![][gh-ci-img]][gh-ci-url]
[![][pkgeval-img]][pkgeval-url] [![][pkgeval-img]][pkgeval-url]
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots)
[![][docs-img]][docs-url] [![][docs-img]][docs-url]
[![Codecov](https://codecov.io/gh/JuliaPlots/Plots.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/Plots.jl) [![Codecov](https://codecov.io/gh/JuliaPlots/Plots.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/Plots.jl)
[![Plots Downloads](https://shields.io/endpoint?url=https://pkgs.genieframework.com/api/v1/badge/Plots)](https://pkgs.genieframework.com?packages=Plots)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4725317.svg)](https://doi.org/10.5281/zenodo.4725317)
This is the DOI for all Versions, please follow the link to get the DOI for a specific version.
#### Created by Tom Breloff (@tbreloff) #### Created by Tom Breloff (@tbreloff)

View File

@ -1,3 +1,6 @@
github_checks:
annotations: false
ignore: ignore:
- "src/backends/inspectdr.jl" - "src/backends/inspectdr.jl"
- "src/backends/orca.jl" - "src/backends/orca.jl"

View File

@ -66,102 +66,118 @@ end
function _precompile_() function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing 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{(:parent,), Tuple{Subplot{GRBackend}}},Type{Subplot},GRBackend})
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{PlotlyBackend}}},Type{Subplot},PlotlyBackend})
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}, Vector{Float64}},Int64}) Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}, Vector{Float64}},Int64})
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}, 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, 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(_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(areaplot)),Any,typeof(areaplot),Any,Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:foreground_color_grid, :grid, :gridalpha, :gridstyle, :gridlinewidth), Tuple{RGBA{Float64}, Bool, Float64, Symbol, Int64}},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{(: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), 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, :lims, :flip), Tuple{Bool, Tuple{Float64, Float64}, Bool}},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{(:grid, :minorgrid, :guide), Tuple{Bool, Bool, String}},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{(:grid, :minorgrid, :mirror, :guide), Tuple{Bool, Bool, Bool, String}},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,), 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{(: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{(: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, :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{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, Float64}}},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{(:lims,), Tuple{Tuple{Int64, Int64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:scale, :guide), Tuple{Symbol, String}},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{(:ticks,), Tuple{Nothing}},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(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{(: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(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)})
Base.precompile(Tuple{Core.kwftype(typeof(font)),NamedTuple{(:family, :pointsize, :valign, :halign, :rotation, :color), Tuple{String, Int64, Symbol, Symbol, Float64, RGBA{Float64}}},typeof(font)})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRange{Int64, Int64},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRange{Int64, Int64},Vector{Float64}})
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},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),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_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),Vector{Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(hline!)),Any,typeof(hline!),Any}) 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(gr_set_font)),NamedTuple{(:rotation, :color), Tuple{Int64, RGBA{Float64}}},typeof(gr_set_font),Font,Subplot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Plot{GRBackend},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Vector{Int64}})
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{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!),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{(: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, PlotText}}}},typeof(plot!)}) 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{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{GRBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Vector{Int64},Vector{Int64}})
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})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{GRBackend},Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{GRBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{PlotlyBackend},Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{PlotlyBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Function,Float64,Vararg{Any, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Function,Float64,Irrational{}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Plot{GRBackend},Function,Vararg{Any, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Plot{GRBackend},Function,Float64,Vararg{Any, N} where N})
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}},Vararg{Any, N} where N}) 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}},Vararg{Any, N} where N}) 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{(: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!),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{(: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},Vararg{Any, N} where N}) 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},Vararg{Any, N} where N}) 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, :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{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!),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{(: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!),Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:title,), Tuple{String}},typeof(plot!)}) 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},Vararg{Any, N} where N}) 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{(:xgrid,), Tuple{Tuple{Symbol, Symbol, Int64, Symbol, Float64}}},typeof(plot!),Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:yaxis,), Tuple{Tuple{String, Symbol}}},typeof(plot!)}) 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{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!),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{(: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{(: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{(:aspect_ratio, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{String},Vector{String},Vararg{Any, N} where N}) 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{(: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{(: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, :seriestype), Tuple{Tuple{Vector{Int64}, Vector{Int64}, Vector{Int64}}, Symbol}},typeof(plot),Vector{Int64},Vector{Int64},Vararg{Vector{Int64}, N} where N}) 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}},Vararg{Any, N} where N}) 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{(: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{(: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{(: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,Vararg{Float64, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:label, :legend, :seriestype), Tuple{String, Symbol, Symbol}},typeof(plot),Vector{Int64}})
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{(:label,), Tuple{Matrix{String}}},typeof(plot),Vector{AbstractVector{Float64}}})
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},Vararg{Plot{GRBackend}, N} where N}) 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},Vararg{Plot{PlotlyBackend}, N} where N}) 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{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, :link), Tuple{Int64, Symbol}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
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, :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, :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{GridLayout, Matrix{String}, Symbol, Matrix{AbsoluteLength}, AbsoluteLength, Int64}},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, :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},Vararg{Plot{GRBackend}, N} where N}) 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},Vararg{Plot{GRBackend}, N} where N}) 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},Vararg{Plot{PlotlyBackend}, N} where N}) 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},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},Vararg{Plot{PlotlyBackend}, 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},Vararg{Plot{GRBackend}, 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})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},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),Vector{Tuple{Int64, Real}}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot),Vector{Tuple{Int64, Real}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :lab, :ms), Tuple{Tuple{Matrix{Symbol}, Int64}, Matrix{String}, Int64}},typeof(plot),Vector{Vector{T} where T},Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :lab, :ms), Tuple{Tuple{Matrix{Symbol}, Int64}, Matrix{String}, Int64}},typeof(plot),Vector{Vector{T} where T},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :label, :legendtitle), Tuple{Tuple{Int64, Matrix{Symbol}}, Matrix{String}, String}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :label, :legendtitle), Tuple{Tuple{Int64, Matrix{Symbol}}, Matrix{String}, String}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :leg, :fill), Tuple{Int64, Bool, Tuple{Int64, Symbol}}},typeof(plot),Function,Function,Vararg{Any, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :leg, :fill), Tuple{Int64, Bool, Tuple{Int64, Symbol}}},typeof(plot),Function,Function,Int64,Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :marker, :bg, :fg, :xlim, :ylim, :leg), Tuple{Tuple{Int64, Symbol, Symbol}, Tuple{Shape, Int64, RGBA{Float64}}, Symbol, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Bool}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :marker, :bg, :fg, :xlim, :ylim, :leg), Tuple{Tuple{Int64, Symbol, Symbol}, Tuple{Shape{Float64, Float64}, Int64, RGBA{Float64}}, Symbol, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Bool}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line_z, :linewidth, :legend), Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int64, Bool}},typeof(plot),Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line_z, :linewidth, :legend), Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Int64, Bool}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:m, :lab, :bg, :xlim, :ylim, :seriestype), Tuple{Tuple{Int64, Symbol}, Matrix{String}, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:m, :markersize, :lab, :bg, :xlim, :ylim, :seriestype), Tuple{Matrix{Symbol}, Int64, Matrix{String}, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker,), Tuple{Bool}},typeof(plot),Vector{Union{Missing, Int64}}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker,), Tuple{Bool}},typeof(plot),Vector{Union{Missing, Int64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker_z, :color, :legend, :seriestype), Tuple{typeof(+), Symbol, Bool, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker_z, :color, :legend, :seriestype), Tuple{typeof(+), Symbol, Bool, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :markersize, :marker_z, :line_z, :linewidth), Tuple{Matrix{Symbol}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :markersize, :marker_z, :line_z, :linewidth), Tuple{Matrix{Symbol}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}}},typeof(plot),Matrix{Float64}})
@ -169,28 +185,31 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :show_empty_bins, :normed, :aspect_ratio, :seriestype), Tuple{Tuple{Int64, Int64}, Bool, Bool, Int64, Symbol}},typeof(plot),Vector{ComplexF64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :show_empty_bins, :normed, :aspect_ratio, :seriestype), Tuple{Tuple{Int64, Int64}, Bool, Bool, Int64, Symbol}},typeof(plot),Vector{ComplexF64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:proj, :m), Tuple{Symbol, Int64}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:proj, :m), Tuple{Symbol, Int64}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
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},Vararg{Any, N} where N}) 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},Vararg{Vector{Float64}, N} where N}) 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{(: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{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{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}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{typeof(sqrt)}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriescolor, :fillalpha), Tuple{Matrix{Symbol}, Matrix{Float64}}},typeof(plot),AreaPlot})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype, :markershape, :markersize, :color), Tuple{Matrix{Symbol}, Vector{Symbol}, Int64, Vector{Symbol}}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype, :markershape, :markersize, :color), Tuple{Matrix{Symbol}, Vector{Symbol}, Int64, Vector{Symbol}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{DateTime},UnitRange{Int64},Vararg{Any, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{DateTime},UnitRange{Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{OHLC}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{OHLC}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:st, :xlabel, :ylabel, :zlabel), Tuple{Symbol, String, String, String}},typeof(plot),Vector{Float64},Vector{Float64},Vararg{Vector{Float64}, N} where N}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:st, :xlabel, :ylabel, :zlabel), Tuple{Symbol, String, String, String}},typeof(plot),Vector{Float64},Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :l, :seriestype), Tuple{String, Float64, Symbol}},typeof(plot),Vector{String},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :l, :seriestype), Tuple{String, Float64, Symbol}},typeof(plot),Vector{String},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xflip, :yflip, :zflip, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xmirror, :ymirror, :zmirror, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{GRBackend},Plot{GRBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
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{(:w,), Tuple{Int64}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:w,), Tuple{Int64}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:xaxis, :background_color, :leg), Tuple{Tuple{String, Tuple{Int64, Int64}, StepRange{Int64, Int64}, Symbol}, RGB{Float64}, Bool}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:xaxis, :background_color, :leg), Tuple{Tuple{String, Tuple{Int64, Int64}, StepRange{Int64, Int64}, Symbol}, RGB{Float64}, Bool}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:yflip, :aspect_ratio), Tuple{Bool, Symbol}},typeof(plot),Vector{Float64},Vector{Int64},Vararg{Any, N} where N}) 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(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},Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(portfoliocomposition)),Any,typeof(portfoliocomposition),Any,Vararg{Any, N} where N}) 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,Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(scatter!)),Any,typeof(scatter!),Any}) 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{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{GridLayout},Int64,Vararg{Int64, N} where N})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{OHLC}}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{OHLC}})
@ -201,12 +220,14 @@ function _precompile_()
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:bins2d}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:bins2d}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:histogram2d}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:histogram2d}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hline}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:lens}},AbstractPlot}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:lens}},AbstractPlot})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:pie}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:pie}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:quiver}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:quiver}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:steppre}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:steppre}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:sticks}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:sticks}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vline}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:xerror}},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:xerror}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{ComplexF64}}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{ComplexF64}})
Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{GRBackend},DefaultsDict}) Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{GRBackend},DefaultsDict})
@ -214,23 +235,23 @@ function _precompile_()
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{GRBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}}) Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{GRBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{PlotlyBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}}) Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{PlotlyBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_attributes!),Plot{GRBackend},DefaultsDict}) Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_attributes!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{GRBackend},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{PlotlyBackend},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_userrecipe!),Plot{GRBackend},Vector{Dict{Symbol, Any}},Dict{Symbol, Any}}) 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.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.unzip),Vector{GeometryBasics.Point2{Float64}}})
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(_bin_centers),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}})
Base.precompile(Tuple{typeof(_bin_centers),Vector{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{Int64},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Nothing},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{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{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}},String})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{Symbol},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),UnitRange{Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),StepRange{Int64, Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},StepRange{Int64, Int64}}) Base.precompile(Tuple{typeof(_cycle),Vector{Float64},StepRange{Int64, Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},UnitRange{Int64}}) Base.precompile(Tuple{typeof(_cycle),Vector{Int64},StepRange{Int64, Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},Vector{Int64}}) Base.precompile(Tuple{typeof(_cycle),Vector{Int64},UnitRange{Int64}})
Base.precompile(Tuple{typeof(_do_plot_show),Plot{GRBackend},Bool}) Base.precompile(Tuple{typeof(_do_plot_show),Plot{GRBackend},Bool})
Base.precompile(Tuple{typeof(_do_plot_show),Plot{PlotlyBackend},Bool}) Base.precompile(Tuple{typeof(_do_plot_show),Plot{PlotlyBackend},Bool})
Base.precompile(Tuple{typeof(_heatmap_edges),Vector{Float64},Bool,Bool}) Base.precompile(Tuple{typeof(_heatmap_edges),Vector{Float64},Bool,Bool})
@ -242,62 +263,71 @@ function _precompile_()
Base.precompile(Tuple{typeof(_update_subplot_args),Plot{PlotlyBackend},Subplot{PlotlyBackend},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_periphery),Subplot{GRBackend},Vector{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(_update_subplot_periphery),Subplot{PlotlyBackend},Vector{Any}})
Base.precompile(Tuple{typeof(axis_limits),Subplot{GRBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(axis_limits),Subplot{PlotlyBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(backend),PlotlyBackend}) Base.precompile(Tuple{typeof(backend),PlotlyBackend})
Base.precompile(Tuple{typeof(bbox),AbsoluteLength,AbsoluteLength,AbsoluteLength,AbsoluteLength}) Base.precompile(Tuple{typeof(bbox),AbsoluteLength,AbsoluteLength,AbsoluteLength,AbsoluteLength})
Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64}) Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64})
Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64}) Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}})
Base.precompile(Tuple{typeof(contour),Any,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(convert_to_polar),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Int64, Float64}}) 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(default),Symbol,Bool})
Base.precompile(Tuple{typeof(default),Symbol,String})
Base.precompile(Tuple{typeof(discrete_value!),Axis,Vector{String}})
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},Vararg{Vector{Float64}, N} where N})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64}}) 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(error_zipit),Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}})
Base.precompile(Tuple{typeof(expand_extrema!),Axis,Tuple{Float64, Float64}}) Base.precompile(Tuple{typeof(fakedata),Int64,Int64})
Base.precompile(Tuple{typeof(font),String,Vararg{Any, N} where N}) 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{Float64}, Vector{String}}})
Base.precompile(Tuple{typeof(get_minor_ticks),Subplot{GRBackend},Axis,Tuple{Vector{Int64}, 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{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),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{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}) Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Float64},Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Int64},Vararg{Any, N} where N}) Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Int64},Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(get_ticks),UnitRange{Int64},Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any, N} where N}) Base.precompile(Tuple{typeof(get_ticks),UnitRange{Int64},Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(get_xy),OHLC{Float64},Int64,Float64})
Base.precompile(Tuple{typeof(get_xy),Vector{OHLC}}) Base.precompile(Tuple{typeof(get_xy),Vector{OHLC}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), NTuple{9, Float64}},Vector{Float64}}) Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), NTuple{9, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), Tuple{Int64, Float64, Float64, Float64, Int64, Float64, Float64, Float64, Float64}},Vector{Float64}}) Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), Tuple{Int64, Int64, Int64, Float64, Int64, Float64, Float64, Float64, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_display),Subplot{GRBackend},AbsoluteLength,AbsoluteLength,Vector{Float64}}) Base.precompile(Tuple{typeof(gr_display),Subplot{GRBackend},AbsoluteLength,AbsoluteLength,Vector{Float64}})
Base.precompile(Tuple{typeof(gr_draw_colorbar),GRColorbar,Subplot{GRBackend},Tuple{Float64, Float64},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_draw_contour),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Matrix{Float64},Tuple{Float64, Float64}}) Base.precompile(Tuple{typeof(gr_draw_contour),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_heatmap),Series,Vector{Float64},Vector{Float64},Matrix{Float64},Tuple{Float64, Float64}}) Base.precompile(Tuple{typeof(gr_draw_heatmap),Series,Vector{Float64},Vector{Float64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Float64,Float64,Tuple{Float64, Float64},Int64,Float64,Float64,Symbol})
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,Float64,Float64,Tuple{Float64, Float64},Int64,Int64,Int64,Symbol})
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,Float64,Tuple{Float64, Float64},Int64,Int64,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_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},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,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}}) Base.precompile(Tuple{typeof(gr_draw_segments),Series,StepRange{Int64, Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,UnitRange{Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,UnitRange{Int64},Vector{Float64},Vector{Int64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Float64},Vector{Float64},Int64,Tuple{Float64, Float64}}) Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Float64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_shapes),Series,Tuple{Float64, Float64}})
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},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_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{Float64}, 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{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_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_polaraxes),Int64,Float64,Subplot{GRBackend}})
Base.precompile(Tuple{typeof(gr_polyline),Vector{Float64},Vector{Float64},Function}) 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_set_gradient),PlotUtils.ContinuousColorGradient})
Base.precompile(Tuple{typeof(gr_text),Float64,Float64,String})
Base.precompile(Tuple{typeof(gr_text_size),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), 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, Float64, Float64, Float64, Int64, Float64, Float64, Float64, 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}}) Base.precompile(Tuple{typeof(gr_viewport_from_bbox),Subplot{GRBackend},BoundingBox{Tuple{AbsoluteLength, AbsoluteLength}, Tuple{AbsoluteLength, AbsoluteLength}},AbsoluteLength,AbsoluteLength,Vector{Float64}})
Base.precompile(Tuple{typeof(heatmap_edges),Base.OneTo{Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol,Tuple{Int64, Int64},Bool})
Base.precompile(Tuple{typeof(heatmap_edges),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol}) Base.precompile(Tuple{typeof(heatmap_edges),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),UnitRange{Int64},Symbol}) Base.precompile(Tuple{typeof(heatmap_edges),UnitRange{Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),Vector{Float64},Symbol,UnitRange{Int64},Symbol,Tuple{Int64, Int64},Bool})
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(heatmap_edges),Vector{Float64},Symbol})
Base.precompile(Tuple{typeof(ignorenan_extrema),Matrix{Float64}})
Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}}) Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}})
Base.precompile(Tuple{typeof(layout_args),Int64}) 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(make_fillrange_side),UnitRange{Int64},LinRange{Float64}}) Base.precompile(Tuple{typeof(make_fillrange_side),UnitRange{Int64},LinRange{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,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{Float64, Float64},Symbol,Symbol})
@ -305,85 +335,117 @@ function _precompile_()
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Int64, Int64},Symbol,Symbol}) Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Int64, Int64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),StepRange{Int64, Int64},Tuple{Int64, Int64},Symbol,Symbol}) Base.precompile(Tuple{typeof(optimal_ticks_and_labels),StepRange{Int64, Int64},Tuple{Int64, Int64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),UnitRange{Int64},Tuple{Float64, Float64},Symbol,Symbol}) Base.precompile(Tuple{typeof(optimal_ticks_and_labels),UnitRange{Int64},Tuple{Float64, Float64},Symbol,Symbol})
Base.precompile(Tuple{typeof(plot),Any,Any,Vararg{Any, N} where N}) Base.precompile(Tuple{typeof(partialcircle),Int64,Float64,Int64})
Base.precompile(Tuple{typeof(plot),Any}) Base.precompile(Tuple{typeof(plot!),Any})
Base.precompile(Tuple{typeof(processGridArg!),DefaultsDict,Bool,Symbol}) Base.precompile(Tuple{typeof(plot!),Plot,Plot,Plot,Vararg{Plot, N} where N})
Base.precompile(Tuple{typeof(plot),Any,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{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}, N} where N})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{typeof(processGridArg!),Dict{Symbol, Any},Symbol,Symbol}) Base.precompile(Tuple{typeof(processGridArg!),Dict{Symbol, Any},Symbol,Symbol})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Float64})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Int64})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Matrix{Symbol}}) Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Matrix{Symbol}})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Symbol}) Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Matrix{Symbol}}) 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},RGBA{Float64}})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Shape}) 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(processMarkerArg),Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(process_annotation),Subplot{GRBackend},Int64,Float64,PlotText}) 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}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,PlotText}) Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,PlotText})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Int64, Symbol, Symbol}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Symbol, Int64, String}})
Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},StepRange{Int64, Int64},Symbol}) Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},StepRange{Int64, Int64},Symbol})
Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},Symbol,Symbol}) 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!),Plot{GRBackend},Float64,Vector{Float64}})
Base.precompile(Tuple{typeof(quiver_using_hack),DefaultsDict}) Base.precompile(Tuple{typeof(push!),Segments{Tuple{Float64, Float64, Float64}},Tuple{Int64, Int64, Float64},Tuple{Int64, Int64, Float64}})
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),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{Bool},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{PlotUtils.ContinuousColorGradient},Int64}) Base.precompile(Tuple{typeof(slice_arg),Matrix{Int64},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{RGBA{Float64}},Int64}) Base.precompile(Tuple{typeof(slice_arg),Matrix{RGBA{Float64}},Int64})
Base.precompile(Tuple{typeof(slice_arg),Matrix{String},Int64})
Base.precompile(Tuple{typeof(spy),Any}) 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(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(stroke),Int64,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(text),String,Int64,Symbol,Vararg{Symbol, N} where N})
Base.precompile(Tuple{typeof(text),String,Symbol,Int64,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(text),String,Symbol})
Base.precompile(Tuple{typeof(title!),AbstractString}) Base.precompile(Tuple{typeof(title!),AbstractString})
Base.precompile(Tuple{typeof(unzip),Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{typeof(vline!),Any}) 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(xgrid!),Plot{GRBackend},Symbol,Vararg{Any, N} where N})
Base.precompile(Tuple{typeof(xlims),Subplot{PlotlyBackend}}) Base.precompile(Tuple{typeof(xlims),Subplot{PlotlyBackend}})
Base.precompile(Tuple{typeof(yaxis!),Any,Any}) isdefined(Plots, Symbol("#166#167")) && Base.precompile(Tuple{getfield(Plots, Symbol("#166#167")),Any})
let fbody = try __lookup_kwbody__(which(plot!, (Any,))) catch missing end isdefined(Plots, Symbol("#2#6")) && Base.precompile(Tuple{getfield(Plots, Symbol("#2#6")),UnitRange{Int64}})
if !ismissing(fbody) isdefined(Plots, Symbol("#295#331")) && Base.precompile(Tuple{getfield(Plots, Symbol("#295#331"))})
precompile(fbody, (Any,typeof(plot!),Any,)) isdefined(Plots, Symbol("#316#352")) && Base.precompile(Tuple{getfield(Plots, Symbol("#316#352"))})
end isdefined(Plots, Symbol("#add_major_or_minor_segments#100")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#100")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
end isdefined(Plots, Symbol("#add_major_or_minor_segments#101")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#101")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
let fbody = try __lookup_kwbody__(which(plot!, (Any,Vararg{Any, N} where N,))) catch missing end let fbody = try __lookup_kwbody__(which(font, (Font,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody) if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Any,Vararg{Any, N} where N,)) precompile(fbody, (Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(font),Font,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot),Any,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot),Any,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Plot,Plot,Vararg{Plot, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot),Plot,Plot,Vararg{Plot, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(text, (String,Int64,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(text),String,Int64,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(text, (String,Symbol,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(text),String,Symbol,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(title!, (AbstractString,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(title!),AbstractString,))
end
end
let fbody = try __lookup_kwbody__(which(yaxis!, (Any,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(yaxis!),Any,Vararg{Any, N} where N,))
end
end end
end
let fbody = try __lookup_kwbody__(which(gr_polyline, (Vector{Float64},Vector{Float64},typeof(GR.fillarea),))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Symbol,Symbol,typeof(gr_polyline),Vector{Float64},Vector{Float64},typeof(GR.fillarea),))
end
end
let fbody = try __lookup_kwbody__(which(gr_set_font, (Font,Subplot{GRBackend},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Symbol,Symbol,RGBA{Float64},Float64,typeof(gr_set_font),Font,Subplot{GRBackend},))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Any,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Any,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Any,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Any,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Plot,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Plot,Plot,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,Plot,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Plot,Plot,Plot,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,Plot,Vararg{Plot, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Plot,Plot,Plot,Vararg{Plot, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot),Any,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot),Any,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(scatter, (Any,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(scatter),Any,Vararg{Any, N} where N,))
end
end
let fbody = try __lookup_kwbody__(which(title!, (AbstractString,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Any,typeof(title!),AbstractString,))
end
end
end end

View File

@ -0,0 +1,487 @@
# Use
# @warnpcfail precompile(args...)
# if you want to be warned when a precompile directive fails
macro warnpcfail(ex::Expr)
modl = __module__
file = __source__.file === nothing ? "?" : String(__source__.file)
line = __source__.line
quote
$(esc(ex)) || @warn """precompile directive
$($(Expr(:quote, ex)))
failed. Please report an issue in $($modl) (after checking for duplicates) or remove this directive.""" _file=$file _line=$line
end
end
const __bodyfunction__ = Dict{Method,Any}()
# Find keyword "body functions" (the function that contains the body
# as written by the developer, called after all missing keyword-arguments
# have been assigned values), in a manner that doesn't depend on
# gensymmed names.
# `mnokw` is the method that gets called when you invoke it without
# supplying any keywords.
function __lookup_kwbody__(mnokw::Method)
function getsym(arg)
isa(arg, Symbol) && return arg
@assert isa(arg, GlobalRef)
return arg.name
end
f = get(__bodyfunction__, mnokw, nothing)
if f === nothing
fmod = mnokw.module
# The lowered code for `mnokw` should look like
# %1 = mkw(kwvalues..., #self#, args...)
# return %1
# where `mkw` is the name of the "active" keyword body-function.
ast = Base.uncompressed_ast(mnokw)
if isa(ast, Core.CodeInfo) && length(ast.code) >= 2
callexpr = ast.code[end-1]
if isa(callexpr, Expr) && callexpr.head == :call
fsym = callexpr.args[1]
if isa(fsym, Symbol)
f = getfield(fmod, fsym)
elseif isa(fsym, GlobalRef)
if fsym.mod === Core && fsym.name === :_apply
f = getfield(mnokw.module, getsym(callexpr.args[2]))
elseif fsym.mod === Core && fsym.name === :_apply_iterate
f = getfield(mnokw.module, getsym(callexpr.args[3]))
else
f = getfield(fsym.mod, fsym.name)
end
else
f = missing
end
else
f = missing
end
else
f = missing
end
__bodyfunction__[mnokw] = f
end
return f
end
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
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})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:parent,), Tuple{Subplot{PlotlyBackend}}},Type{Subplot},PlotlyBackend})
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}, Vector{Float64}},Int64})
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(areaplot)),Any,typeof(areaplot),Any,Vararg{Any}})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:flip,), Tuple{Bool}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:foreground_color_grid, :grid, :gridalpha, :gridstyle, :gridlinewidth), Tuple{RGBA{Float64}, Bool, Float64, Symbol, Int64}},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{(: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)})
Base.precompile(Tuple{Core.kwftype(typeof(font)),NamedTuple{(:family, :pointsize, :valign, :halign, :rotation, :color), Tuple{String, Int64, Symbol, Symbol, Float64, RGBA{Float64}}},typeof(font)})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRange{Int64, Int64},Vector{Float64}})
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(gr_set_font)),NamedTuple{(:rotation, :color), Tuple{Int64, RGBA{Float64}}},typeof(gr_set_font),Font,Subplot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(lens!)),Any,typeof(lens!),Any,Vararg{Any}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Plot{GRBackend},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Vector{Int64}})
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{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{GRBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Vector{Int64},Vector{Int64}})
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}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{GRBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{PlotlyBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Function,Float64,Irrational{}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Plot{GRBackend},Function,Float64,Vararg{Any}})
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}, Int64},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}, Int64},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}, Int64},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!),Plot{PlotlyBackend},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}})
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{GRBackend}})
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}, Int64}, 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}})
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}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},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, :legend, :seriestype), Tuple{String, Symbol, Symbol}},typeof(plot),Vector{Int64}})
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{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{Matrix{Any}, AbsoluteLength}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
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{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{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}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot),Vector{Tuple{Int64, Real}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :lab, :ms), Tuple{Tuple{Matrix{Symbol}, Int64}, Matrix{String}, Int64}},typeof(plot),Vector{Vector},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :label, :legendtitle), Tuple{Tuple{Int64, Matrix{Symbol}}, Matrix{String}, String}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :leg, :fill), Tuple{Int64, Bool, Tuple{Int64, Symbol}}},typeof(plot),Function,Function,Int64,Vararg{Any}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :marker, :bg, :fg, :xlim, :ylim, :leg), Tuple{Tuple{Int64, Symbol, Symbol}, Tuple{Shape{Float64, Float64}, Int64, RGBA{Float64}}, Symbol, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Bool}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line_z, :linewidth, :legend), Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, Int64, Bool}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:m, :markersize, :lab, :bg, :xlim, :ylim, :seriestype), Tuple{Matrix{Symbol}, Int64, Matrix{String}, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker,), Tuple{Bool}},typeof(plot),Vector{Union{Missing, Int64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker_z, :color, :legend, :seriestype), Tuple{typeof(+), Symbol, Bool, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :markersize, :marker_z, :line_z, :linewidth), Tuple{Matrix{Symbol}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :seriestype, :label), Tuple{Symbol, Symbol, String}},typeof(plot),UnitRange{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :show_empty_bins, :normed, :aspect_ratio, :seriestype), Tuple{Tuple{Int64, Int64}, Bool, Bool, Int64, Symbol}},typeof(plot),Vector{ComplexF64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:proj, :m), Tuple{Symbol, Int64}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:projection, :seriestype), Tuple{Symbol, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},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}, Int64}}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{typeof(sqrt)}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriescolor, :fillalpha), Tuple{Matrix{Symbol}, Matrix{Float64}}},typeof(plot),AreaPlot})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype, :markershape, :markersize, :color), Tuple{Matrix{Symbol}, Vector{Symbol}, Int64, Vector{Symbol}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{DateTime},UnitRange{Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{OHLC}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:st, :xlabel, :ylabel, :zlabel), Tuple{Symbol, String, String, String}},typeof(plot),Vector{Float64},Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :l, :seriestype), Tuple{String, Float64, Symbol}},typeof(plot),Vector{String},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xflip, :yflip, :zflip, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xmirror, :ymirror, :zmirror, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:w,), Tuple{Int64}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:xaxis, :background_color, :leg), Tuple{Tuple{String, Tuple{Int64, Int64}, StepRange{Int64, Int64}, Symbol}, RGB{Float64}, Bool}},typeof(plot),Matrix{Float64}})
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}})
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{Core.kwftype(typeof(yaxis!)),Any,typeof(yaxis!),Any,Any})
Base.precompile(Tuple{Type{GridLayout},Int64,Vararg{Int64}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{<:GeometryBasics.Point}})
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})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:histogram2d}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:lens}},AbstractPlot})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:pie}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:quiver}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:spy}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:steppre}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:sticks}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:xerror}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{ComplexF64}})
Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{PlotlyBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{GRBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{PlotlyBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_attributes!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_axis_args!),Plot{GRBackend},Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_axis_args!),Plot{PlotlyBackend},Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{GRBackend},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{PlotlyBackend},Vector{Dict{Symbol, Any}}})
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.unzip),Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{typeof(_bin_centers),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}})
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}, Int64}},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),UnitRange{Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},StepRange{Int64, Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},UnitRange{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Int64},StepRange{Int64, Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Int64},UnitRange{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})
Base.precompile(Tuple{typeof(_plot!),Plot,Any,Any})
Base.precompile(Tuple{typeof(_preprocess_barlike),DefaultsDict,Base.OneTo{Int64},Vector{Float64}})
Base.precompile(Tuple{typeof(_preprocess_binlike),DefaultsDict,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{typeof(_replace_markershape),Vector{Symbol}})
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_periphery),Subplot{GRBackend},Vector{Any}})
Base.precompile(Tuple{typeof(_update_subplot_periphery),Subplot{PlotlyBackend},Vector{Any}})
Base.precompile(Tuple{typeof(annotate!),AbstractVector{<:Tuple}})
Base.precompile(Tuple{typeof(axis_limits),Subplot{GRBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(axis_limits),Subplot{PlotlyBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(backend),PlotlyBackend})
Base.precompile(Tuple{typeof(bbox),AbsoluteLength,AbsoluteLength,AbsoluteLength,AbsoluteLength})
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}, Int64},Vector{Float64},Tuple{Int64, Float64}})
Base.precompile(Tuple{typeof(discrete_value!),Axis,Vector{Union{Missing, Float64}}})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64},Vararg{Vector{Float64}}})
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),TaskLocalRNG,Int64,Vararg{Int64}})
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}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Int64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),UnitRange{Int64},Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_xy),Vector{OHLC}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), NTuple{9, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), Tuple{Int64, Int64, Int64, Float64, Int64, Float64, Float64, Float64, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_display),Subplot{GRBackend},AbsoluteLength,AbsoluteLength,Vector{Float64}})
Base.precompile(Tuple{typeof(gr_draw_contour),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_heatmap),Series,Vector{Float64},Vector{Float64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Float64,Float64,Tuple{Float64, Float64},Int64,Float64,Float64,Symbol})
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,Float64,Float64,Tuple{Float64, Float64},Int64,Int64,Int64,Symbol})
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,Float64,Tuple{Float64, Float64},Int64,Int64,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},Int64,Int64})
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}, Int64},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_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,Base.OneTo{Int64},Vector{Float64},Nothing,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64},Nothing,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,StepRange{Int64, Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,UnitRange{Int64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,UnitRange{Int64},Vector{Float64},Nothing,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,UnitRange{Int64},Vector{Float64},Vector{Int64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Float64},Vector{Float64},Int64,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Float64},Vector{Float64},Nothing,Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Int64},Vector{Int64},Nothing,Tuple{Float64, Float64}})
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_text_size),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}})
Base.precompile(Tuple{typeof(heatmap_edges),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),UnitRange{Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),Vector{Float64},Symbol})
Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}})
Base.precompile(Tuple{typeof(layout_args),Matrix{Any}})
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(make_fillrange_side),UnitRange{Int64},LinRange{Float64, Int64}})
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})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Int64, Int64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),StepRange{Int64, Int64},Tuple{Int64, Int64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),UnitRange{Int64},Tuple{Float64, Float64},Symbol,Symbol})
Base.precompile(Tuple{typeof(partialcircle),Float64,Float64,Int64})
Base.precompile(Tuple{typeof(partialcircle),Int64,Float64,Int64})
Base.precompile(Tuple{typeof(plot!),Any})
Base.precompile(Tuple{typeof(plot!),Plot,Plot,Plot,Vararg{Plot}})
Base.precompile(Tuple{typeof(plot),Any,Any})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{typeof(processGridArg!),Dict{Symbol, Any},Symbol,Symbol})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Matrix{Symbol}})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Symbol})
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Bool})
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(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}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,PlotText})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Int64, Symbol, Symbol}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Symbol, Int64, String}})
Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},StepRange{Int64, Int64},Symbol})
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(quiver_using_arrows),DefaultsDict})
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}})
Base.precompile(Tuple{typeof(text),String,Symbol})
Base.precompile(Tuple{typeof(title!),AbstractString})
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}})
Base.precompile(Tuple{typeof(xgrid!),Plot{PlotlyBackend},Symbol,Vararg{Any}})
Base.precompile(Tuple{typeof(xlims),Subplot{PlotlyBackend}})
isdefined(Plots, Symbol("#168#169")) && Base.precompile(Tuple{getfield(Plots, Symbol("#168#169")),Any})
isdefined(Plots, Symbol("#170#171")) && Base.precompile(Tuple{getfield(Plots, Symbol("#170#171")),Any})
isdefined(Plots, Symbol("#2#6")) && Base.precompile(Tuple{getfield(Plots, Symbol("#2#6")),UnitRange{Int64}})
isdefined(Plots, Symbol("#301#337")) && Base.precompile(Tuple{getfield(Plots, Symbol("#301#337"))})
isdefined(Plots, Symbol("#322#358")) && Base.precompile(Tuple{getfield(Plots, Symbol("#322#358"))})
isdefined(Plots, Symbol("#add_major_or_minor_segments#102")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#102")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#add_major_or_minor_segments#103")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#103")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
let fbody = try __lookup_kwbody__(which(annotate!, (AbstractVector{<:Tuple},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(annotate!),AbstractVector{<:Tuple},))
end
end
let fbody = try __lookup_kwbody__(which(font, (Font,Vararg{Any},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(font),Font,Vararg{Any},))
end
end
let fbody = try __lookup_kwbody__(which(gr_polyline, (Vector{Float64},Vector{Float64},typeof(GR.fillarea),))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Symbol,Symbol,typeof(gr_polyline),Vector{Float64},Vector{Float64},typeof(GR.fillarea),))
end
end
let fbody = try __lookup_kwbody__(which(gr_set_font, (Font,Subplot{GRBackend},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Symbol,Symbol,RGBA{Float64},Float64,typeof(gr_set_font),Font,Subplot{GRBackend},))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Any,Vararg{Any},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot!),Any,Vararg{Any},))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot!),Plot,Plot,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,Plot,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot!),Plot,Plot,Plot,))
end
end
let fbody = try __lookup_kwbody__(which(plot!, (Plot,Plot,Plot,Vararg{Plot},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot!),Plot,Plot,Plot,Vararg{Plot},))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot),Any,))
end
end
let fbody = try __lookup_kwbody__(which(plot, (Any,Vararg{Any},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(plot),Any,Vararg{Any},))
end
end
let fbody = try __lookup_kwbody__(which(title!, (AbstractString,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(title!),AbstractString,))
end
end
let fbody = try __lookup_kwbody__(which(yaxis!, (Any,Vararg{Any},))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}},typeof(yaxis!),Any,Vararg{Any},))
end
end
end

View File

@ -0,0 +1,282 @@
# Use
# @warnpcfail precompile(args...)
# if you want to be warned when a precompile directive fails
macro warnpcfail(ex::Expr)
modl = __module__
file = __source__.file === nothing ? "?" : String(__source__.file)
line = __source__.line
quote
$(esc(ex)) || @warn """precompile directive
$($(Expr(:quote, ex)))
failed. Please report an issue in $($modl) (after checking for duplicates) or remove this directive.""" _file=$file _line=$line
end
end
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
Base.precompile(Tuple{Core.kwftype(typeof(_make_hist)),NamedTuple{(:normed, :weights), Tuple{Bool, Nothing}},typeof(_make_hist),Tuple{Vector{Float64}, Vector{Float64}},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{(:formatter,), Tuple{typeof(datetimeformatter)}},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{(:lims,), Tuple{Tuple{Int64, Float64}}},typeof(attr!),Axis})
Base.precompile(Tuple{Core.kwftype(typeof(attr!)),NamedTuple{(:ticks,), Tuple{Nothing}},typeof(attr!),Axis})
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(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),StepRange{Int64, Int64},Vector{Float64}})
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(gr_set_font)),NamedTuple{(:rotation, :color), Tuple{Int64, RGBA{Float64}}},typeof(gr_set_font),Font,Subplot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:alpha, :label, :seriestype), Tuple{Float64, String, Symbol}},typeof(plot!),Vector{Int64}})
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{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{GRBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{PlotlyBackend},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Vector{Int64},Vector{Int64}})
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}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:legend,), Tuple{Symbol}},typeof(plot!),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend},Vararg{Plot{PlotlyBackend}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{GRBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:line, :seriestype), Tuple{Tuple{Int64, Symbol, Float64, Matrix{Symbol}}, Symbol}},typeof(plot!),Plot{PlotlyBackend},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Function,Float64,Irrational{}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:lw, :color), Tuple{Int64, Symbol}},typeof(plot!),Plot{GRBackend},Function,Float64,Vararg{Any}})
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}, Int64},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}, Int64},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}, Int64},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{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}})
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{(: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}, Int64}, 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}})
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}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},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, :legend, :seriestype), Tuple{String, Symbol, Symbol}},typeof(plot),Vector{Int64}})
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{(: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, :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{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{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{Symbol}},typeof(plot),Vector{Tuple{Int64, Real}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :lab, :ms), Tuple{Tuple{Matrix{Symbol}, Int64}, Matrix{String}, Int64}},typeof(plot),Vector{Vector},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :label, :legendtitle), Tuple{Tuple{Int64, Matrix{Symbol}}, Matrix{String}, String}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :leg, :fill), Tuple{Int64, Bool, Tuple{Int64, Symbol}}},typeof(plot),Function,Function,Int64,Vararg{Any}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line, :marker, :bg, :fg, :xlim, :ylim, :leg), Tuple{Tuple{Int64, Symbol, Symbol}, Tuple{Shape{Float64, Float64}, Int64, RGBA{Float64}}, Symbol, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Bool}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:line_z, :linewidth, :legend), Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, Int64, Bool}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:m, :markersize, :lab, :bg, :xlim, :ylim, :seriestype), Tuple{Matrix{Symbol}, Int64, Matrix{String}, Symbol, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker,), Tuple{Bool}},typeof(plot),Vector{Union{Missing, Int64}}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:marker_z, :color, :legend, :seriestype), Tuple{typeof(+), Symbol, Bool, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :markersize, :marker_z, :line_z, :linewidth), Tuple{Matrix{Symbol}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}, Matrix{Int64}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:markershape, :seriestype, :label), Tuple{Symbol, Symbol, String}},typeof(plot),UnitRange{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :seriestype), Tuple{Int64, Symbol}},typeof(plot),Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:nbins, :show_empty_bins, :normed, :aspect_ratio, :seriestype), Tuple{Tuple{Int64, Int64}, Bool, Bool, Int64, Symbol}},typeof(plot),Vector{ComplexF64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:proj, :m), Tuple{Symbol, Int64}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:projection, :seriestype), Tuple{Symbol, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},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{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:ribbon,), Tuple{typeof(sqrt)}},typeof(plot),UnitRange{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype, :markershape, :markersize, :color), Tuple{Matrix{Symbol}, Vector{Symbol}, Int64, Vector{Symbol}}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{DateTime},UnitRange{Int64},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:seriestype,), Tuple{Symbol}},typeof(plot),Vector{OHLC}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:st, :xlabel, :ylabel, :zlabel), Tuple{Symbol, String, String, String}},typeof(plot),Vector{Float64},Vector{Float64},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :l, :seriestype), Tuple{String, Float64, Symbol}},typeof(plot),Vector{String},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xflip, :yflip, :zflip, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :xmirror, :ymirror, :zmirror, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, Bool, Bool, Bool, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title, :zlabel, :grid, :ylabel, :minorgrid, :xlabel, :seriestype), Tuple{String, String, Bool, String, Bool, String, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Function})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:title,), Tuple{Matrix{String}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:w,), Tuple{Int64}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:xaxis, :background_color, :leg), Tuple{Tuple{String, Tuple{Int64, Int64}, StepRange{Int64, Int64}, Symbol}, RGB{Float64}, Bool}},typeof(plot),Matrix{Float64}})
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}})
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{Core.kwftype(typeof(yaxis!)),Any,typeof(yaxis!),Any,Any})
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{: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})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:histogram2d}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:hspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:lens}},AbstractPlot})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:pie}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:quiver}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:sticks}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vline}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:vspan}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{Val{:xerror}},Any,Any,Any})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{ComplexF64}})
Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.add_series!),Plot{PlotlyBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{GRBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.plot_setup!),Plot{PlotlyBackend},Dict{Symbol, Any},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.preprocess_attributes!),Plot{GRBackend},DefaultsDict})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{GRBackend},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_sliced_series_attributes!),Plot{PlotlyBackend},Vector{Dict{Symbol, Any}}})
Base.precompile(Tuple{typeof(RecipesPipeline.process_userrecipe!),Plot{GRBackend},Vector{Dict{Symbol, Any}},Dict{Symbol, Any}})
Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Vector{GeometryBasics.Point2{Float64}}})
Base.precompile(Tuple{typeof(_bin_centers),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}})
Base.precompile(Tuple{typeof(_cbar_unique),Vector{PlotUtils.ContinuousColorGradient},String})
Base.precompile(Tuple{typeof(_cycle),StepRange{Int64, Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},StepRange{Int64, 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(_preprocess_barlike),DefaultsDict,Base.OneTo{Int64},Vector{Float64}})
Base.precompile(Tuple{typeof(_preprocess_binlike),DefaultsDict,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Vector{Float64}})
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_periphery),Subplot{GRBackend},Vector{Any}})
Base.precompile(Tuple{typeof(_update_subplot_periphery),Subplot{PlotlyBackend},Vector{Any}})
Base.precompile(Tuple{typeof(annotate!),AbstractVector{<:Tuple}})
Base.precompile(Tuple{typeof(axis_limits),Subplot{GRBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(axis_limits),Subplot{PlotlyBackend},Symbol,Bool,Bool})
Base.precompile(Tuple{typeof(backend),PlotlyBackend})
Base.precompile(Tuple{typeof(bbox),AbsoluteLength,AbsoluteLength,AbsoluteLength,AbsoluteLength})
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}, Int64},Vector{Float64},Tuple{Int64, Float64}})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64},Vararg{Vector{Float64}}})
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(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}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),Symbol,Vector{Float64},Vector{Any},Tuple{Int64, Int64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_ticks),UnitRange{Int64},Vector{Float64},Vector{Any},Tuple{Float64, Float64},Vararg{Any}})
Base.precompile(Tuple{typeof(get_xy),Vector{OHLC}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), NTuple{9, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_add_legend),Subplot{GRBackend},NamedTuple{(:w, :h, :dy, :leftw, :textw, :rightw, :xoffset, :yoffset, :width_factor), Tuple{Int64, Int64, Int64, Float64, Int64, Float64, Float64, Float64, Float64}},Vector{Float64}})
Base.precompile(Tuple{typeof(gr_display),Subplot{GRBackend},AbsoluteLength,AbsoluteLength,Vector{Float64}})
Base.precompile(Tuple{typeof(gr_draw_contour),Series,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_heatmap),Series,Vector{Float64},Vector{Float64},Matrix{Float64},Tuple{Float64, Float64}})
Base.precompile(Tuple{typeof(gr_draw_marker),Series,Float64,Float64,Tuple{Float64, Float64},Int64,Float64,Float64,Symbol})
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,Float64,Float64,Tuple{Float64, Float64},Int64,Int64,Int64,Symbol})
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,Float64,Tuple{Float64, Float64},Int64,Int64,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_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}})
Base.precompile(Tuple{typeof(gr_draw_segments),Series,Vector{Float64},Vector{Float64},Int64,Tuple{Float64, Float64}})
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_ticks_size),Tuple{Vector{Float64}, 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_set_gradient),PlotUtils.ContinuousColorGradient})
Base.precompile(Tuple{typeof(gr_text),Float64,Float64,String})
Base.precompile(Tuple{typeof(gr_text_size),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}})
Base.precompile(Tuple{typeof(heatmap_edges),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),UnitRange{Int64},Symbol})
Base.precompile(Tuple{typeof(heatmap_edges),Vector{Float64},Symbol})
Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}})
Base.precompile(Tuple{typeof(is_marker_supported),GRBackend,Vector{Symbol}})
Base.precompile(Tuple{typeof(layout_args),Matrix{Any}})
Base.precompile(Tuple{typeof(link_axes!),GridLayout,Symbol})
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})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),Nothing,Tuple{Int64, Int64},Symbol,Symbol})
Base.precompile(Tuple{typeof(optimal_ticks_and_labels),StepRange{Int64, Int64},Tuple{Int64, Int64},Symbol,Symbol})
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!),Plot,Plot,Plot,Vararg{Plot}})
Base.precompile(Tuple{typeof(plot),Any,Any})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}}})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend}})
Base.precompile(Tuple{typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{typeof(processLineArg),Dict{Symbol, Any},Matrix{Symbol}})
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(process_annotation),Subplot{GRBackend},Int64,Float64,PlotText,Font})
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},Font})
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},Font})
Base.precompile(Tuple{typeof(process_annotation),Subplot{GRBackend},Int64,Float64,Tuple{String, Symbol, Int64, String}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,PlotText,Font})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,PlotText})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Int64, Symbol, Symbol},Font})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Int64, Symbol, Symbol}})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Symbol, Int64, String},Font})
Base.precompile(Tuple{typeof(process_annotation),Subplot{PlotlyBackend},Int64,Float64,Tuple{String, Symbol, Int64, String}})
Base.precompile(Tuple{typeof(process_axis_arg!),Dict{Symbol, Any},StepRange{Int64, Int64},Symbol})
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, Int64, Int64},Tuple{Float64, Int64, 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),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(spy),Any})
Base.precompile(Tuple{typeof(straightline_data),Tuple{Float64, Float64},Tuple{Float64, Float64},Vector{Float64},Vector{Float64},Int64})
Base.precompile(Tuple{typeof(title!),AbstractString})
Base.precompile(Tuple{typeof(update_child_bboxes!),GridLayout})
Base.precompile(Tuple{typeof(update_clims),Float64,Float64,SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true},typeof(ignorenan_extrema)})
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}})
Base.precompile(Tuple{typeof(xgrid!),Plot{PlotlyBackend},Symbol,Vararg{Any}})
Base.precompile(Tuple{typeof(xlims),Subplot{PlotlyBackend}})
isdefined(Plots, Symbol("#2#6")) && Base.precompile(Tuple{getfield(Plots, Symbol("#2#6")),UnitRange{Int64}})
isdefined(Plots, Symbol("#322#358")) && Base.precompile(Tuple{getfield(Plots, Symbol("#322#358"))})
isdefined(Plots, Symbol("#add_major_or_minor_segments#102")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#102")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#add_major_or_minor_segments#103")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#103")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
end

View File

@ -1,8 +1,6 @@
using CompileBot include("snoop_bot_config.jl")
snoop_bench( snoop_bench(
BotConfig( botconfig,
"Plots",
),
joinpath(@__DIR__, "precompile_script.jl"), joinpath(@__DIR__, "precompile_script.jl"),
) )

View File

@ -1,8 +1,6 @@
using CompileBot include("snoop_bot_config.jl")
snoop_bot( snoop_bot(
BotConfig( botconfig,
"Plots",
),
joinpath(@__DIR__, "precompile_script.jl"), joinpath(@__DIR__, "precompile_script.jl"),
) )

7
deps/SnoopCompile/snoop_bot_config.jl vendored Normal file
View File

@ -0,0 +1,7 @@
using CompileBot
botconfig = BotConfig(
"Plots",
version = ["1.6", "1.7", "1.8", "nightly"], # <<< keep these versions in sync with .github/workflows/SnoopCompile.yml
# else_version = "nightly",
)

View File

@ -1,35 +1,61 @@
module Plots module Plots
using Pkg
if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optlevel")) if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optlevel"))
@eval Base.Experimental.@optlevel 1 @eval Base.Experimental.@optlevel 1
end end
if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@max_methods"))
@eval Base.Experimental.@max_methods 1
end
const _current_plots_version = VersionNumber(split(first(filter(line -> occursin("version", line), readlines(normpath(@__DIR__, "..", "Project.toml")))), "\"")[2]) const _plots_project = Pkg.Types.read_project(normpath(@__DIR__, "..", "Project.toml"))
const _current_plots_version = _plots_project.version
const _plots_compats = _plots_project.compat
function _check_compat(sim::Module)
sim_str = string(sim)
if !haskey(_plots_compats, sim_str)
return nothing
end
be_v = Pkg.Types.read_project(joinpath(Base.pkgdir(sim), "Project.toml")).version
be_c = _plots_compats[sim_str]
if be_c isa String # julia 1.6
if !(be_v in Pkg.Types.semver_spec(be_c))
@warn "$sim $be_v is not compatible with this version of Plots. The declared compatibility is $(be_c)."
end
else
if isempty(intersect(be_v, be_c.val))
@warn "$sim $be_v is not compatible with this version of Plots. The declared compatibility is $(be_c.str)."
end
end
end
using Reexport using Reexport
import GeometryBasics import GeometryBasics
using Dates, Printf, Statistics, Base64, LinearAlgebra, Random using Dates, Printf, Statistics, Base64, LinearAlgebra, Random, Unzip
using SparseArrays using SparseArrays
using FFMPEG using FFMPEG
@reexport using RecipesBase @reexport using RecipesBase
import RecipesBase: plot, plot!, animate, is_explicit import RecipesBase: plot, plot!, animate, is_explicit, grid
using Base.Meta using Base.Meta
@reexport using PlotUtils @reexport using PlotUtils
@reexport using PlotThemes @reexport using PlotThemes
import Showoff import UnicodeFun
import StatsBase import StatsBase
import Downloads
import Showoff
import JSON import JSON
using Requires using Requires
#! format: off
export export
grid, grid,
bbox, bbox,
plotarea, plotarea,
@layout,
KW, KW,
wrap, wrap,
@ -117,8 +143,7 @@ export
scalefontsize, scalefontsize,
scalefontsizes, scalefontsizes,
resetfontsizes resetfontsizes
#! format: on
# --------------------------------------------------------- # ---------------------------------------------------------
import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563 import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563
@ -137,7 +162,6 @@ ignorenan_extrema(x) = Base.extrema(x)
# This makes it impossible to create row vectors of String and Symbol with the transpose operator. # This makes it impossible to create row vectors of String and Symbol with the transpose operator.
# This solves this issue, internally in Plots at least. # This solves this issue, internally in Plots at least.
# commented out on the insistence of the METADATA maintainers # commented out on the insistence of the METADATA maintainers
#Base.transpose(x::Symbol) = x #Base.transpose(x::Symbol) = x
@ -148,12 +172,15 @@ ignorenan_extrema(x) = Base.extrema(x)
import Measures import Measures
module PlotMeasures module PlotMeasures
import Measures import Measures
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h import Measures:
Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
const BBox = Measures.Absolute2DBox const BBox = Measures.Absolute2DBox
# allow pixels and percentages # allow pixels and percentages
const px = AbsoluteLength(0.254) const px = AbsoluteLength(0.254)
const pct = Length{:pct, Float64}(1.0) 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::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value) Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
@ -168,7 +195,8 @@ import .PlotMeasures: Length, AbsoluteLength, Measure, width, height
# --------------------------------------------------------- # ---------------------------------------------------------
import RecipesPipeline import RecipesPipeline
import RecipesPipeline: SliceIt, import RecipesPipeline:
SliceIt,
DefaultsDict, DefaultsDict,
Formatted, Formatted,
AbstractSurface, AbstractSurface,
@ -182,14 +210,13 @@ import RecipesPipeline: SliceIt,
pop_kw!, pop_kw!,
scale_func, scale_func,
inverse_scale_func, inverse_scale_func,
unzip,
dateformatter, dateformatter,
datetimeformatter, datetimeformatter,
timeformatter timeformatter
# Use fixed version of Plotly instead of the latest one for stable dependency # Use fixed version of Plotly instead of the latest one for stable dependency
# Ref: https://github.com/JuliaPlots/Plots.jl/pull/2779 # Ref: https://github.com/JuliaPlots/Plots.jl/pull/2779
const _plotly_min_js_filename = "plotly-1.57.1.min.js" const _plotly_min_js_filename = "plotly-2.6.3.min.js"
include("types.jl") include("types.jl")
include("utils.jl") include("utils.jl")
@ -197,6 +224,7 @@ include("colorbars.jl")
include("axes.jl") include("axes.jl")
include("args.jl") include("args.jl")
include("components.jl") include("components.jl")
include("consts.jl")
include("themes.jl") include("themes.jl")
include("plot.jl") include("plot.jl")
include("pipeline.jl") include("pipeline.jl")
@ -220,36 +248,34 @@ include("backends/web.jl")
include("shorthands.jl") include("shorthands.jl")
let PlotOrSubplot = Union{Plot, Subplot} let PlotOrSubplot = Union{Plot,Subplot}
global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...) global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
global xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...) global xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
global ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...) global ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
global xlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; xlims = lims, kw...) global xlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; xlims = lims, kw...)
global ylims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; ylims = lims, kw...) global ylims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; ylims = lims, kw...)
global zlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; zlims = lims, kw...) global zlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; zlims = lims, kw...)
global xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...) global xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin, xmax), kw...)
global ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...) global ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin, ymax), kw...)
global zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...) global zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin, zmax), kw...)
global xticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; xticks = ticks, kw...) global xticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; xticks = ticks, kw...)
global yticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; yticks = ticks, kw...) global yticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; yticks = ticks, kw...)
global xticks!(plt::PlotOrSubplot, global xticks!(plt::PlotOrSubplot, ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks, labels), kw...)
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...) global yticks!(plt::PlotOrSubplot, ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (ticks, labels), kw...)
global yticks!(plt::PlotOrSubplot, global xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (ticks,labels), kw...) global ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
global xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...) global annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
global ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...) global annotate!(plt::PlotOrSubplot, anns::AVec{T}; kw...) where {T<:Tuple} = plot!(plt; annotation = anns, kw...)
global annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...) global xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
global annotate!(plt::PlotOrSubplot, anns::AVec{T}; kw...) where {T<:Tuple} = plot!(plt; annotation = anns, kw...) global yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
global xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...) global xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
global yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...) global yaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; yaxis = args, kw...)
global xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
global yaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; yaxis = args, kw...)
end end
# --------------------------------------------------------- # ---------------------------------------------------------
const CURRENT_BACKEND = CurrentBackend(:none) const CURRENT_BACKEND = CurrentBackend(:none)
const PLOTS_SEED = 1234
include("precompile_includer.jl") include("precompile_includer.jl")

View File

@ -14,24 +14,24 @@ end
Add a plot (the current plot if not specified) to an existing animation Add a plot (the current plot if not specified) to an existing animation
""" """
function frame(anim::Animation, plt::P=current()) where P<:AbstractPlot function frame(anim::Animation, plt::P = current()) where {P<:AbstractPlot}
i = length(anim.frames) + 1 i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i) filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename)) png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename) push!(anim.frames, filename)
end end
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif") giffn() = (isijulia() ? "tmp.gif" : tempname() * ".gif")
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov") movfn() = (isijulia() ? "tmp.mov" : tempname() * ".mov")
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4") mp4fn() = (isijulia() ? "tmp.mp4" : tempname() * ".mp4")
webmfn() = (isijulia() ? "tmp.webm" : tempname()*".webm") webmfn() = (isijulia() ? "tmp.webm" : tempname() * ".webm")
mutable struct FrameIterator mutable struct FrameIterator
itr itr
every::Int every::Int
kw kw
end end
FrameIterator(itr; every=1, kw...) = FrameIterator(itr, every, kw) FrameIterator(itr; every = 1, kw...) = FrameIterator(itr, every, kw)
""" """
Animate from an iterator which returns the plot args each iteration. Animate from an iterator which returns the plot args each iteration.
@ -48,8 +48,8 @@ function animate(fitr::FrameIterator, fn = giffn(); kw...)
end end
# most things will implement this # most things will implement this
function animate(obj, fn = giffn(); every=1, fps=20, loop=0, kw...) function animate(obj, fn = giffn(); every = 1, fps = 20, loop = 0, kw...)
animate(FrameIterator(obj, every, kw), fn; fps=fps, loop=loop) animate(FrameIterator(obj, every, kw), fn; fps = fps, loop = loop)
end end
# ----------------------------------------------- # -----------------------------------------------
@ -69,12 +69,16 @@ webm(anim::Animation, fn = webmfn(); kw...) = buildanimation(anim, fn, false; kw
ffmpeg_framerate(fps) = "$fps" ffmpeg_framerate(fps) = "$fps"
ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)" ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)"
function buildanimation(anim::Animation, fn::AbstractString, function buildanimation(
is_animated_gif::Bool=true; anim::Animation,
fps::Real = 20, loop::Integer = 0, fn::AbstractString,
variable_palette::Bool=false, is_animated_gif::Bool = true;
verbose=false, fps::Real = 20,
show_msg::Bool=true) loop::Integer = 0,
variable_palette::Bool = false,
verbose = false,
show_msg::Bool = true,
)
if length(anim.frames) == 0 if length(anim.frames) == 0
throw(ArgumentError("Cannot build empty animations")) throw(ArgumentError("Cannot build empty animations"))
end end
@ -82,41 +86,49 @@ function buildanimation(anim::Animation, fn::AbstractString,
fn = abspath(expanduser(fn)) fn = abspath(expanduser(fn))
animdir = anim.dir animdir = anim.dir
framerate = ffmpeg_framerate(fps) framerate = ffmpeg_framerate(fps)
verbose_level = (verbose isa Int ? verbose : verbose_level = (verbose isa Int ? verbose : verbose ? 32 : 16) # "error"
verbose ? 32 # "info"
: 16) # "error"
if is_animated_gif if is_animated_gif
if variable_palette if variable_palette
# generate a colorpalette for each frame for highest quality, but larger filesize # generate a colorpalette for each frame for highest quality, but larger filesize
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1" palette = "palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1"
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -lavfi "$palette" -loop $loop -y $fn`) ffmpeg_exe(
`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -lavfi "$palette" -loop $loop -y $fn`,
)
else else
# generate a colorpalette first so ffmpeg does not have to guess it # generate a colorpalette first so ffmpeg does not have to guess it
ffmpeg_exe(`-v $verbose_level -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`) ffmpeg_exe(
`-v $verbose_level -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`,
)
# then apply the palette to get better results # then apply the palette to get better results
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -loop $loop -y $fn`) ffmpeg_exe(
`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -loop $loop -y $fn`,
)
end end
else else
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -vf format=yuv420p -loop $loop -y $fn`) ffmpeg_exe(
`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -vf format=yuv420p -loop $loop -y $fn`,
)
end end
show_msg && @info("Saved animation to ", fn) show_msg && @info("Saved animation to ", fn)
AnimatedGif(fn) AnimatedGif(fn)
end end
# write out html to view the gif # write out html to view the gif
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
ext = file_extension(agif.filename) ext = file_extension(agif.filename)
if ext == "gif" if ext == "gif"
html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />" html =
elseif ext in ("mov", "mp4","webm") "<img src=\"data:image/gif;base64," *
base64encode(read(agif.filename)) *
"\" />"
elseif ext in ("mov", "mp4", "webm")
mimetype = ext == "mov" ? "video/quicktime" : "video/$ext" mimetype = ext == "mov" ? "video/quicktime" : "video/$ext"
html = "<video controls><source src=\"data:$mimetype;base64," * html =
base64encode(read(agif.filename)) * "<video controls><source src=\"data:$mimetype;base64," *
"\" type = \"$mimetype\"></video>" base64encode(read(agif.filename)) *
"\" type = \"$mimetype\"></video>"
else else
error("Cannot show animation with extension $ext: $agif") error("Cannot show animation with extension $ext: $agif")
end end
@ -125,64 +137,67 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
return nothing return nothing
end end
# Only gifs can be shown via image/gif # Only gifs can be shown via image/gif
Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif" Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif"
function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif) function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif)
open(fio-> write(io, fio), agif.filename) open(fio -> write(io, fio), agif.filename)
end end
# ----------------------------------------------- # -----------------------------------------------
function _animate(forloop::Expr, args...; callgif = false) function _animate(forloop::Expr, args...; callgif = false)
if forloop.head != :for if forloop.head (:for, :while)
error("@animate macro expects a for-block. got: $(forloop.head)") error("@animate macro expects a for- or while-block. got: $(forloop.head)")
end end
# add the call to frame to the end of each iteration # add the call to frame to the end of each iteration
animsym = gensym("anim") animsym = gensym("anim")
countersym = gensym("counter") countersym = gensym("counter")
freqassert = :() freqassert = :()
block = forloop.args[2] block = forloop.args[2]
# create filter # create filter
n = length(args) n = length(args)
filterexpr = if n == 0 filterexpr = if n == 0
# no filter... every iteration gets a frame # no filter... every iteration gets a frame
true true
elseif args[1] == :every elseif args[1] == :every
# filter every `freq` frames (starting with the first frame) # filter every `freq` frames (starting with the first frame)
@assert n == 2 @assert n == 2
freq = args[2] freq = args[2]
freqassert = :(@assert isa($freq, Integer) && $freq > 0) freqassert = :(@assert isa($freq, Integer) && $freq > 0)
:(mod1($countersym, $freq) == 1) :(mod1($countersym, $freq) == 1)
elseif args[1] == :when elseif args[1] == :when
# filter on custom expression # filter on custom expression
@assert n == 2 @assert n == 2
args[2] args[2]
else else
error("Unsupported animate filter: $args") error("Unsupported animate filter: $args")
end end
push!(block.args, :(if $filterexpr; Plots.frame($animsym); end)) push!(block.args, :(
push!(block.args, :(global $countersym += 1)) if $filterexpr
Plots.frame($animsym)
end
))
push!(block.args, :($countersym += 1))
# add a final call to `gif(anim)`? # add a final call to `gif(anim)`?
retval = callgif ? :(Plots.gif($animsym)) : animsym retval = callgif ? :(Plots.gif($animsym)) : animsym
# full expression: # full expression:
esc(quote esc(quote
$freqassert # if filtering, check frequency is an Integer > 0 $freqassert # if filtering, check frequency is an Integer > 0
$animsym = Plots.Animation() # init animation object $animsym = Plots.Animation() # init animation object
global $countersym = 1 # init iteration counter let $countersym = 1 # init iteration counter
$forloop # for loop, saving a frame after each iteration $forloop # for loop, saving a frame after each iteration
$retval # return the animation object, or the gif end
end) $retval # return the animation object, or the gif
end)
end end
""" """

View File

@ -1,172 +1,192 @@
const _arg_desc = KW( const _arg_desc = KW(
# series args # series args
:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.", :label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.",
:seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot", :seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot",
:seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.", :seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.",
:seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.", :seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.",
:linestyle => "Symbol. Style of the line (for path and bar stroke). Choose from $(_allStyles)", :linestyle => "Symbol. Style of the line (for path and bar stroke). Choose from $(_allStyles)",
:linewidth => "Number. Width of the line (in pixels)", :linewidth => "Number. Width of the line (in pixels)",
:linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).", :linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).",
:linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.", :linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.",
:fillrange => "Number or AbstractVector. Fills area between fillrange and y for line-types, sets the base for bar/stick types, and similar for other types.", :fillrange => "Number or AbstractVector. Fills area between fillrange and y for line-types, sets the base for bar/stick types, and similar for other types.",
:fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.", :fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.",
:fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.", :fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.",
:markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).", :markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).",
:markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.", :fillstyle => "Symbol. Style of the fill area. `nothing` (the default) means solid fill. Choose from :/, :\\, :|, :-, :+, :x",
:markeralpha => "Number in [0,1]. The alpha/opacity override for the marker interior. `nothing` (the default) means it will take the alpha value of markercolor.", :markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.",
:markersize => "Number or AbstractVector. Size (radius pixels) of the markers.", :markeralpha => "Number in [0,1]. The alpha/opacity override for the marker interior. `nothing` (the default) means it will take the alpha value of markercolor.",
:markerstrokestyle => "Symbol. Style of the marker stroke (border). Choose from $(_allStyles)", :markersize => "Number or AbstractVector. Size (radius pixels) of the markers",
:markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)", :markerstrokestyle => "Symbol. Style of the marker stroke (border). Choose from $(_allStyles)",
:markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokewidth => "Number. Width of the marker stroke (border) in pixels",
:markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.",
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(minimum(x), stop = maximum(x), length = 25)`", :markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.",
:smooth => "Bool. Add a regression line?", :bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(minimum(x), stop = maximum(x), length = 25)`",
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.", :smooth => "Bool. Add a regression line?",
:x => "Various. Input data. First Dimension", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`",
:y => "Various. Input data. Second Dimension", :x => "Various. Input data. First Dimension",
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.", :y => "Various. Input data. Second Dimension",
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.", :z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).", :marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", :line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
:levels => "Integer, NTuple{2,Integer}, or AbstractVector. Levels or number of levels (or x-levels/y-levels) for a contour type.", :fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).", :levels => "Integer (number of contours) or AbstractVector (contour values). Determines contour levels for a contour type.",
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)", :permute => "Tuple{Symbol,Symbol}. Permutes data and axis properties of the axes given in the tuple. E.g. (:x, :y).",
:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", :orientation => "Symbol. (deprecated) Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", :bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)", :bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).",
:yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)", :bar_edges => "Bool. Align bars to edges (true), or centers (the default)?",
:ribbon => "Number or AbstractVector. Creates a fillrange around the data points.", :xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)",
:quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.", :yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)",
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.", :ribbon => "Number or AbstractVector. Creates a fillrange around the data points.",
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).", :quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.",
:weights => "AbstractVector. Used in histogram types for weighted counts.", :arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
:show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default).", :normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.", :weights => "AbstractVector. Used in histogram types for weighted counts.",
:contour_labels => "Bool. Show labels at the contour lines?", :show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default)",
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.", :contour_labels => "Bool. Show labels at the contour lines?",
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.", :match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.", :subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.",
:hover => "nothing or vector of strings. Text to display when hovering over each data point.", :series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",
:colorbar_entry => "Bool. Include this series in the color bar? Set to `false` to exclude.", :primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
:colorbar_entry => "Bool. Include this series in the color bar? Set to `false` to exclude.",
:z_order => "Symbol or Integer. :front (default), :back or index of position where 1 is farest in the background.",
# plot args # plot args
:plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)", :plot_title => "String. Title for the whole plot (not the subplots)",
:background_color => "Color Type. Base color for all backgrounds.", :plot_titlevspan => "Number in [0,1]. Vertical span of the whole plot title (fraction of the plot height)",
:background_color_outside => "Color Type or `:match` (matches `:background_color`). Color outside the plot area(s)", :background_color => "Color Type. Base color for all backgrounds.",
:foreground_color => "Color Type. Base color for all foregrounds.", :background_color_outside => "Color Type or `:match` (matches `:background_color`). Color outside the plot area(s)",
:size => "NTuple{2,Int}. (width_px, height_px) of the whole Plot", :foreground_color => "Color Type. Base color for all foregrounds.",
:pos => "NTuple{2,Int}. (left_px, top_px) position of the GUI window (note: currently unimplemented)", :size => "NTuple{2,Int}. (width_px, height_px) of the whole Plot",
:window_title => "String. Title of the standalone gui-window.", :pos => "NTuple{2,Int}. (left_px, top_px) position of the GUI window (note: currently unimplemented)",
:show => "Bool. Should this command open/refresh a GUI/display? This allows displaying in scripts or functions without explicitly calling `display`", :window_title => "String. Title of the standalone gui-window.",
:layout => "Integer (number of subplots), NTuple{2,Integer} (grid dimensions), AbstractLayout (for example `grid(2,2)`), or the return from the `@layout` macro. This builds the layout of subplots.", :show => "Bool. Should this command open/refresh a GUI/display? This allows displaying in scripts or functions without explicitly calling `display`",
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).", :layout => "Integer (number of subplots), NTuple{2,Integer} (grid dimensions), AbstractLayout (for example `grid(2,2)`), or the return from the `@layout` macro. This builds the layout of subplots.",
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).", :link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.", :overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
:tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.", :html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots", :tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.",
:dpi => "Number. Dots Per Inch of output figures", :inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.", :dpi => "Number. Dots Per Inch of output figures",
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.", :thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
:extra_kwargs => "Either one of (`:plot`, `:subplot`, `:series`) to specify for which element extra keyword args are collected or a KW (Dict{Symbol,Any}) to pass a map of extra keyword args which may be specific to a backend. Default: `:series`.\n Example: `pgfplotsx(); scatter(1:5, extra_kwargs=Dict(:subplot=>Dict(\"axis line shift\" => \"10pt\"))`", :display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides", :extra_kwargs => "Either one of (`:plot`, `:subplot`, `:series`) to specify for which element extra keyword args are collected or a KW (Dict{Symbol,Any}) to pass a map of extra keyword args which may be specific to a backend. Default: `:series`.\n Example: `pgfplotsx(); scatter(1:5, extra_kwargs=Dict(:subplot=>Dict(\"axis line shift\" => \"10pt\"))`",
:warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes", :fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
:warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes",
# subplot args # subplot args
:title => "String. Subplot title.", :title => "String. Subplot title.",
:titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`", :titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
:titlefontfamily => "String or Symbol. Font family of subplot title.", :titlefontfamily => "String or Symbol. Font family of subplot title.",
:titlefontsize => "Integer. Font pointsize of subplot title.", :titlefontsize => "Integer. Font pointsize of subplot title.",
:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center", :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", :titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center",
:titlefontrotation => "Real. Font rotation of subplot title", :titlefontrotation => "Real. Font rotation of subplot title",
:titlefontcolor => "Color Type. Font color 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_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.", :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).", :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_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.", :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.", :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.", :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.", :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)",
:legendfontfamily => "String or Symbol. Font family of legend entries.", :legend_column => "Integer. Number of columns in the legend. `-1` stands for maximum number of colums (horizontal legend).",
:legendfontsize => "Integer. Font pointsize of legend entries.", :legend_title_font => "Font. Font of the legend title.",
:legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center", :legend_font_family => "String or Symbol. Font family of legend entries.",
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center", :legend_font_pointsize => "Integer. Font pointsize of legend entries.",
:legendfontrotation => "Real. Font rotation of legend entries", :legend_font_halign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
:legendfontcolor => "Color Type. Font color of legend entries", :legend_font_valign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendtitle => "String. Legend title.", :legend_font_rotation => "Real. Font rotation of legend entries",
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.", :legend_font_color => "Color Type. Font color of legend entries",
:legendtitlefontsize => "Integer. Font pointsize the legend title.", :legend_title => "String. Legend title.",
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center", :legend_title_font_family => "String or Symbol. Font family of the legend title.",
:legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center", :legend_title_font_pointsize => "Integer. Font pointsize the legend title.",
:legendtitlefontrotation => "Real. Font rotation of the legend title", :legend_title_font_halign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legendtitlefontcolor => "Color Type. Font color of the legend title", :legend_title_font_valign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
: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)", :legend_title_font_rotation => "Real. Font rotation of the legend title",
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.", :legend_title_font_color => "Color Type. Font color of the legend title",
:colorbar_fontfamily => "String or Symbol. Font family of colobar entries.", :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)",
:colorbar_ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", :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_tickfontfamily => "String or Symbol. Font family of colorbar tick labels.", :colorbar_fontfamily => "String or Symbol. Font family of colobar entries.",
:colorbar_tickfontsize => "Integer. Font pointsize of colorbar tick entries.", :colorbar_ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
:colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries", :colorbar_tickfontfamily => "String or Symbol. Font family of colorbar tick labels.",
:colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`", :colorbar_tickfontsize => "Integer. Font pointsize of colorbar tick entries.",
:colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", :colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries",
:legendfont => "Font. Font of legend items.", :colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`",
:legendtitlefont => "Font. Font of the legend title.", :colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.", :legend_font => "Font. Font of legend items.",
:projection => "Symbol or String. '3d' or 'polar'", :legend_titlefont => "Font. Font of the legend title.",
: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.", :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.",
:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.", :annotationfontfamily => "String or Symbol. Font family of annotations.",
:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.", :annotationfontsize => "Integer. Font pointsize of annotations.",
:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.", :annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.",
:right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.", :annotationvalign => "Symbol. Vertical alignment of annotations, :vcenter, :top, :bottom or :center.",
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.", :annotationrotation => "Float. Rotation of annotations in degrees.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.", :annotationcolor => "Colorant or :match. Color of annotations.",
:colorbar_title => "String. Title of colorbar.", :projection => "Symbol or String. '3d' or 'polar'",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)", :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.",
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots", :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 # axis args
:guide => "String. Axis guide (label).", :guide => "String. Axis guide (label).",
:guide_position => "Symbol. Position of axis guides: :top, :bottom, :left or :right", :guide_position => "Symbol. Position of axis guides: :top, :bottom, :left or :right",
:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]", :lims => """
:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example).
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]
:rotation => "Number. Degrees rotation of tick labels.", `:symmetric` sets the limits to be symmetric around zero.
:flip => "Bool. Should we flip (reverse) the axis?", Set widen=true to widen the specified limits (as occurs when lims are not specified).
:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", """,
:tickfontfamily => "String or Symbol. Font family of tick labels.", :ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
:tickfontsize => "Integer. Font pointsize of tick labels.", :scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center", :rotation => "Number. Degrees rotation of tick labels.",
:tickfontvalign => "Symbol. Font vertical alignment of tick labels: :vcenter, :top, :bottom or :center", :flip => "Bool. Should we flip (reverse) the axis?",
:tickfontrotation => "Real. Font rotation of tick labels", :formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
:tickfontcolor => "Color Type. Font color of tick labels", :tickfontfamily => "String or Symbol. Font family of tick labels.",
:guidefontfamily => "String or Symbol. Font family of axes guides.", :tickfontsize => "Integer. Font pointsize of tick labels.",
:guidefontsize => "Integer. Font pointsize of axes guides.", :tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
:guidefonthalign => "Symbol. Font horizontal alignment of axes guides: :hcenter, :left, :right or :center", :tickfontvalign => "Symbol. Font vertical alignment of tick labels: :vcenter, :top, :bottom or :center",
:guidefontvalign => "Symbol. Font vertical alignment of axes guides: :vcenter, :top, :bottom or :center", :tickfontrotation => "Real. Font rotation of tick labels",
:guidefontrotation => "Real. Font rotation of axes guides", :tickfontcolor => "Color Type. Font color of tick labels",
:guidefontcolor => "Color Type. Font color of axes guides", :guidefontfamily => "String or Symbol. Font family of axes guides.",
:foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.", :guidefontsize => "Integer. Font pointsize of axes guides.",
:foreground_color_border => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of plot area border (spines).", :guidefonthalign => "Symbol. Font horizontal alignment of axes guides: :hcenter, :left, :right or :center",
:foreground_color_text => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of tick labels.", :guidefontvalign => "Symbol. Font vertical alignment of axes guides: :vcenter, :top, :bottom or :center",
:foreground_color_guide => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis guides (axis labels).", :guidefontrotation => "Real. Font rotation of axes guides",
:mirror => "Bool. Switch the side of the tick labels (right or top).", :guidefontcolor => "Color Type. Font color of axes guides",
:grid => "Bool, Symbol, String or `nothing`. Show the grid lines? `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:none`, `:off`", :foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.",
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.", :foreground_color_border => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of plot area border (spines).",
:gridalpha => "Number in [0,1]. The alpha/opacity override for the grid lines.", :foreground_color_text => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of tick labels.",
:gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)", :foreground_color_guide => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis guides (axis labels).",
:gridlinewidth => "Number. Width of the grid lines (in pixels)", :mirror => "Bool. Switch the side of the tick labels (right or top).",
:foreground_color_minor_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of minor grid lines.", :grid => "Bool, Symbol, String or `nothing`. Show the grid lines? `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:none`, `:off`",
:minorgrid => "Bool. Adds minor grid lines and ticks to the plot. Set minorticks to change number of gridlines", :foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
:minorticks => "Integer. Intervals to divide the gap between major ticks into", :gridalpha => "Number in [0,1]. The alpha/opacity override for the grid lines.",
:minorgridalpha => "Number in [0,1]. The alpha/opacity override for the minorgrid lines.", :gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)",
:minorgridstyle => "Symbol. Style of the minor grid lines. Choose from $(_allStyles)", :gridlinewidth => "Number. Width of the grid lines (in pixels)",
:minorgridlinewidth => "Number. Width of the minor grid lines (in pixels)", :foreground_color_minor_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of minor grid lines.",
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`", :minorgrid => "Bool. Adds minor grid lines and ticks to the plot. Set minorticks to change number of gridlines",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`", :minorticks => "Integer. Intervals to divide the gap between major ticks into",
:widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.", :minorgridalpha => "Number in [0,1]. The alpha/opacity override for the minorgrid lines.",
:draw_arrow => "Bool. Draw arrow at the end of the axis.", :minorgridstyle => "Symbol. Style of the minor grid lines. Choose from $(_allStyles)",
:minorgridlinewidth => "Number. Width of the minor grid lines (in pixels)",
:tick_direction => "Symbol. Direction of the ticks. `:in`, `:out` or `:none`",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`",
:widen => """
Bool or :auto. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders.
Defaults to `:auto`, which widens unless limits were manually set.
""",
:draw_arrow => "Bool. Draw arrow at the end of the axis.",
) )

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
# xaxis(args...; kw...) = Axis(:x, args...; kw...) # xaxis(args...; kw...) = Axis(:x, args...; kw...)
# yaxis(args...; kw...) = Axis(:y, args...; kw...) # yaxis(args...; kw...) = Axis(:y, args...; kw...)
# zaxis(args...; kw...) = Axis(:z, args...; kw...) # zaxis(args...; kw...) = Axis(:z, args...; kw...)
@ -24,7 +23,7 @@ function Axis(sp::Subplot, letter::Symbol, args...; kw...)
end end
function get_axis(sp::Subplot, letter::Symbol) function get_axis(sp::Subplot, letter::Symbol)
axissym = Symbol(letter, :axis) axissym = get_attr_symbol(letter, :axis)
if haskey(sp.attr, axissym) if haskey(sp.attr, axissym)
sp.attr[axissym] sp.attr[axissym]
else else
@ -36,42 +35,45 @@ function process_axis_arg!(plotattributes::AKW, arg, letter = "")
T = typeof(arg) T = typeof(arg)
arg = get(_scaleAliases, arg, arg) arg = get(_scaleAliases, arg, arg)
if typeof(arg) <: Font if typeof(arg) <: Font
plotattributes[Symbol(letter,:tickfont)] = arg plotattributes[get_attr_symbol(letter, :tickfont)] = arg
plotattributes[Symbol(letter,:guidefont)] = arg plotattributes[get_attr_symbol(letter, :guidefont)] = arg
elseif arg in _allScales elseif arg in _allScales
plotattributes[Symbol(letter,:scale)] = arg plotattributes[get_attr_symbol(letter, :scale)] = arg
elseif arg in (:flip, :invert, :inverted) elseif arg in (:flip, :invert, :inverted)
plotattributes[Symbol(letter,:flip)] = true plotattributes[get_attr_symbol(letter, :flip)] = true
elseif T <: AbstractString elseif T <: AbstractString
plotattributes[Symbol(letter,:guide)] = arg plotattributes[get_attr_symbol(letter, :guide)] = arg
# xlims/ylims # xlims/ylims
elseif (T <: Tuple || T <: AVec) && length(arg) == 2 elseif (T <: Tuple || T <: AVec) && length(arg) == 2
sym = typeof(arg[1]) <: Number ? :lims : :ticks sym = typeof(arg[1]) <: Number ? :lims : :ticks
plotattributes[Symbol(letter,sym)] = arg plotattributes[get_attr_symbol(letter, sym)] = arg
# xticks/yticks # xticks/yticks
elseif T <: AVec elseif T <: AVec
plotattributes[Symbol(letter,:ticks)] = arg plotattributes[get_attr_symbol(letter, :ticks)] = arg
elseif arg === nothing elseif arg === nothing
plotattributes[Symbol(letter,:ticks)] = [] plotattributes[get_attr_symbol(letter, :ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs elseif T <: Bool || arg in _allShowaxisArgs
plotattributes[Symbol(letter,:showaxis)] = showaxis(arg, letter) plotattributes[get_attr_symbol(letter, :showaxis)] = showaxis(arg, letter)
elseif typeof(arg) <: Number elseif typeof(arg) <: Number
plotattributes[Symbol(letter,:rotation)] = arg plotattributes[get_attr_symbol(letter, :rotation)] = arg
elseif typeof(arg) <: Function elseif typeof(arg) <: Function
plotattributes[Symbol(letter,:formatter)] = arg plotattributes[get_attr_symbol(letter, :formatter)] = arg
elseif !handleColors!(plotattributes, arg, Symbol(letter, :foreground_color_axis)) elseif !handleColors!(
plotattributes,
arg,
get_attr_symbol(letter, :foreground_color_axis),
)
@warn("Skipped $(letter)axis arg $arg") @warn("Skipped $(letter)axis arg $arg")
end end
end end
@ -87,15 +89,15 @@ function attr!(axis::Axis, args...; kw...)
RecipesPipeline.preprocess_attributes!(KW(kw)) RecipesPipeline.preprocess_attributes!(KW(kw))
# then override for any keywords... only those keywords that already exists in plotattributes # then override for any keywords... only those keywords that already exists in plotattributes
for (k,v) in kw for (k, v) in kw
if haskey(plotattributes, k) if haskey(plotattributes, k)
if k == :discrete_values if k == :discrete_values
# add these discrete values to the axis # add these discrete values to the axis
for vi in v for vi in v
discrete_value!(axis, vi) discrete_value!(axis, vi)
end end
#could perhaps use TimeType here, as Date and DateTime are both subtypes of TimeType #could perhaps use TimeType here, as Date and DateTime are both subtypes of TimeType
# or could perhaps check if dateformatter or datetimeformatter is in use # or could perhaps check if dateformatter or datetimeformatter is in use
elseif k == :lims && isa(v, Tuple{Date,Date}) elseif k == :lims && isa(v, Tuple{Date,Date})
plotattributes[k] = (v[1].instant.periods.value, v[2].instant.periods.value) plotattributes[k] = (v[1].instant.periods.value, v[2].instant.periods.value)
elseif k == :lims && isa(v, Tuple{DateTime,DateTime}) elseif k == :lims && isa(v, Tuple{DateTime,DateTime})
@ -122,11 +124,8 @@ Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.plotattributes, v,
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k) Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k)
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax)) ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
const _label_func = Dict{Symbol,Function}( const _label_func =
:log10 => x -> "10^$x", Dict{Symbol,Function}(:log10 => x -> "10^$x", :log2 => x -> "2^$x", :ln => x -> "e^$x")
:log2 => x -> "2^$x",
:ln => x -> "e^$x",
)
labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string) labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string)
const _label_func_tex = Dict{Symbol,Function}( const _label_func_tex = Dict{Symbol,Function}(
@ -136,7 +135,6 @@ const _label_func_tex = Dict{Symbol,Function}(
) )
labelfunc_tex(scale::Symbol) = get(_label_func_tex, scale, convert_sci_unicode) labelfunc_tex(scale::Symbol) = get(_label_func_tex, scale, convert_sci_unicode)
function optimal_ticks_and_labels(ticks, alims, scale, formatter) function optimal_ticks_and_labels(ticks, alims, scale, formatter)
amin, amax = alims amin, amax = alims
@ -158,8 +156,8 @@ function optimal_ticks_and_labels(ticks, alims, scale, formatter)
# are converted to 'DateTime integers' (actually floats) before # are converted to 'DateTime integers' (actually floats) before
# being passed to optimize_datetime_ticks. # being passed to optimize_datetime_ticks.
# (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i) # (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i)
ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax; ticks, labels =
k_min = 2, k_max = 4) optimize_datetime_ticks(864e5 * amin, 864e5 * amax; k_min = 2, k_max = 4)
# Now the ticks are converted back to floats corresponding to Dates. # Now the ticks are converted back to floats corresponding to Dates.
return ticks / 864e5, labels return ticks / 864e5, labels
elseif formatter == RecipesPipeline.datetimeformatter elseif formatter == RecipesPipeline.datetimeformatter
@ -172,8 +170,9 @@ function optimal_ticks_and_labels(ticks, alims, scale, formatter)
scaled_ticks = optimize_ticks( scaled_ticks = optimize_ticks(
sf(amin), sf(amin),
sf(amax); sf(amax);
k_min = 4, # minimum number of ticks k_min = scale _logScales ? 2 : 4, # minimum number of ticks
k_max = 8, # maximum number of ticks k_max = 8, # maximum number of ticks
scale = scale,
)[1] )[1]
elseif typeof(ticks) <: Int elseif typeof(ticks) <: Int
scaled_ticks, viewmin, viewmax = optimize_ticks( scaled_ticks, viewmin, viewmax = optimize_ticks(
@ -185,6 +184,7 @@ function optimal_ticks_and_labels(ticks, alims, scale, formatter)
# `strict_span = false` rewards cases where the span of the # `strict_span = false` rewards cases where the span of the
# chosen ticks is not too much bigger than amin - amax: # chosen ticks is not too much bigger than amin - amax:
strict_span = false, strict_span = false,
scale = scale,
) )
# axis[:lims] = map(RecipesPipeline.inverse_scale_func(scale), (viewmin, viewmax)) # axis[:lims] = map(RecipesPipeline.inverse_scale_func(scale), (viewmin, viewmax))
else else
@ -196,7 +196,10 @@ function optimal_ticks_and_labels(ticks, alims, scale, formatter)
if formatter in (:auto, :plain, :scientific, :engineering) if formatter in (:auto, :plain, :scientific, :engineering)
map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, formatter)) map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, formatter))
elseif formatter == :latex elseif formatter == :latex
map(x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"), Showoff.showoff(unscaled_ticks, :auto)) map(
x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"),
Showoff.showoff(unscaled_ticks, :auto),
)
else else
# there was an override for the formatter... use that on the unscaled ticks # there was an override for the formatter... use that on the unscaled ticks
map(formatter, unscaled_ticks) map(formatter, unscaled_ticks)
@ -221,21 +224,87 @@ function get_ticks(sp::Subplot, axis::Axis; update = true)
if update || !haskey(axis.plotattributes, :optimized_ticks) if update || !haskey(axis.plotattributes, :optimized_ticks)
dvals = axis[:discrete_values] dvals = axis[:discrete_values]
ticks = _transform_ticks(axis[:ticks]) ticks = _transform_ticks(axis[:ticks])
axis.plotattributes[:optimized_ticks] = if ticks isa Symbol && ticks !== :none && axis.plotattributes[:optimized_ticks] =
ispolar(sp) && axis[:letter] === :x && !isempty(dvals) if (
collect(0:pi/4:7pi/4), string.(0:45:315) ticks isa Symbol &&
else ticks !== :none &&
cvals = axis[:continuous_values] ispolar(sp) &&
alims = axis_limits(sp, axis[:letter]) axis[:letter] === :x &&
scale = axis[:scale] !isempty(dvals)
formatter = axis[:formatter] )
get_ticks(ticks, cvals, dvals, alims, scale, formatter) collect(0:(pi / 4):(7pi / 4)), string.(0:45:315)
end else
cvals = axis[:continuous_values]
alims = axis_limits(sp, axis[:letter])
scale = axis[:scale]
formatter = axis[:formatter]
get_ticks(ticks, cvals, dvals, alims, scale, formatter)
end
end end
return axis.plotattributes[:optimized_ticks] return axis.plotattributes[:optimized_ticks]
end end
function get_ticks(ticks::Symbol, cvals::T, dvals, args...) where T # Ticks getter functions
for l in (:x, :y, :z)
axis = string(l, "-axis") # "x-axis"
ticks = string(l, "ticks") # "xticks"
f = Symbol(ticks) # :xticks
@eval begin
"""
$($f)(p::Plot)
returns a vector of the $($axis) ticks of the subplots of `p`.
Example use:
```jldoctest
julia> p = plot(1:5, $($ticks)=[1,2])
julia> $($f)(p)
1-element Vector{Tuple{Vector{Float64}, Vector{String}}}:
([1.0, 2.0], ["1", "2"])
```
If `p` consists of a single subplot, you might want to grab
only the first element, via
```jldoctest
julia> $($f)(p)[1]
([1.0, 2.0], ["1", "2"])
```
or you can call $($f) on the first (only) subplot of `p` via
```jldoctest
julia> $($f)(p[1])
([1.0, 2.0], ["1", "2"])
```
"""
$f(p::Plot) = get_ticks(p, $(Meta.quot(l)))
"""
$($f)(sp::Subplot)
returns the $($axis) ticks of the subplot `sp`.
Note that the ticks are returned as tuples of values and labels:
```jldoctest
julia> sp = plot(1:5, $($ticks)=[1,2]).subplots[1]
Subplot{1}
julia> $($f)(sp)
([1.0, 2.0], ["1", "2"])
```
"""
$f(sp::Subplot) = get_ticks(sp, $(Meta.quot(l)))
export $f
end
end
# get_ticks from axis symbol :x, :y, or :z
get_ticks(sp::Subplot, s::Symbol) = get_ticks(sp, sp[get_attr_symbol(s, :axis)])
get_ticks(p::Plot, s::Symbol) = [get_ticks(sp, s) for sp in p.subplots]
function get_ticks(ticks::Symbol, cvals::T, dvals, args...) where {T}
if ticks === :none if ticks === :none
return T[], String[] return T[], String[]
elseif !isempty(dvals) elseif !isempty(dvals)
@ -254,47 +323,71 @@ end
get_ticks(ticks::AVec, cvals, dvals, args...) = optimal_ticks_and_labels(ticks, args...) get_ticks(ticks::AVec, cvals, dvals, args...) = optimal_ticks_and_labels(ticks, args...)
function get_ticks(ticks::Int, dvals, cvals, args...) function get_ticks(ticks::Int, dvals, cvals, args...)
if !isempty(dvals) if !isempty(dvals)
rng = round.(Int, range(1, stop=length(dvals), length=ticks)) rng = round.(Int, range(1, stop = length(dvals), length = ticks))
cvals[rng], string.(dvals[rng]) cvals[rng], string.(dvals[rng])
else else
optimal_ticks_and_labels(ticks, args...) optimal_ticks_and_labels(ticks, args...)
end end
end end
get_ticks(ticks::NTuple{2, Any}, args...) = ticks get_ticks(ticks::NTuple{2,Any}, args...) = ticks
get_ticks(::Nothing, cvals::T, args...) where T = T[], String[] get_ticks(::Nothing, cvals::T, args...) where {T} = T[], String[]
get_ticks(ticks::Bool, args...) = get_ticks(ticks::Bool, args...) =
ticks ? get_ticks(:auto, args...) : get_ticks(nothing, args...) ticks ? get_ticks(:auto, args...) : get_ticks(nothing, args...)
get_ticks(::T, args...) where T = error("Unknown ticks type in get_ticks: $T") get_ticks(::T, args...) where {T} = error("Unknown ticks type in get_ticks: $T")
_transform_ticks(ticks) = ticks _transform_ticks(ticks) = ticks
_transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.value.(ticks) _transform_ticks(ticks::AbstractArray{T}) where {T<:Dates.TimeType} = Dates.value.(ticks)
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2]) _transform_ticks(ticks::NTuple{2,Any}) = (_transform_ticks(ticks[1]), ticks[2])
function get_minor_ticks(sp, axis, ticks) function get_minor_ticks(sp, axis, ticks)
axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing axis[:minorticks] (:none, nothing, false) && !axis[:minorgrid] && return nothing
ticks = ticks[1] ticks = ticks[1]
length(ticks) < 2 && return nothing length(ticks) < 2 && return nothing
amin, amax = axis_limits(sp, axis[:letter]) amin, amax = axis_limits(sp, axis[:letter])
#Add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits scale = axis[:scale]
if length(ticks) > 2 log_scaled = scale _logScales
ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1]) base = get(_logScaleBases, scale, nothing)
elseif axis[:scale] in (:none, :identity)
ratio = 1 # add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits
else if log_scaled
return nothing sub = round(Int, log(base, ticks[2] / ticks[1]))
end ticks = [ticks[1] / base; ticks; ticks[end] * base]
first_step = ticks[2] - ticks[1] else
last_step = ticks[end] - ticks[end-1] sub = 1 # unused
ticks = [ticks[1] - first_step/ratio; ticks; ticks[end] + last_step*ratio] ratio = length(ticks) > 2 ? (ticks[3] - ticks[2]) / (ticks[2] - ticks[1]) : 1
first_step = ticks[2] - ticks[1]
last_step = ticks[end] - ticks[end - 1]
ticks = [ticks[1] - first_step / ratio; ticks; ticks[end] + last_step * ratio]
end
# default to 9 intervals between major ticks for log10 scale and 5 intervals otherwise
n_default = (scale == :log10) ? 9 : 5
n =
typeof(axis[:minorticks]) <: Integer && axis[:minorticks] > 1 ? axis[:minorticks] :
n_default
#Default to 5 intervals between major ticks
n = typeof(axis[:minorticks]) <: Integer && axis[:minorticks] > 1 ? axis[:minorticks] : 5
minorticks = typeof(ticks[1])[] minorticks = typeof(ticks[1])[]
for (i,hi) in enumerate(ticks[2:end]) for (i, hi) in enumerate(ticks[2:end])
lo = ticks[i] lo = ticks[i]
if isfinite(lo) && isfinite(hi) && hi > lo if isfinite(lo) && isfinite(hi) && hi > lo
append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n)) if log_scaled
for e in 1:sub
lo_ = lo * base^(e - 1)
hi_ = lo_ * base
step = (hi_ - lo_) / n
append!(
minorticks,
collect(
(lo_ + (e > 1 ? 0 : step)):step:(hi_ - (e < sub ? 0 :
step / 2)),
),
)
end
else
step = (hi - lo) / n
append!(minorticks, collect((lo + step):step:(hi - step / 2)))
end
end end
end end
minorticks[amin .<= minorticks .<= amax] minorticks[amin .<= minorticks .<= amax]
@ -302,17 +395,15 @@ end
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
function reset_extrema!(sp::Subplot) function reset_extrema!(sp::Subplot)
for asym in (:x,:y,:z) for asym in (:x, :y, :z)
sp[Symbol(asym,:axis)][:extrema] = Extrema() sp[get_attr_symbol(asym, :axis)][:extrema] = Extrema()
end end
for series in sp.series_list for series in sp.series_list
expand_extrema!(sp, series.plotattributes) expand_extrema!(sp, series.plotattributes)
end end
end end
function expand_extrema!(ex::Extrema, v::Number) function expand_extrema!(ex::Extrema, v::Number)
ex.emin = isfinite(v) ? min(v, ex.emin) : ex.emin ex.emin = isfinite(v) ? min(v, ex.emin) : ex.emin
ex.emax = isfinite(v) ? max(v, ex.emax) : ex.emax ex.emax = isfinite(v) ? max(v, ex.emax) : ex.emax
@ -327,14 +418,13 @@ end
expand_extrema!(axis::Axis, ::Nothing) = axis[:extrema] expand_extrema!(axis::Axis, ::Nothing) = axis[:extrema]
expand_extrema!(axis::Axis, ::Bool) = axis[:extrema] expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number} function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number}
ex = axis[:extrema] ex = axis[:extrema]
ex.emin = isfinite(v[1]) ? min(v[1], ex.emin) : ex.emin ex.emin = isfinite(v[1]) ? min(v[1], ex.emin) : ex.emin
ex.emax = isfinite(v[2]) ? max(v[2], ex.emax) : ex.emax ex.emax = isfinite(v[2]) ? max(v[2], ex.emax) : ex.emax
ex ex
end end
function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number function expand_extrema!(axis::Axis, v::AVec{N}) where {N<:Number}
ex = axis[:extrema] ex = axis[:extrema]
for vi in v for vi in v
expand_extrema!(ex, vi) expand_extrema!(ex, vi)
@ -342,7 +432,6 @@ function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
ex ex
end end
function expand_extrema!(sp::Subplot, plotattributes::AKW) function expand_extrema!(sp::Subplot, plotattributes::AKW)
vert = isvertical(plotattributes) vert = isvertical(plotattributes)
@ -353,16 +442,22 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
else else
letter == :x ? :y : letter == :y ? :x : :z letter == :x ? :y : letter == :y ? :x : :z
end] end]
if letter != :z && plotattributes[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2] if (
letter != :z &&
plotattributes[:seriestype] == :straightline &&
any(series[:seriestype] != :straightline for series in series_list(sp)) &&
data[1] != data[2]
)
data = [NaN] data = [NaN]
end end
axis = sp[Symbol(letter, "axis")] axis = sp[get_attr_symbol(letter, :axis)]
if isa(data, Volume) if isa(data, Volume)
expand_extrema!(sp[:xaxis], data.x_extents) expand_extrema!(sp[:xaxis], data.x_extents)
expand_extrema!(sp[:yaxis], data.y_extents) expand_extrema!(sp[:yaxis], data.y_extents)
expand_extrema!(sp[:zaxis], data.z_extents) expand_extrema!(sp[:zaxis], data.z_extents)
elseif eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf)) elseif eltype(data) <: Number ||
(isa(data, Surface) && all(di -> isa(di, Number), data.surf))
if !(eltype(data) <: Number) if !(eltype(data) <: Number)
# huh... must have been a mis-typed surface? lets swap it out # huh... must have been a mis-typed surface? lets swap it out
data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf)) data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
@ -372,7 +467,9 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
# TODO: need more here... gotta track the discrete reference value # TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all # as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value) # correspond to the same x-value)
plotattributes[letter], plotattributes[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data) plotattributes[letter],
plotattributes[get_attr_symbol(letter, :(_discrete_indices))] =
discrete_value!(axis, data)
expand_extrema!(axis, plotattributes[letter]) expand_extrema!(axis, plotattributes[letter])
end end
end end
@ -406,9 +503,11 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
bw = plotattributes[:bar_width] bw = plotattributes[:bar_width]
if bw === nothing if bw === nothing
bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data)))) bw =
plotattributes[:bar_width] =
_bar_width * ignorenan_minimum(filter(x -> x > 0, diff(sort(data))))
end end
axis = sp.attr[Symbol(dsym, :axis)] axis = sp.attr[get_attr_symbol(dsym, :axis)]
expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw)) expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw)) expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
end end
@ -417,8 +516,8 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
if plotattributes[:seriestype] == :heatmap if plotattributes[:seriestype] == :heatmap
for letter in (:x, :y) for letter in (:x, :y)
data = plotattributes[letter] data = plotattributes[letter]
axis = sp[Symbol(letter, "axis")] axis = sp[get_attr_symbol(letter, :axis)]
scale = get(plotattributes, Symbol(letter, "scale"), :identity) scale = get(plotattributes, get_attr_symbol(letter, :scale), :identity)
expand_extrema!(axis, heatmap_edges(data, scale)) expand_extrema!(axis, heatmap_edges(data, scale))
end end
end end
@ -437,49 +536,85 @@ function widen(lmin, lmax, scale = :identity)
span = f(lmax) - f(lmin) span = f(lmax) - f(lmin)
# eps = NaNMath.max(1e-16, min(1e-2span, 1e-10)) # eps = NaNMath.max(1e-16, min(1e-2span, 1e-10))
eps = NaNMath.max(1e-16, 0.03span) eps = NaNMath.max(1e-16, 0.03span)
invf(f(lmin)-eps), invf(f(lmax)+eps) invf(f(lmin) - eps), invf(f(lmax) + eps)
end end
# figure out if widening is a good idea. # figure out if widening is a good idea.
const _widen_seriestypes = (:line, :path, :steppre, :stepmid, :steppost, :sticks, :scatter, :barbins, :barhist, :histogram, :scatterbins, :scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :bar, :shape, :path3d, :scatter3d) const _widen_seriestypes = (
:line,
:path,
:steppre,
:stepmid,
:steppost,
:sticks,
:scatter,
:barbins,
:barhist,
:histogram,
:scatterbins,
:scatterhist,
:stepbins,
:stephist,
:bins2d,
:histogram2d,
:bar,
:shape,
:path3d,
:scatter3d,
)
function default_should_widen(axis::Axis) function default_should_widen(axis::Axis)
should_widen = false if axis[:widen] isa Bool
if !(is_2tuple(axis[:lims]) || axis[:lims] == :round) return axis[:widen]
for sp in axis.sps end
for series in series_list(sp) # automatic behavior: widen if limits aren't specified and series type is appropriate
if series.plotattributes[:seriestype] in _widen_seriestypes (is_2tuple(axis[:lims]) || axis[:lims] == :round) && return false
should_widen = true for sp in axis.sps
end for series in series_list(sp)
if series.plotattributes[:seriestype] in _widen_seriestypes
return true
end end
end end
end end
should_widen false
end end
function round_limits(amin,amax) function round_limits(amin, amax, scale)
scale = 10^(1-round(log10(amax - amin))) base = get(_logScaleBases, scale, 10.0)
amin = floor(amin*scale)/scale factor = base^(1 - round(log(base, amax - amin)))
amax = ceil(amax*scale)/scale amin = floor(amin * factor) / factor
amax = ceil(amax * factor) / factor
amin, amax amin, amax
end end
# using the axis extrema and limit overrides, return the min/max value for this axis # using the axis extrema and limit overrides, return the min/max value for this axis
function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(letter, :axis)]), consider_aspect = true) function axis_limits(
axis = sp[Symbol(letter, :axis)] sp,
letter,
should_widen = default_should_widen(sp[get_attr_symbol(letter, :axis)]),
consider_aspect = true,
)
axis = sp[get_attr_symbol(letter, :axis)]
ex = axis[:extrema] ex = axis[:extrema]
amin, amax = ex.emin, ex.emax amin, amax = ex.emin, ex.emax
lims = axis[:lims] lims = axis[:lims]
has_user_lims = (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2 has_user_lims = (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2
if has_user_lims if has_user_lims
lmin, lmax = lims lmin, lmax = lims
if lmin != :auto && isfinite(lmin) if lmin == :auto
elseif isfinite(lmin)
amin = lmin amin = lmin
end end
if lmax != :auto && isfinite(lmax) if lmax == :auto
elseif isfinite(lmax)
amax = lmax amax = lmax
end end
end end
if lims == :symmetric
aval = max(abs(amin), abs(amax))
amin = -aval
amax = aval
end
if amax <= amin && isfinite(amin) if amax <= amin && isfinite(amin)
amax = amin + 1.0 amax = amin + 1.0
end end
@ -490,20 +625,25 @@ function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(l
if axis[:letter] == :x if axis[:letter] == :x
amin, amax = 0, 2pi amin, amax = 0, 2pi
elseif lims == :auto elseif lims == :auto
#widen max radius so ticks dont overlap with theta axis # widen max radius so ticks dont overlap with theta axis
0, amax + 0.1 * abs(amax - amin) 0, amax + 0.1 * abs(amax - amin)
else else
amin, amax amin, amax
end end
elseif should_widen && axis[:widen] elseif should_widen
widen(amin, amax, axis[:scale]) widen(amin, amax, axis[:scale])
elseif lims == :round elseif lims == :round
round_limits(amin,amax) round_limits(amin, amax, axis[:scale])
else else
amin, amax amin, amax
end end
if !has_user_lims && consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || RecipesPipeline.is3d(:sp)) if (
!has_user_lims &&
consider_aspect &&
letter in (:x, :y) &&
!(sp[:aspect_ratio] in (:none, :auto) || RecipesPipeline.is3d(:sp))
)
aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1 aspect_ratio = isa(sp[:aspect_ratio], Number) ? sp[:aspect_ratio] : 1
plot_ratio = height(plotarea(sp)) / width(plotarea(sp)) plot_ratio = height(plotarea(sp)) / width(plotarea(sp))
dist = amax - amin dist = amax - amin
@ -535,9 +675,17 @@ end
# these methods track the discrete (categorical) values which correspond to axis continuous values (cv) # these methods track the discrete (categorical) values which correspond to axis continuous values (cv)
# whenever we have discrete values, we automatically set the ticks to match. # whenever we have discrete values, we automatically set the ticks to match.
# we return (continuous_value, discrete_index) # we return (continuous_value, discrete_index)
function discrete_value!(plotattributes, letter::Symbol, dv)
l = if plotattributes[:permute] !== :none
only(filter(!=(letter), plotattributes[:permute]))
else
letter
end
discrete_value!(plotattributes[:subplot][get_attr_symbol(l, :axis)], dv)
end
function discrete_value!(axis::Axis, dv) function discrete_value!(axis::Axis, dv)
cv_idx = get(axis[:discrete_map], dv, -1) cv_idx = get(axis[:discrete_map], dv, -1)
# @show axis[:discrete_map], axis[:discrete_values], dv
if cv_idx == -1 if cv_idx == -1
ex = axis[:extrema] ex = axis[:extrema]
cv = NaNMath.max(0.5, ex.emax + 1.0) cv = NaNMath.max(0.5, ex.emax + 1.0)
@ -571,11 +719,11 @@ end
# add the discrete value for each item. return the continuous values and the indices # add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AMat) function discrete_value!(axis::Axis, v::AMat)
n,m = axes(v) n, m = axes(v)
cmat = zeros(axes(v)) cmat = zeros(axes(v))
discrete_indices = similar(Array{Int}, axes(v)) discrete_indices = similar(Array{Int}, axes(v))
for i in n, j in m for i in n, j in m
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j]) cmat[i, j], discrete_indices[i, j] = discrete_value!(axis, v[i, j])
end end
cmat, discrete_indices cmat, discrete_indices
end end
@ -589,10 +737,10 @@ end
# compute the line segments which should be drawn for this axis # compute the line segments which should be drawn for this axis
function axis_drawing_info(sp, letter) function axis_drawing_info(sp, letter)
# find out which axis we are dealing with # find out which axis we are dealing with
asym = Symbol(letter, :axis) asym = get_attr_symbol(letter, :axis)
isy = letter === :y isy = letter === :y
oletter = isy ? :x : :y oletter = isy ? :x : :y
oasym = Symbol(oletter, :axis) oasym = get_attr_symbol(oletter, :axis)
# get axis objects, ticks and minor ticks # get axis objects, ticks and minor ticks
ax, oax = sp[asym], sp[oasym] ax, oax = sp[asym], sp[oasym]
@ -618,7 +766,11 @@ function axis_drawing_info(sp, letter)
if sp[:framestyle] != :grid if sp[:framestyle] != :grid
push!(segments, reverse_if((amin, oa1), isy), reverse_if((amax, oa1), isy)) push!(segments, reverse_if((amin, oa1), isy), reverse_if((amax, oa1), isy))
# don't show the 0 tick label for the origin framestyle # don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(ticks in (:none, nothing, false)) && length(ticks) > 1 if (
sp[:framestyle] == :origin &&
!(ticks in (:none, nothing, false)) &&
length(ticks) > 1
)
i = findfirst(==(0), ticks[1]) i = findfirst(==(0), ticks[1])
if i !== nothing if i !== nothing
deleteat!(ticks[1], i) deleteat!(ticks[1], i)
@ -634,60 +786,62 @@ function axis_drawing_info(sp, letter)
) )
end end
end end
if !(ax[:ticks] in (:none, nothing, false)) if ax[:ticks] (:none, nothing, false)
f = RecipesPipeline.scale_func(oax[:scale]) f = RecipesPipeline.scale_func(oax[:scale])
invf = RecipesPipeline.inverse_scale_func(oax[:scale]) invf = RecipesPipeline.inverse_scale_func(oax[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(oamax) - f(oamin)))
(-t, t)
else
ticks_in = ax[:tick_direction] == :out ? -1 : 1
t = invf(f(oa1) + 0.012 * (f(oa2) - f(oa1)) * ticks_in)
(oa1, t)
end
for tick in ticks[1] add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin
if ax[:showaxis] ticks === nothing && return
push!( if cond
tick_segments, tick_start, tick_stop = if sp[:framestyle] == :origin
reverse_if((tick, tick_start), isy), t = invf(f(0) + factor * (f(oamax) - f(oamin)))
reverse_if((tick, tick_stop), isy), (-t, t)
) else
ticks_in = ax[:tick_direction] == :out ? -1 : 1
t = invf(f(oa1) + factor * (f(oa2) - f(oa1)) * ticks_in)
(oa1, t)
end
end end
if ax[:grid]
push!(
grid_segments,
reverse_if((tick, oamin), isy),
reverse_if((tick, oamax), isy),
)
end
end
if !(ax[:minorticks] in (:none, nothing, false)) || ax[:minorgrid] for tick in ticks
tick_start, tick_stop = if sp[:framestyle] == :origin if ax[:showaxis] && cond
t = invf(f(0) + 0.006 * (f(oamax) - f(oamin)))
(-t, t)
else
t = invf(f(oa1) + 0.006 * (f(oa2) - f(oa1)) * ticks_in)
(oa1, t)
end
for tick in minor_ticks
if ax[:showaxis]
push!( push!(
tick_segments, tick_segments,
reverse_if((tick, tick_start), isy), reverse_if((tick, tick_start), isy),
reverse_if((tick, tick_stop), isy), reverse_if((tick, tick_stop), isy),
) )
end end
if ax[:minorgrid] if grid
push!( push!(
minorgrid_segments, segments,
reverse_if((tick, oamin), isy), reverse_if((tick, oamin), isy),
reverse_if((tick, oamax), isy), reverse_if((tick, oamax), isy),
) )
end end
end end
end end
ax_length = letter === :x ? height(sp.plotarea).value : width(sp.plotarea).value
# add major grid segments
add_major_or_minor_segments(
ticks[1],
ax[:grid],
grid_segments,
1.2 / ax_length,
ax[:tick_direction] !== :none,
)
# add minor grid segments
if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid]
add_major_or_minor_segments(
minor_ticks,
ax[:minorgrid],
minorgrid_segments,
0.6 / ax_length,
true,
)
end
end end
end end
@ -697,7 +851,7 @@ function axis_drawing_info(sp, letter)
tick_segments = tick_segments, tick_segments = tick_segments,
grid_segments = grid_segments, grid_segments = grid_segments,
minorgrid_segments = minorgrid_segments, minorgrid_segments = minorgrid_segments,
border_segments = border_segments border_segments = border_segments,
) )
end end
@ -715,9 +869,9 @@ function axis_drawing_info_3d(sp, letter)
near_letter = letter in (:x, :z) ? :y : :x near_letter = letter in (:x, :z) ? :y : :x
far_letter = letter in (:x, :y) ? :z : :x far_letter = letter in (:x, :y) ? :z : :x
ax = sp[Symbol(letter, :axis)] ax = sp[get_attr_symbol(letter, :axis)]
nax = sp[Symbol(near_letter, :axis)] nax = sp[get_attr_symbol(near_letter, :axis)]
fax = sp[Symbol(far_letter, :axis)] fax = sp[get_attr_symbol(far_letter, :axis)]
amin, amax = axis_limits(sp, letter) amin, amax = axis_limits(sp, letter)
namin, namax = axis_limits(sp, near_letter) namin, namax = axis_limits(sp, near_letter)
@ -733,8 +887,7 @@ function axis_drawing_info_3d(sp, letter)
minorgrid_segments = Segments(3) minorgrid_segments = Segments(3)
border_segments = Segments(3) border_segments = Segments(3)
if sp[:framestyle] != :none # && letter === :x
if sp[:framestyle] != :none# && letter === :x
na0, na1 = if sp[:framestyle] in (:origin, :zerolines) na0, na1 = if sp[:framestyle] in (:origin, :zerolines)
0, 0 0, 0
else else
@ -754,7 +907,11 @@ function axis_drawing_info_3d(sp, letter)
sort_3d_axes(amax, na0, fa0, letter), sort_3d_axes(amax, na0, fa0, letter),
) )
# don't show the 0 tick label for the origin framestyle # don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(ticks in (:none, nothing, false)) && length(ticks) > 1 if (
sp[:framestyle] == :origin &&
!(ticks in (:none, nothing, false)) &&
length(ticks) > 1
)
i0 = findfirst(==(0), ticks[1]) i0 = findfirst(==(0), ticks[1])
if i0 !== nothing if i0 !== nothing
deleteat!(ticks[1], i0) deleteat!(ticks[1], i0)
@ -770,72 +927,70 @@ function axis_drawing_info_3d(sp, letter)
) )
end end
end end
# TODO this can be simplified, we do almost the same thing twice for grid and minorgrid
if !(ax[:ticks] in (:none, nothing, false)) if ax[:ticks] (:none, nothing, false)
f = RecipesPipeline.scale_func(nax[:scale]) f = RecipesPipeline.scale_func(nax[:scale])
invf = RecipesPipeline.inverse_scale_func(nax[:scale]) invf = RecipesPipeline.inverse_scale_func(nax[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin ga0, ga1 =
t = invf(f(0) + 0.012 * (f(namax) - f(namin))) sp[:framestyle] in (:origin, :zerolines) ? (namin, namax) : (na0, na1)
(-t, t)
else
ticks_in = ax[:tick_direction] == :out ? -1 : 1
t = invf(f(na0) + 0.012 * (f(na1) - f(na0)) * ticks_in)
(na0, t)
end
ga0, ga1 = sp[:framestyle] in (:origin, :zerolines) ? (namin, namax) : (na0, na1) add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin
for tick in ticks[1] ticks === nothing && return
if ax[:showaxis] if cond
push!( tick_start, tick_stop = if sp[:framestyle] == :origin
tick_segments, t = invf(f(0) + factor * (f(namax) - f(namin)))
sort_3d_axes(tick, tick_start, fa0, letter), (-t, t)
sort_3d_axes(tick, tick_stop, fa0, letter), else
) ticks_in = ax[:tick_direction] == :out ? -1 : 1
t = invf(f(na0) + factor * (f(na1) - f(na0)) * ticks_in)
(na0, t)
end
end end
if ax[:grid]
push!(
grid_segments,
sort_3d_axes(tick, ga0, fa0, letter),
sort_3d_axes(tick, ga1, fa0, letter),
)
push!(
grid_segments,
sort_3d_axes(tick, ga1, fa0, letter),
sort_3d_axes(tick, ga1, fa1, letter),
)
end
end
if !(ax[:minorticks] in (:none, nothing, false)) || ax[:minorgrid] for tick in ticks
tick_start, tick_stop = if sp[:framestyle] == :origin if ax[:showaxis] && cond
t = invf(f(0) + 0.006 * (f(namax) - f(namin)))
(-t, t)
else
t = invf(f(na0) + 0.006 * (f(na1) - f(na0)) * ticks_in)
(na0, t)
end
for tick in minor_ticks
if ax[:showaxis]
push!( push!(
tick_segments, tick_segments,
sort_3d_axes(tick, tick_start, fa0, letter), sort_3d_axes(tick, tick_start, fa0, letter),
sort_3d_axes(tick, tick_stop, fa0, letter), sort_3d_axes(tick, tick_stop, fa0, letter),
) )
end end
if ax[:minorgrid] if grid
fa0_, fa1_ = reverse_if((fa0, fa1), ax[:mirror])
ga0_, ga1_ = reverse_if((ga0, ga1), ax[:mirror])
push!( push!(
minorgrid_segments, segments,
sort_3d_axes(tick, ga0, fa0, letter), sort_3d_axes(tick, ga0_, fa0_, letter),
sort_3d_axes(tick, ga1, fa0, letter), sort_3d_axes(tick, ga1_, fa0_, letter),
) )
push!( push!(
minorgrid_segments, segments,
sort_3d_axes(tick, ga1, fa0, letter), sort_3d_axes(tick, ga1_, fa0_, letter),
sort_3d_axes(tick, ga1, fa1, letter), sort_3d_axes(tick, ga1_, fa1_, letter),
) )
end end
end end
end end
# add major grid segments
add_major_or_minor_segments(
ticks[1],
ax[:grid],
grid_segments,
0.012,
ax[:tick_direction] !== :none,
)
# add minor grid segments
if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid]
add_major_or_minor_segments(
minor_ticks,
ax[:minorgrid],
minorgrid_segments,
0.006,
true,
)
end
end end
end end
@ -845,7 +1000,7 @@ function axis_drawing_info_3d(sp, letter)
tick_segments = tick_segments, tick_segments = tick_segments,
grid_segments = grid_segments, grid_segments = grid_segments,
minorgrid_segments = minorgrid_segments, minorgrid_segments = minorgrid_segments,
border_segments = border_segments border_segments = border_segments,
) )
end end

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
# significant contributions by: @pkofod # significant contributions by: @pkofod
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
# COV_EXCL_START
const _pgfplots_linestyles = KW( const _pgfplots_linestyles = KW(
:solid => "solid", :solid => "solid",
:dash => "dashed", :dash => "dashed",
@ -27,7 +27,7 @@ const _pgfplots_markers = KW(
:diamond => "diamond*", :diamond => "diamond*",
:pentagon => "pentagon*", :pentagon => "pentagon*",
:hline => "-", :hline => "-",
:vline => "|" :vline => "|",
) )
const _pgfplots_legend_pos = KW( const _pgfplots_legend_pos = KW(
@ -38,7 +38,6 @@ const _pgfplots_legend_pos = KW(
:outertopright => "outer north east", :outertopright => "outer north east",
) )
const _pgf_series_extrastyle = KW( const _pgf_series_extrastyle = KW(
:steppre => "const plot mark right", :steppre => "const plot mark right",
:stepmid => "const plot mark mid", :stepmid => "const plot mark mid",
@ -50,11 +49,7 @@ const _pgf_series_extrastyle = KW(
# PGFPlots uses the anchors to define orientations for example to align left # PGFPlots uses the anchors to define orientations for example to align left
# one needs to use the right edge as anchor # one needs to use the right edge as anchor
const _pgf_annotation_halign = KW( const _pgf_annotation_halign = KW(:center => "", :left => "right", :right => "left")
:center => "",
:left => "right",
:right => "left"
)
const _pgf_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none] const _pgf_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none]
const _pgf_framestyle_defaults = Dict(:semi => :box) const _pgf_framestyle_defaults = Dict(:semi => :box)
@ -63,7 +58,9 @@ function pgf_framestyle(style::Symbol)
return style return style
else else
default_style = get(_pgf_framestyle_defaults, style, :axes) default_style = get(_pgf_framestyle_defaults, style, :axes)
@warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.") @warn(
"Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead."
)
default_style default_style
end end
end end
@ -78,15 +75,15 @@ end
function pgf_color(grad::ColorGradient) function pgf_color(grad::ColorGradient)
# Can't handle ColorGradient here, fallback to defaults. # Can't handle ColorGradient here, fallback to defaults.
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012) cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316, 0.97868012)
cstr, 1 cstr, 1
end end
# Generates a colormap for pgfplots based on a ColorGradient # Generates a colormap for pgfplots based on a ColorGradient
function pgf_colormap(grad::ColorGradient) function pgf_colormap(grad::ColorGradient)
join(map(grad.colors) do c join(map(grad.colors) do c
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c)) @sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c), blue(c))
end,", ") end, ", ")
end end
pgf_thickness_scaling(plt::Plot) = plt[:thickness_scaling] pgf_thickness_scaling(plt::Plot) = plt[:thickness_scaling]
@ -94,7 +91,7 @@ pgf_thickness_scaling(sp::Subplot) = pgf_thickness_scaling(sp.plt)
pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot]) pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(plotattributes, i = 1) function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(plotattributes, i)) cstr, a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(plotattributes, i) fa = get_fillalpha(plotattributes, i)
if fa !== nothing if fa !== nothing
a = fa a = fa
@ -126,8 +123,15 @@ end
function pgf_marker(plotattributes, i = 1) function pgf_marker(plotattributes, i = 1)
shape = _cycle(plotattributes[:markershape], i) shape = _cycle(plotattributes[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i))) cstr, a = pgf_color(
cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i))) plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i)),
)
cstr_stroke, a_stroke = pgf_color(
plot_color(
get_markerstrokecolor(plotattributes, i),
get_markerstrokealpha(plotattributes, i),
),
)
return string( return string(
"mark = $(get(_pgfplots_markers, shape, "*")),\n", "mark = $(get(_pgfplots_markers, shape, "*")),\n",
"mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),\n", "mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),\n",
@ -138,22 +142,28 @@ function pgf_marker(plotattributes, i = 1)
line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)), line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0), rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid")) $(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
}" }",
) )
end end
function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1) function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1)
# Construct the style string. # Construct the style string.
# Currently supports color and orientation # Currently supports color and orientation
cstr,a = pgf_color(val.font.color) cstr, a = pgf_color(val.font.color)
push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text push!(
x, y, o,
style=""" PGFPlots.Plots.Node(
$(get(_pgf_annotation_halign,val.font.halign,"")), val.str, # Annotation Text
color=$cstr, draw opacity=$(convert(Float16,a)), x,
rotate=$(val.font.rotation), y,
font=$(pgf_font(val.font.pointsize, thickness_scaling)) style = """
""")) $(get(_pgf_annotation_halign,val.font.halign,"")),
color=$cstr, draw opacity=$(convert(Float16,a)),
rotate=$(val.font.rotation),
font=$(pgf_font(val.font.pointsize, thickness_scaling))
""",
),
)
end end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
@ -217,7 +227,7 @@ function pgf_series(sp::Subplot, series::Series)
end end
# add to legend? # 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 if plotattributes[:fillrange] !== nothing
push!(style, "forget plot") push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args)) push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
@ -241,7 +251,15 @@ function pgf_series(sp::Subplot, series::Series)
# add fillrange # add fillrange
if series[:fillrange] !== nothing && st != :shape if series[:fillrange] !== nothing && st != :shape
push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...)) push!(
series_collection,
pgf_fillrange_series(
series,
i,
_cycle(series[:fillrange], rng),
seg_args...,
),
)
end end
# build/return the series object # build/return the series object
@ -313,7 +331,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function pgf_axis(sp::Subplot, letter) function pgf_axis(sp::Subplot, letter)
axis = sp[Symbol(letter,:axis)] axis = sp[get_attr_symbol(letter, :axis)]
style = [] style = []
kw = KW() kw = KW()
@ -324,7 +342,7 @@ function pgf_axis(sp::Subplot, letter)
framestyle = pgf_framestyle(sp[:framestyle]) framestyle = pgf_framestyle(sp[:framestyle])
# axis guide # axis guide
kw[Symbol(letter,:label)] = axis[:guide] kw[get_attr_symbol(letter, :label)] = axis[:guide]
# axis label position # axis label position
labelpos = "" labelpos = ""
@ -336,7 +354,23 @@ function pgf_axis(sp::Subplot, letter)
# Add label font # Add label font
cstr, α = pgf_color(plot_color(axis[:guidefontcolor])) cstr, α = pgf_color(plot_color(axis[:guidefontcolor]))
push!(style, string(letter, "label style = {", labelpos ,"font = ", pgf_font(axis[:guidefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:guidefontrotation], "}")) push!(
style,
string(
letter,
"label style = {",
labelpos,
"font = ",
pgf_font(axis[:guidefontsize], pgf_thickness_scaling(sp)),
", color = ",
cstr,
", draw opacity = ",
α,
", rotate = ",
axis[:guidefontrotation],
"}",
),
)
# flip/reverse? # flip/reverse?
axis[:flip] && push!(style, "$letter dir=reverse") axis[:flip] && push!(style, "$letter dir=reverse")
@ -344,7 +378,7 @@ function pgf_axis(sp::Subplot, letter)
# scale # scale
scale = axis[:scale] scale = axis[:scale]
if scale in (:log2, :ln, :log10) if scale in (:log2, :ln, :log10)
kw[Symbol(letter,:mode)] = "log" kw[get_attr_symbol(letter, :mode)] = "log"
scale == :ln || push!(style, "log basis $letter=$(scale == :log2 ? 2 : 10)") scale == :ln || push!(style, "log basis $letter=$(scale == :log2 ? 2 : 10)")
end end
@ -363,16 +397,20 @@ function pgf_axis(sp::Subplot, letter)
# limits # limits
# TODO: support zlims # TODO: support zlims
if letter != :z if letter != :z
lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, letter) lims =
kw[Symbol(letter,:min)] = lims[1] ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) :
kw[Symbol(letter,:max)] = lims[2] axis_limits(sp, letter)
kw[get_attr_symbol(letter, :min)] = lims[1]
kw[get_attr_symbol(letter, :max)] = lims[2]
end end
if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none
ticks = get_ticks(sp, axis) ticks = get_ticks(sp, axis)
#pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values #pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values
tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1] tick_values =
push!(style, string(letter, "tick = {", join(tick_values,","), "}")) ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] :
ticks[1]
push!(style, string(letter, "tick = {", join(tick_values, ","), "}"))
if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
# wrap the power part of label with } # wrap the power part of label with }
tick_labels = Vector{String}(undef, length(ticks[2])) tick_labels = Vector{String}(undef, length(ticks[2]))
@ -381,21 +419,59 @@ function pgf_axis(sp::Subplot, letter)
power = string("{", power, "}") power = string("{", power, "}")
tick_labels[i] = string(base, "^", power) tick_labels[i] = string(base, "^", power)
end end
push!(style, string(letter, "ticklabels = {\$", join(tick_labels,"\$,\$"), "\$}")) push!(
style,
string(letter, "ticklabels = {\$", join(tick_labels, "\$,\$"), "\$}"),
)
elseif axis[:showaxis] elseif axis[:showaxis]
tick_labels = ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2] tick_labels =
ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
if axis[:formatter] in (:scientific, :auto) if axis[:formatter] in (:scientific, :auto)
tick_labels = string.("\$", convert_sci_unicode.(tick_labels), "\$") tick_labels = string.("\$", convert_sci_unicode.(tick_labels), "\$")
tick_labels = replace.(tick_labels, Ref("×" => "\\times")) tick_labels = replace.(tick_labels, Ref("×" => "\\times"))
end end
push!(style, string(letter, "ticklabels = {", join(tick_labels,","), "}")) push!(style, string(letter, "ticklabels = {", join(tick_labels, ","), "}"))
else else
push!(style, string(letter, "ticklabels = {}")) push!(style, string(letter, "ticklabels = {}"))
end end
push!(style, string(letter, "tick align = ", (axis[:tick_direction] == :out ? "outside" : "inside"))) push!(
style,
string(
letter,
"tick align = ",
(axis[:tick_direction] == :out ? "outside" : "inside"),
),
)
cstr, α = pgf_color(plot_color(axis[:tickfontcolor])) cstr, α = pgf_color(plot_color(axis[:tickfontcolor]))
push!(style, string(letter, "ticklabel style = {font = ", pgf_font(axis[:tickfontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:tickfontrotation], "}")) push!(
push!(style, string(letter, " grid style = {", pgf_linestyle(pgf_thickness_scaling(sp) * axis[:gridlinewidth], axis[:foreground_color_grid], axis[:gridalpha], axis[:gridstyle]), "}")) style,
string(
letter,
"ticklabel style = {font = ",
pgf_font(axis[:tickfontsize], pgf_thickness_scaling(sp)),
", color = ",
cstr,
", draw opacity = ",
α,
", rotate = ",
axis[:tickfontrotation],
"}",
),
)
push!(
style,
string(
letter,
" grid style = {",
pgf_linestyle(
pgf_thickness_scaling(sp) * axis[:gridlinewidth],
axis[:foreground_color_grid],
axis[:gridalpha],
axis[:gridstyle],
),
"}",
),
)
end end
# framestyle # framestyle
@ -412,7 +488,20 @@ function pgf_axis(sp::Subplot, letter)
if framestyle == :zerolines if framestyle == :zerolines
push!(style, string("extra ", letter, " ticks = 0")) push!(style, string("extra ", letter, " ticks = 0"))
push!(style, string("extra ", letter, " tick labels = ")) push!(style, string("extra ", letter, " tick labels = "))
push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}}")) push!(
style,
string(
"extra ",
letter,
" tick style = {grid = major, major grid style = {",
pgf_linestyle(
pgf_thickness_scaling(sp),
axis[:foreground_color_border],
1.0,
),
"}}",
),
)
end end
if !axis[:showaxis] if !axis[:showaxis]
@ -421,7 +510,19 @@ function pgf_axis(sp::Subplot, letter)
if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none) if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
push!(style, string(letter, " axis line style = {draw opacity = 0}")) push!(style, string(letter, " axis line style = {draw opacity = 0}"))
else else
push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}")) push!(
style,
string(
letter,
" axis line style = {",
pgf_linestyle(
pgf_thickness_scaling(sp),
axis[:foreground_color_border],
1.0,
),
"}",
),
)
end end
# return the style list and KW args # return the style list and KW args
@ -430,7 +531,6 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function _update_plot_object(plt::Plot{PGFPlotsBackend}) function _update_plot_object(plt::Plot{PGFPlotsBackend})
plt.o = PGFPlots.Axis[] plt.o = PGFPlots.Axis[]
# Obtain the total height of the plot by extracting the maximal bottom # Obtain the total height of the plot by extracting the maximal bottom
@ -438,7 +538,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
total_height = bottom(bbox(plt.layout)) total_height = bottom(bbox(plt.layout))
for sp in plt.subplots for sp in plt.subplots
# first build the PGFPlots.Axis object # first build the PGFPlots.Axis object
style = ["unbounded coords=jump"] style = ["unbounded coords=jump"]
kw = KW() kw = KW()
@ -456,40 +556,66 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
# A round on 2 decimal places should be enough precision for 300 dpi # A round on 2 decimal places should be enough precision for 300 dpi
# plots. # plots.
bb = bbox(sp) bb = bbox(sp)
push!(style, """ push!(
xshift = $(left(bb).value)mm, style,
yshift = $(round((total_height - (bottom(bb))).value, digits=2))mm, """
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])} xshift = $(left(bb).value)mm,
""") yshift = $(round((total_height - (bottom(bb))).value, digits=2))mm,
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
""",
)
kw[:width] = "$(width(bb).value)mm" kw[:width] = "$(width(bb).value)mm"
kw[:height] = "$(height(bb).value)mm" kw[:height] = "$(height(bb).value)mm"
if sp[:title] != "" if sp[:title] != ""
kw[:title] = "$(sp[:title])" kw[:title] = "$(sp[:title])"
cstr, α = pgf_color(plot_color(sp[:titlefontcolor])) cstr, α = pgf_color(plot_color(sp[:titlefontcolor]))
push!(style, string("title style = {font = ", pgf_font(sp[:titlefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", sp[:titlefontrotation], "}")) push!(
style,
string(
"title style = {font = ",
pgf_font(sp[:titlefontsize], pgf_thickness_scaling(sp)),
", color = ",
cstr,
", draw opacity = ",
α,
", rotate = ",
sp[:titlefontrotation],
"}",
),
)
end end
if get_aspect_ratio(sp) in (1, :equal) if get_aspect_ratio(sp) in (1, :equal)
kw[:axisEqual] = "true" kw[:axisEqual] = "true"
end end
legpos = sp[:legend] legpos = sp[:legend_position]
if haskey(_pgfplots_legend_pos, legpos) if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos] kw[:legendPos] = _pgfplots_legend_pos[legpos]
end end
cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend])) cstr, bg_alpha = pgf_color(plot_color(sp[:legend_background_color]))
fg_alpha = alpha(plot_color(sp[:foreground_color_legend])) fg_alpha = alpha(plot_color(sp[:legend_foreground_color]))
push!(style, string( push!(
"legend style = {", style,
pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], fg_alpha, "solid", ), ",", string(
"legend style = {",
pgf_linestyle(
pgf_thickness_scaling(sp),
sp[:legend_foreground_color],
fg_alpha,
"solid",
),
",",
"fill = $cstr,", "fill = $cstr,",
"fill opacity = $bg_alpha,", "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)), "font = ",
"}", pgf_font(sp[:legend_font_pointsize], pgf_thickness_scaling(sp)),
)) "}",
),
)
if any(s[:seriestype] == :contour for s in series_list(sp)) if any(s[:seriestype] == :contour for s in series_list(sp))
kw[:view] = "{0}{90}" kw[:view] = "{0}{90}"
@ -520,7 +646,10 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
for series in series_list(sp) for series in series_list(sp)
for col in (:markercolor, :fillcolor, :linecolor) for col in (:markercolor, :fillcolor, :linecolor)
if typeof(series.plotattributes[col]) == ColorGradient if typeof(series.plotattributes[col]) == ColorGradient
push!(style,"colormap={plots}{$(pgf_colormap(series.plotattributes[col]))}") push!(
style,
"colormap={plots}{$(pgf_colormap(series.plotattributes[col]))}",
)
if sp[:colorbar] == :none if sp[:colorbar] == :none
kw[:colorbar] = "false" kw[:colorbar] = "false"
@ -543,17 +672,26 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
# add series annotations # add series annotations
anns = series[:series_annotations] anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y]) for (xi, yi, str, fnt) in EachAnn(anns, series[:x], series[:y])
pgf_add_annotation!(o, xi, yi, PlotText(str, fnt), pgf_thickness_scaling(series)) pgf_add_annotation!(
o,
xi,
yi,
PlotText(str, fnt),
pgf_thickness_scaling(series),
)
end end
end end
# add the annotations # add the annotations
for ann in sp[:annotations] for ann in sp[:annotations]
pgf_add_annotation!(o, locate_annotation(sp, ann...)..., pgf_thickness_scaling(sp)) pgf_add_annotation!(
o,
locate_annotation(sp, ann...)...,
pgf_thickness_scaling(sp),
)
end end
# add the PGFPlots.Axis to the list # add the PGFPlots.Axis to the list
push!(plt.o, o) push!(plt.o, o)
end end
@ -568,7 +706,7 @@ function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
pgfplt = PGFPlots.plot(plt.o) pgfplt = PGFPlots.plot(plt.o)
# save a pdf # save a pdf
fn = tempname()*".pdf" fn = tempname() * ".pdf"
PGFPlots.save(PGFPlots.PDF(fn), pgfplt) PGFPlots.save(PGFPlots.PDF(fn), pgfplt)
# read it into io # read it into io
@ -579,8 +717,12 @@ function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
end end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend}) function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex" fn = tempname() * ".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone]) PGFPlots.save(
fn,
backend_object(plt),
include_preamble = plt.attr[:tex_output_standalone],
)
write(io, read(open(fn), String)) write(io, read(open(fn), String))
end end
@ -598,3 +740,5 @@ function _display(plt::Plot{PGFPlotsBackend})
# cleanup # cleanup
PGFPlots.cleanup(plt.o) PGFPlots.cleanup(plt.o)
end end
# COV_EXCL_STOP

604
src/backends/gaston.jl Normal file
View File

@ -0,0 +1,604 @@
# https://github.com/mbaz/Gaston.
should_warn_on_unsupported(::GastonBackend) = false
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{GastonBackend})
state_handle = Gaston.nexthandle() # for now all the figures will be kept
plt.o = Gaston.newfigure(state_handle)
end
function _before_layout_calcs(plt::Plot{GastonBackend})
# Initialize all the subplots first
plt.o.subplots = Gaston.SubPlot[]
n1 = n2 = 0
if length(plt.inset_subplots) > 0
n1, sps = gaston_get_subplots(0, plt.inset_subplots, plt.layout)
gaston_init_subplots(plt, sps)
end
if length(plt.subplots) > 0
n2, sps = gaston_get_subplots(0, plt.subplots, plt.layout)
end
if (n = n1 + n2) != length(plt.subplots)
@error "Gaston: $n != $(length(plt.subplots))"
end
plt.o.layout = gaston_init_subplots(plt, sps)
# Then add the series (curves in gaston)
for series in plt.series_list
gaston_add_series(plt, series)
end
for sp in plt.subplots
sp === nothing && continue
for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...)
sp.o.axesconf *= "\nset label '$(val.str)' at $x,$y $(gaston_font(val.font))"
end
end
nothing
end
function _update_min_padding!(sp::Subplot{GastonBackend})
sp.minpad = 0mm, 0mm, 0mm, 0mm
nothing
end
function _update_plot_object(plt::Plot{GastonBackend})
# respect the layout ratio
dat = gaston_multiplot_pos_size(plt.layout, (0, 0, 1, 1))
gaston_multiplot_pos_size!(dat)
nothing
end
for (mime, term) in (
"application/eps" => "epscairo",
"image/eps" => "epslatex",
"application/pdf" => "pdfcairo",
"application/postscript" => "postscript",
"image/png" => "png",
"image/svg+xml" => "svg",
"text/latex" => "tikz",
"application/x-tex" => "epslatex",
"text/plain" => "dumb",
)
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GastonBackend})
term = String($term)
tmpfile = "$(Gaston.tempname()).$term"
Gaston.save(
term = term,
output = tmpfile,
handle = plt.o.handle,
saveopts = gaston_saveopts(plt),
)
while !isfile(tmpfile)
end # avoid race condition with read in next line
write(io, read(tmpfile))
rm(tmpfile, force = true)
nothing
end
end
_display(plt::Plot{GastonBackend}) = display(plt.o)
# --------------------------------------------
# These functions are gaston specific
# --------------------------------------------
function gaston_saveopts(plt::Plot{GastonBackend})
saveopts = String["size $(join(plt.attr[:size], ","))"]
push!(
saveopts,
gaston_font(
plottitlefont(plt),
rot = false,
align = false,
color = false,
scale = 1,
),
)
push!(saveopts, "background $(gaston_color(plt.attr[:background_color]))")
# push!(saveopts, "title '$(plt.attr[:window_title])'")
# Scale all plot elements to match Plots.jl DPI standard
scaling = plt.attr[:dpi] / Plots.DPI
push!(saveopts, "fontscale $scaling lw $scaling dl $scaling") # ps $scaling
return join(saveopts, " ")
end
function gaston_get_subplots(n, plt_subplots, layout)
nr, nc = size(layout)
sps = Array{Any}(nothing, nr, nc)
for r in 1:nr, c in 1:nc # NOTE: col major
l = layout[r, c]
if l isa GridLayout
n, sub = gaston_get_subplots(n, plt_subplots, l)
sps[r, c] = size(sub) == (1, 1) ? only(sub) : sub
else
sps[r, c] = get(l.attr, :blank, false) ? nothing : plt_subplots[n += 1]
end
end
return n, sps
end
function gaston_init_subplots(plt, sps)
sz = nr, nc = size(sps)
for c in 1:nc, r in 1:nr # NOTE: row major
sp = sps[r, c]
if sp isa Subplot || sp === nothing
gaston_init_subplot(plt, sp)
else
gaston_init_subplots(plt, sp)
sz = max.(sz, size(sp))
end
end
return sz
end
function gaston_init_subplot(
plt::Plot{GastonBackend},
sp::Union{Nothing,Subplot{GastonBackend}},
)
if sp === nothing
push!(plt.o.subplots, sp)
else
dims =
RecipesPipeline.is3d(sp) ||
sp.attr[:projection] == "3d" ||
needs_any_3d_axes(sp) ? 3 : 2
any_label = false
for series in series_list(sp)
if dims == 2 && series[:seriestype] (:heatmap, :contour)
dims = 3 # we need heatmap/contour to use splot, not plot
end
any_label |= should_add_to_legend(series)
end
sp.o = Gaston.Plot(
dims = dims,
curves = [],
axesconf = gaston_parse_axes_args(plt, sp, dims, any_label),
)
push!(plt.o.subplots, sp.o)
end
nothing
end
function gaston_multiplot_pos_size(layout, parent_xy_wh)
nr, nc = size(layout)
dat = Array{Any}(nothing, nr, nc)
for r in 1:nr, c in 1:nc
l = layout[r, c]
# width and height (pct) are multiplicative (parent)
w = layout.widths[c].value * parent_xy_wh[3]
h = layout.heights[r].value * parent_xy_wh[4]
if isa(l, EmptyLayout)
dat[r, c] = (c - 1) * w, (r - 1) * h, w, h, nothing
else
# previous position (origin)
prev_r = r > 1 ? dat[r - 1, c] : nothing
prev_c = c > 1 ? dat[r, c - 1] : nothing
prev_r isa Array && (prev_r = prev_r[end, end])
prev_c isa Array && (prev_c = prev_c[end, end])
x = prev_c !== nothing ? prev_c[1] + prev_c[3] : parent_xy_wh[1]
y = prev_r !== nothing ? prev_r[2] + prev_r[4] : parent_xy_wh[2]
if l isa GridLayout
sub = gaston_multiplot_pos_size(l, (x, y, w, h))
dat[r, c] = size(sub) == (1, 1) ? only(sub) : sub
else
dat[r, c] = x, y, w, h, l
end
end
end
return dat
end
function gaston_multiplot_pos_size!(dat)
nr, nc = size(dat)
for r in 1:nr, c in 1:nc
xy_wh_sp = dat[r, c]
if xy_wh_sp isa Array
gaston_multiplot_pos_size!(xy_wh_sp)
elseif xy_wh_sp isa Tuple
x, y, w, h, sp = xy_wh_sp
sp === nothing && continue
sp.o === nothing && continue
# gnuplot screen coordinates: bottom left at 0,0 and top right at 1,1
sp.o.axesconf = "set origin $x, $(1 - y - h)\nset size $w, $h\n" * sp.o.axesconf
end
end
nothing
end
function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
sp = series[:subplot]
gsp = sp.o
x, y, z = series[:x], series[:y], series[:z]
st = series[:seriestype]
curves = []
if gsp.dims == 2 && z === nothing
for (n, seg) in enumerate(series_segments(series, st; check = true))
i, rng = seg.attr_index, seg.range
fr = _cycle(series[:fillrange], 1:length(x[rng]))
for sc in gaston_seriesconf!(sp, series, i, n == 1)
push!(curves, Gaston.Curve(x[rng], y[rng], nothing, fr, sc))
end
end
else
if z isa Surface
z = z.surf
if st == :image
z = reverse(Float32.(Gray.(z)), dims = 1) # flip y axis
nr, nc = size(z)
if (ly = length(y)) == 2 && ly != nr
y = collect(range(y[1], y[2], length = nr))
end
if (lx = length(x)) == 2 && lx != nc
x = collect(range(x[1], x[2], length = nc))
end
end
length(x) == size(z, 2) + 1 && (x = (x[1:(end - 1)] + x[2:end]) / 2)
length(y) == size(z, 1) + 1 && (y = (y[1:(end - 1)] + y[2:end]) / 2)
end
if st == :mesh3d
x, y, z = mesh3d_triangles(x, y, z, series[:connections])
end
for sc in gaston_seriesconf!(sp, series, 1, true)
push!(curves, Gaston.Curve(x, y, z, nothing, sc))
end
end
for c in curves
append = length(gsp.curves) > 0
push!(gsp.curves, c)
Gaston.write_data(c, gsp.dims, gsp.datafile, append = append)
end
nothing
end
function gaston_seriesconf!(
sp::Subplot{GastonBackend},
series::Series,
i::Int,
add_to_legend::Bool,
)
#=
gnuplot abbreviations (see gnuplot/src/set.c)
---------------------------------------------
dl: dashlength
dt: dashtype
fc: fillcolor
fs: fillstyle
lc: linecolor
lp: linespoints
ls: linestyle
lt: linetype
lw: linewidth
pi: pointinterval
pn: pointnumber
ps: pointscale
pt: pointtype
tc: textcolor
w: with
=#
gsp = sp.o
st = series[:seriestype]
extra = []
add_to_legend &= should_add_to_legend(series)
curveconf = String[add_to_legend ? "title '$(series[:label])'" : "notitle"]
clims = get_clims(sp, series)
if st (:scatter, :scatter3d)
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
push!(curveconf, "w points pt $pt ps $ps lc $mc")
elseif st (:path, :straightline, :path3d)
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
push!(
curveconf,
"w filledcurves fc $fc fs solid border lc $lc lw $lw dt $dt,'' w lines lc $lc lw $lw dt $dt",
)
elseif series[:markershape] == :none # simplepath
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
else
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
push!(curveconf, "w lp lc $mc dt $dt lw $lw pt $pt ps $ps")
end
elseif st == :shape
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i))
lc, _ = gaston_lc_ls_lw(series, clims, i)
push!(curveconf, "w filledcurves fc $fc fs solid border lc $lc")
elseif st (:steppre, :stepmid, :steppost)
step = if st == :steppre
"fsteps"
elseif st == :stepmid
"histeps"
elseif st == :steppost
"steps"
end
push!(curveconf, "w $step")
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
push!(extra, "w points lc $lc dt $dt lw $lw notitle")
elseif st == :image
palette = gaston_palette(series[:seriescolor])
gsp.axesconf *= "\nset palette model RGB defined $palette"
push!(curveconf, "w image pixels")
elseif st (:contour, :contour3d)
push!(curveconf, "w lines")
st == :contour && (gsp.axesconf *= "\nset view map\nunset surface") # 2D
levels = join(map(string, collect(contour_levels(series, clims))), ", ")
gsp.axesconf *= "\nset contour base\nset cntrparam levels discrete $levels"
elseif st (:surface, :heatmap)
push!(curveconf, "w pm3d")
palette = gaston_palette(series[:seriescolor])
gsp.axesconf *= "\nset palette model RGB defined $palette"
st == :heatmap && (gsp.axesconf *= "\nset view map")
elseif st (:wireframe, :mesh3d)
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
elseif st == :quiver
push!(curveconf, "w vectors filled")
else
@warn "Gaston: $st is not implemented yet"
end
return [join(curveconf, " "), extra...]
end
function gaston_parse_axes_args(
plt::Plot{GastonBackend},
sp::Subplot{GastonBackend},
dims::Int,
any_label::Bool,
)
# axesconf = String["set margins 2, 2, 2, 2"] # left, right, bottom, top
axesconf = String[]
polar = ispolar(sp) && dims == 2 # cannot splot in polar coordinates
for letter in (:x, :y, :z)
(letter == :z && dims == 2) && continue
axis = sp.attr[get_attr_symbol(letter, :axis)]
# label names
push!(
axesconf,
"set $(letter)label '$(axis[:guide])' $(gaston_font(guidefont(axis)))",
)
mirror = axis[:mirror] ? "mirror" : "nomirror"
if axis[:scale] == :identity
logscale, base = "nologscale", ""
elseif axis[:scale] == :log10
logscale, base = "logscale", "10"
elseif axis[:scale] == :log2
logscale, base = "logscale", "2"
elseif axis[:scale] == :ln
logscale, base = "logscale", "e"
end
push!(axesconf, "set $logscale $letter $base")
# handle ticks
if polar
push!(axesconf, "set size square\nunset $(letter)tics")
else
push!(
axesconf,
"set $(letter)tics $(mirror) $(axis[:tick_direction]) $(gaston_font(tickfont(axis)))",
)
# major tick locations
if axis[:ticks] != :native
if axis[:flip]
hi, lo = axis_limits(sp, letter)
else
lo, hi = axis_limits(sp, letter)
end
push!(axesconf, "set $(letter)range [$lo:$hi]")
ticks = get_ticks(sp, axis)
gaston_set_ticks!(axesconf, ticks, letter, "", "")
if axis[:minorticks] != :native
minor_ticks = get_minor_ticks(sp, axis, ticks)
gaston_set_ticks!(axesconf, minor_ticks, letter, "m", "add")
end
end
end
if axis[:grid]
push!(axesconf, "set grid " * (polar ? "polar" : "$(letter)tics"))
axis[:minorgrid] &&
push!(axesconf, "set grid " * (polar ? "polar" : "m$(letter)tics"))
end
ratio = get_aspect_ratio(sp)
if ratio != :none
ratio == :equal && (ratio = -1)
push!(axesconf, "set size ratio $ratio")
end
end
gaston_set_legend!(axesconf, sp, any_label)
if hascolorbar(sp)
push!(axesconf, "set cbtics $(gaston_font(colorbartitlefont(sp)))")
end
if sp[:title] !== nothing
push!(axesconf, "set title '$(sp[:title])' $(gaston_font(titlefont(sp)))")
end
if polar
push!(axesconf, "unset border\nset polar\nset border polar")
tmin, tmax = axis_limits(sp, :x, false, false)
rmin, rmax = axis_limits(sp, :y, false, false)
rticks = get_ticks(sp, :y)
if (ttype = ticksType(rticks)) == :ticks
gaston_ticks = string.(rticks)
elseif ttype == :ticks_and_labels
gaston_ticks = String["'$l' $t" for (t, l) in zip(rticks...)]
end
push!(
axesconf,
"set rtics ( " *
join(gaston_ticks, ", ") *
" ) $(gaston_font(tickfont(sp.attr[:yaxis])))",
)
push!(axesconf, "set trange [$(min(0, tmin)):$(max(2π, tmax))]")
push!(axesconf, "set rrange [$rmin:$rmax]")
push!(
axesconf,
"set ttics 0,30 format \"%g\".GPVAL_DEGREE_SIGN $(gaston_font(tickfont(sp.attr[:xaxis])))",
)
push!(axesconf, "set mttics 3")
end
return join(axesconf, "\n")
end
function gaston_set_ticks!(axesconf, ticks, letter, maj_min, add)
ticks == :auto && return
if ticks (:none, nothing, false)
push!(axesconf, "unset $(maj_min)$(letter)tics")
return
end
gaston_ticks = String[]
if (ttype = ticksType(ticks)) == :ticks
tick_locs = @view ticks[:]
for i in eachindex(tick_locs)
tick = if maj_min == "m"
"'' $(tick_locs[i]) 1" # see gnuplot manual 'Mxtics'
else
"$(tick_locs[i])"
end
push!(gaston_ticks, tick)
end
elseif ttype == :ticks_and_labels
tick_locs = @view ticks[1][:]
tick_labels = @view ticks[2][:]
for i in eachindex(tick_locs)
lab = gaston_enclose_tick_string(tick_labels[i])
push!(gaston_ticks, "'$lab' $(tick_locs[i])")
end
else
gaston_ticks = nothing
@error "Gaston: invalid input for $(maj_min)$(letter)ticks: $ticks"
end
if gaston_ticks !== nothing
push!(axesconf, "set $(letter)tics $add (" * join(gaston_ticks, ", ") * ")")
end
nothing
end
function gaston_set_legend!(axesconf, sp, any_label)
leg = sp[:legend_position]
if sp[:legend_position] (:none, :inline) && any_label
leg == :best && (leg = :topright)
push!(
axesconf,
"set key " * (occursin("outer", string(leg)) ? "outside" : "inside"),
)
for position in ("top", "bottom", "left", "right")
occursin(position, string(leg)) && push!(axesconf, "set key $position")
end
push!(axesconf, "set key $(gaston_font(legendfont(sp), rot=false, align=false))")
if sp[:legend_title] !== nothing
# NOTE: cannot use legendtitlefont(sp) as it will override legendfont
push!(axesconf, "set key title '$(sp[:legend_title])'")
end
push!(axesconf, "set key box lw 1 opaque")
push!(axesconf, "set border back")
else
push!(axesconf, "set key off")
end
nothing
end
# --------------------------------------------
# Helpers
# --------------------------------------------
gaston_halign(k) = (left = :left, hcenter = :center, right = :right)[k]
gaston_valign(k) = (top = :top, vcenter = :center, bottom = :bottom)[k]
gaston_alpha(alpha) = alpha === nothing ? 0 : alpha
gaston_lc_ls_lw(series::Series, clims, i::Int) = (
gaston_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
gaston_linestyle(get_linestyle(series, i)),
get_linewidth(series, i),
)
gaston_mk_ms_mc(series::Series, clims, i::Int) = (
gaston_marker(_cycle(series[:markershape], i), get_markeralpha(series, i)),
_cycle(series[:markersize], i) * 1.3 / 5,
gaston_color(get_markercolor(series, clims, i), get_markeralpha(series, i)),
)
function gaston_font(f; rot = true, align = true, color = true, scale = 1)
font = String["font '$(f.family),$(round(Int, scale * f.pointsize))'"]
align && push!(font, "$(gaston_halign(f.halign))")
rot && push!(font, "rotate by $(f.rotation)")
color && push!(font, "textcolor $(gaston_color(f.color))")
return join(font, " ")
end
function gaston_palette(gradient)
palette = String[]
n = -1
for rgba in gradient # FIXME: naive conversion, inefficient ?
push!(palette, "$(n += 1) $(rgba.r) $(rgba.g) $(rgba.b)")
end
return '(' * join(palette, ", ") * ')'
end
function gaston_marker(marker, alpha)
# NOTE: :rtriangle, :ltriangle, :hexagon, :heptagon, :octagon seems unsupported by gnuplot
filled = gaston_alpha(alpha) == 0
marker == :none && return -1
marker == :pixel && return 0
marker (:+, :cross) && return 1
marker (:x, :xcross) && return 2
marker == :star5 && return 3
marker == :rect && return filled ? 5 : 4
marker == :circle && return filled ? 7 : 6
marker == :utriangle && return filled ? 9 : 8
marker == :dtriangle && return filled ? 11 : 10
marker == :diamond && return filled ? 13 : 12
marker == :pentagon && return filled ? 15 : 14
@warn "Gaston: unsupported marker $marker"
return 1
end
function gaston_color(col, alpha = 0)
col = single_color(col) # in case of gradients
col = alphacolor(col, gaston_alpha(alpha)) # add a default alpha if non existent
return "rgb '#$(hex(col, :aarrggbb))'"
end
function gaston_linestyle(style)
style == :solid && return "1"
style == :dash && return "2"
style == :dot && return "3"
style == :dashdot && return "4"
style == :dashdotdot && return "5"
end
function gaston_enclose_tick_string(tick_string)
findfirst("^", tick_string) === nothing && return tick_string
base, power = split(tick_string, "^")
return "$base^{$power}"
end

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@ Read from .hdf5 file using:
display(pread) display(pread)
==# ==#
#==TODO #==TODO
=============================================================================== ===============================================================================
1. Support more features. 1. Support more features.
@ -56,7 +55,8 @@ import ..HDF5PLOT_MAP_STR2TELEM, ..HDF5PLOT_MAP_TELEM2STR
import ..HDF5Plot_PlotRef, ..HDF5PLOT_PLOTREF import ..HDF5Plot_PlotRef, ..HDF5PLOT_PLOTREF
import ..BoundingBox, ..Extrema, ..Length import ..BoundingBox, ..Extrema, ..Length
import ..RecipesPipeline.datetimeformatter import ..RecipesPipeline.datetimeformatter
import ..PlotUtils.ColorPalette, ..PlotUtils.CategoricalColorGradient, ..PlotUtils.ContinuousColorGradient import ..PlotUtils.ColorPalette,
..PlotUtils.CategoricalColorGradient, ..PlotUtils.ContinuousColorGradient
import ..Surface, ..Shape, ..Arrow import ..Surface, ..Shape, ..Arrow
import ..GridLayout, ..RootLayout import ..GridLayout, ..RootLayout
import ..Font, ..PlotText, ..SeriesAnnotations import ..Font, ..PlotText, ..SeriesAnnotations
@ -66,14 +66,13 @@ import .._axis_defaults
import ..plot, ..plot! import ..plot, ..plot!
#Types that already have built-in HDF5 support (just write out natively): #Types that already have built-in HDF5 support (just write out natively):
const HDF5_SupportedTypes = Union{Number, String} const HDF5_SupportedTypes = Union{Number,String}
#TODO: Types_HDF5Support #TODO: Types_HDF5Support
#Dispatch types: #Dispatch types:
struct CplxTuple; end #Identifies a "complex" tuple structure (not merely numbers) struct CplxTuple end #Identifies a "complex" tuple structure (not merely numbers)
#HDF5 reader will auto-detect type correctly: #HDF5 reader will auto-detect type correctly:
struct HDF5_AutoDetect; end #See HDF5_SupportedTypes struct HDF5_AutoDetect end #See HDF5_SupportedTypes
#== #==
===============================================================================# ===============================================================================#
@ -82,13 +81,12 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1
#Possible element types of high-level data types: #Possible element types of high-level data types:
#(Used to add type information as an HDF5 string attribute) #(Used to add type information as an HDF5 string attribute)
#(Also used to dispatch appropriate read function through _read_typed()) #(Also used to dispatch appropriate read function through _read_typed())
_telem2str = Dict{String, Type}( _telem2str = Dict{String,Type}(
"NOTHING" => Nothing, "NOTHING" => Nothing,
"SYMBOL" => Symbol, "SYMBOL" => Symbol,
"RGBA" => Colorant, #Write out any Colorant to an #RRGGBBAA string "RGBA" => Colorant, #Write out any Colorant to an #RRGGBBAA string
"TUPLE" => Tuple, "TUPLE" => Tuple,
"CTUPLE" => CplxTuple, #Tuple of complex structures "CTUPLE" => CplxTuple,
"EXTREMA" => Extrema, "EXTREMA" => Extrema,
"LENGTH" => Length, "LENGTH" => Length,
"ARRAY" => Array, #Array{Any} (because Array{T<:Union{Number, String}} natively supported by HDF5) "ARRAY" => Array, #Array{Any} (because Array{T<:Union{Number, String}} natively supported by HDF5)
@ -115,10 +113,12 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1
"SUBPLOT" => Subplot, "SUBPLOT" => Subplot,
) )
merge!(HDF5PLOT_MAP_STR2TELEM, _telem2str) #Faster to create than push!()?? merge!(HDF5PLOT_MAP_STR2TELEM, _telem2str) #Faster to create than push!()??
merge!(HDF5PLOT_MAP_TELEM2STR, Dict{Type, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM)) merge!(
HDF5PLOT_MAP_TELEM2STR,
Dict{Type,String}(v => k for (k, v) in HDF5PLOT_MAP_STR2TELEM),
)
end end
#==Helper functions #==Helper functions
===============================================================================# ===============================================================================#
@ -151,19 +151,18 @@ function _hdf5_merge!(dest::AKW, src::AKW)
end end
#_type_for_map returns the type to use with HDF5PLOT_MAP_TELEM2STR[], in case it is not concrete: #_type_for_map returns the type to use with HDF5PLOT_MAP_TELEM2STR[], in case it is not concrete:
_type_for_map(::Type{T}) where T = T #Catch-all _type_for_map(::Type{T}) where {T} = T #Catch-all
_type_for_map(::Type{T}) where T<:BoundingBox = BoundingBox _type_for_map(::Type{T}) where {T<:BoundingBox} = BoundingBox
_type_for_map(::Type{T}) where T<:ColorScheme = ColorScheme _type_for_map(::Type{T}) where {T<:ColorScheme} = ColorScheme
_type_for_map(::Type{T}) where T<:Surface = Surface _type_for_map(::Type{T}) where {T<:Surface} = Surface
#==Read/write things like type name in attributes #==Read/write things like type name in attributes
===============================================================================# ===============================================================================#
function _write_datatype_attr(ds::Union{Group, Dataset}, ::Type{T}) where T function _write_datatype_attr(ds::Union{Group,Dataset}, ::Type{T}) where {T}
typestr = HDF5PLOT_MAP_TELEM2STR[T] typestr = HDF5PLOT_MAP_TELEM2STR[T]
HDF5.attributes(ds)["TYPE"] = typestr HDF5.attributes(ds)["TYPE"] = typestr
end end
function _read_datatype_attr(ds::Union{Group, Dataset}) function _read_datatype_attr(ds::Union{Group,Dataset})
if !Base.haskey(HDF5.attributes(ds), "TYPE") if !Base.haskey(HDF5.attributes(ds), "TYPE")
return HDF5_AutoDetect return HDF5_AutoDetect
end end
@ -173,7 +172,7 @@ function _read_datatype_attr(ds::Union{Group, Dataset})
end end
#Type parameter attributes: #Type parameter attributes:
function _write_typeparam_attr(ds::Dataset, v::Length{T}) where T function _write_typeparam_attr(ds::Dataset, v::Length{T}) where {T}
HDF5.attributes(ds)["TYPEPARAM"] = string(T) #Need to add units for Length HDF5.attributes(ds)["TYPEPARAM"] = string(T) #Need to add units for Length
end end
_read_typeparam_attr(ds::Dataset) = HDF5.read(HDF5.attributes(ds)["TYPEPARAM"]) _read_typeparam_attr(ds::Dataset) = HDF5.read(HDF5.attributes(ds)["TYPEPARAM"])
@ -186,8 +185,8 @@ _read_length_attr(::Type{Vector}, grp::Group) = HDF5.read(HDF5.attributes(grp)["
function _write_size_attr(grp::Group, v::Array) #of an array function _write_size_attr(grp::Group, v::Array) #of an array
HDF5.attributes(grp)["SIZE"] = [size(v)...] HDF5.attributes(grp)["SIZE"] = [size(v)...]
end end
_read_size_attr(::Type{Array}, grp::Group) = tuple(HDF5.read(HDF5.attributes(grp)["SIZE"])...) _read_size_attr(::Type{Array}, grp::Group) =
tuple(HDF5.read(HDF5.attributes(grp)["SIZE"])...)
#==_write_typed(): Simple (leaf) datatypes. (Labels with type name.) #==_write_typed(): Simple (leaf) datatypes. (Labels with type name.)
===============================================================================# ===============================================================================#
@ -228,9 +227,9 @@ function _write_typed(grp::Group, name::String, v::Length)
end end
function _write_typed(grp::Group, name::String, v::typeof(datetimeformatter)) function _write_typed(grp::Group, name::String, v::typeof(datetimeformatter))
grp[name] = string(v) #Just write something that helps reader grp[name] = string(v) #Just write something that helps reader
_write_datatype_attr(grp[name], typeof(datetimeformatter)) _write_datatype_attr(grp[name], typeof(datetimeformatter))
end end
function _write_typed(grp::Group, name::String, v::Array{T}) where T<:Number #Default for arrays function _write_typed(grp::Group, name::String, v::Array{T}) where {T<:Number} #Default for arrays
grp[name] = v grp[name] = v
return #No need to _write_datatype_attr return #No need to _write_datatype_attr
end end
@ -238,8 +237,6 @@ function _write_typed(grp::Group, name::String, v::AbstractRange)
_write_typed(grp, name, collect(v)) #For now _write_typed(grp, name, collect(v)) #For now
end end
#== Helper functions for writing complex data structures #== Helper functions for writing complex data structures
===============================================================================# ===============================================================================#
@ -270,20 +267,19 @@ function _write(grp::Group, name::String, d::AbstractDict)
end end
#Write out arbitrary `struct`s: #Write out arbitrary `struct`s:
function _writestructgeneric(grp::Group, obj::T) where T function _writestructgeneric(grp::Group, obj::T) where {T}
for fname in fieldnames(T) for fname in fieldnames(T)
v = getfield(obj, fname) v = getfield(obj, fname)
_write_typed(grp, String(fname), v) _write_typed(grp, String(fname), v)
end end
return return
end end
#==_write_typed(): More complex structures. (Labels with type name.) #==_write_typed(): More complex structures. (Labels with type name.)
===============================================================================# ===============================================================================#
#Catch-all (default behaviour for `struct`s): #Catch-all (default behaviour for `struct`s):
function _write_typed(grp::Group, name::String, v::T) where T function _write_typed(grp::Group, name::String, v::T) where {T}
#NOTE: need "name" parameter so that call signature is same with built-ins #NOTE: need "name" parameter so that call signature is same with built-ins
MT = _type_for_map(T) MT = _type_for_map(T)
try #Check to see if type is supported try #Check to see if type is supported
@ -299,12 +295,12 @@ function _write_typed(grp::Group, name::String, v::T) where T
_writestructgeneric(objgrp, v) _writestructgeneric(objgrp, v)
end end
function _write_typed(grp::Group, name::String, v::Array{T}) where T function _write_typed(grp::Group, name::String, v::Array{T}) where {T}
_write_harray(grp, name, v) _write_harray(grp, name, v)
_write_datatype_attr(grp[name], Array) #{Any} _write_datatype_attr(grp[name], Array) #{Any}
end end
function _write_typed(grp::Group, name::String, v::Tuple, ::Type{ELT}) where ELT<: Number #Basic Tuple function _write_typed(grp::Group, name::String, v::Tuple, ::Type{ELT}) where {ELT<:Number} #Basic Tuple
_write_typed(grp, name, [v...]) _write_typed(grp, name, [v...])
_write_datatype_attr(grp[name], Tuple) _write_datatype_attr(grp[name], Tuple)
end end
@ -315,12 +311,12 @@ end
_write_typed(grp::Group, name::String, v::Tuple) = _write_typed(grp, name, v, eltype(v)) _write_typed(grp::Group, name::String, v::Tuple) = _write_typed(grp, name, v, eltype(v))
function _write_typed(grp::Group, name::String, v::Dict) function _write_typed(grp::Group, name::String, v::Dict)
#= #=
tstr = string(Dict) tstr = string(Dict)
path = HDF5.name(grp) * "/" * name path = HDF5.name(grp) * "/" * name
@info("Type not supported: $tstr\npath: $path") @info("Type not supported: $tstr\npath: $path")
return return
=# =#
#No support for structures with Dicts yet #No support for structures with Dicts yet
end end
function _write_typed(grp::Group, name::String, d::DefaultsDict) #Typically for plot attributes function _write_typed(grp::Group, name::String, d::DefaultsDict) #Typically for plot attributes
@ -347,7 +343,6 @@ function _write_typed(grp::Group, name::String, v::Plot)
#Don't write plot references #Don't write plot references
end end
#==_write(): Write out more complex structures #==_write(): Write out more complex structures
NOTE: No need to write out type information (inferred from hierarchy) NOTE: No need to write out type information (inferred from hierarchy)
===============================================================================# ===============================================================================#
@ -378,7 +373,11 @@ function _write(grp::Group, plt::Plot{HDF5Backend})
return return
end end
function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString; name::String="_unnamed") function hdf5plot_write(
plt::Plot{HDF5Backend},
path::AbstractString;
name::String = "_unnamed",
)
HDF5.h5open(path, "w") do file HDF5.h5open(path, "w") do file
HDF5.write_dataset(file, "VERSION_INFO", _get_Plots_versionstr()) HDF5.write_dataset(file, "VERSION_INFO", _get_Plots_versionstr())
grp = HDF5.create_group(file, h5plotpath(name)) grp = HDF5.create_group(file, h5plotpath(name))
@ -386,7 +385,6 @@ function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString; name::Stri
end end
end end
#== _read(): Read data, but not type information. #== _read(): Read data, but not type information.
===============================================================================# ===============================================================================#
@ -417,7 +415,6 @@ function _read(::Type{Length}, ds::Dataset)
end end
_read(::Type{typeof(datetimeformatter)}, ds::Dataset) = datetimeformatter _read(::Type{typeof(datetimeformatter)}, ds::Dataset) = datetimeformatter
#== Helper functions for reading in complex data structures #== Helper functions for reading in complex data structures
===============================================================================# ===============================================================================#
@ -429,7 +426,7 @@ function _read_typed(grp::Group, name::String)
end end
#_readstructgeneric: Needs object values to be written out with _write_typed(): #_readstructgeneric: Needs object values to be written out with _write_typed():
function _readstructgeneric(::Type{T}, grp::Group) where T function _readstructgeneric(::Type{T}, grp::Group) where {T}
vlist = Array{Any}(nothing, fieldcount(T)) vlist = Array{Any}(nothing, fieldcount(T))
for (i, fname) in enumerate(fieldnames(T)) for (i, fname) in enumerate(fieldnames(T))
vlist[i] = _read_typed(grp, String(fname)) vlist[i] = _read_typed(grp, String(fname))
@ -454,7 +451,6 @@ function _read(::Type{KW}, grp::Group)
return d return d
end end
#== _read(): More complex structures. #== _read(): More complex structures.
===============================================================================# ===============================================================================#
@ -463,7 +459,9 @@ _read(T::Type, grp::Group) = _readstructgeneric(T, grp)
function _read(::Type{Array}, grp::Group) #Array{Any} function _read(::Type{Array}, grp::Group) #Array{Any}
sz = _read_size_attr(Array, grp) sz = _read_size_attr(Array, grp)
if tuple(0) == sz; return []; end if tuple(0) == sz
return []
end
result = Array{Any}(undef, sz) result = Array{Any}(undef, sz)
lidx = LinearIndices(sz) lidx = LinearIndices(sz)
@ -498,7 +496,9 @@ function _read(::Type{DefaultsDict}, grp::Group)
#User should set DefaultsDict.defaults to one of: #User should set DefaultsDict.defaults to one of:
# _plot_defaults, _subplot_defaults, _axis_defaults, _series_defaults # _plot_defaults, _subplot_defaults, _axis_defaults, _series_defaults
path = HDF5.name(ds) path = HDF5.name(ds)
@warn("Cannot yet read DefaultsDict using _read_typed():\n $path\nCannot fully reconstruct plot.") @warn(
"Cannot yet read DefaultsDict using _read_typed():\n $path\nCannot fully reconstruct plot."
)
end end
function _read(::Type{Axis}, grp::Group) function _read(::Type{Axis}, grp::Group)
#1st arg appears to be ref to subplots. Seems to work without it. #1st arg appears to be ref to subplots. Seems to work without it.
@ -510,7 +510,6 @@ function _read(::Type{Subplot}, grp::Group)
return HDF5PLOT_PLOTREF.ref.subplots[idx] return HDF5PLOT_PLOTREF.ref.subplots[idx]
end end
#== _read(): Main plot structures #== _read(): Main plot structures
===============================================================================# ===============================================================================#
@ -538,7 +537,7 @@ function _read_plot(grp::Group)
n = _read_length_attr(Vector, listgrp) n = _read_length_attr(Vector, listgrp)
#Construct new plot, +allocate subplots: #Construct new plot, +allocate subplots:
plt = plot(layout=n) plt = plot(layout = n)
HDF5PLOT_PLOTREF.ref = plt #Used when reading "layout" HDF5PLOT_PLOTREF.ref = plt #Used when reading "layout"
agrp = HDF5.open_group(grp, "attr") agrp = HDF5.open_group(grp, "attr")
@ -552,17 +551,15 @@ function _read_plot(grp::Group)
return plt return plt
end end
function hdf5plot_read(path::AbstractString; name::String="_unnamed") function hdf5plot_read(path::AbstractString; name::String = "_unnamed")
HDF5.h5open(path, "r") do file HDF5.h5open(path, "r") do file
grp = HDF5.open_group(file, h5plotpath("_unnamed")) grp = HDF5.open_group(file, h5plotpath("_unnamed"))
return _read_plot(grp) return _read_plot(grp)
end end
end end
end #module _hdf5_implementation end #module _hdf5_implementation
#==Implement Plots.jl backend interface for HDF5Backend #==Implement Plots.jl backend interface for HDF5Backend
===============================================================================# ===============================================================================#
@ -640,7 +637,8 @@ end
#==Interface actually required to use HDF5Backend #==Interface actually required to use HDF5Backend
===============================================================================# ===============================================================================#
hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) = _hdf5_implementation.hdf5plot_write(plt, path) hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) =
_hdf5_implementation.hdf5plot_write(plt, path)
hdf5plot_write(path::AbstractString) = _hdf5_implementation.hdf5plot_write(current(), path) hdf5plot_write(path::AbstractString) = _hdf5_implementation.hdf5plot_write(current(), path)
hdf5plot_read(path::AbstractString) = _hdf5_implementation.hdf5plot_read(path) hdf5plot_read(path::AbstractString) = _hdf5_implementation.hdf5plot_read(path)

View File

@ -13,7 +13,7 @@ Add in functionality to Plots.jl:
:aspect_ratio, :aspect_ratio,
=# =#
# --------------------------------------------------------------------------- should_warn_on_unsupported(::InspectDRBackend) = false
is_marker_supported(::InspectDRBackend, shape::Shape) = true is_marker_supported(::InspectDRBackend, shape::Shape) = true
@ -44,16 +44,16 @@ _inspectdr_mapcolor(v::Colorant) = v
function _inspectdr_mapcolor(g::PlotUtils.ColorGradient) function _inspectdr_mapcolor(g::PlotUtils.ColorGradient)
@warn("Color gradients are currently unsupported in InspectDR.") @warn("Color gradients are currently unsupported in InspectDR.")
#Pick middle color: #Pick middle color:
_inspectdr_mapcolor(g.colors[div(1+end,2)]) _inspectdr_mapcolor(g.colors[div(1 + end, 2)])
end end
function _inspectdr_mapcolor(v::AVec) function _inspectdr_mapcolor(v::AVec)
@warn("Vectors of colors are currently unsupported in InspectDR.") @warn("Vectors of colors are currently unsupported in InspectDR.")
#Pick middle color: #Pick middle color:
_inspectdr_mapcolor(v[div(1+end,2)]) _inspectdr_mapcolor(v[div(1 + end, 2)])
end end
#Hack: suggested point size does not seem adequate relative to plot size, for some reason. #Hack: suggested point size does not seem adequate relative to plot size, for some reason.
_inspectdr_mapptsize(v) = 1.5*v _inspectdr_mapptsize(v) = 1.5 * v
function _inspectdr_add_annotations(plot, x, y, val) function _inspectdr_add_annotations(plot, x, y, val)
#What kind of annotation is this? #What kind of annotation is this?
@ -61,14 +61,21 @@ end
#plot::InspectDR.Plot2D #plot::InspectDR.Plot2D
function _inspectdr_add_annotations(plot, x, y, val::PlotText) function _inspectdr_add_annotations(plot, x, y, val::PlotText)
vmap = Dict{Symbol, Symbol}(:top=>:t, :bottom=>:b) #:vcenter vmap = Dict{Symbol,Symbol}(:top => :t, :bottom => :b) #:vcenter
hmap = Dict{Symbol, Symbol}(:left=>:l, :right=>:r) #:hcenter hmap = Dict{Symbol,Symbol}(:left => :l, :right => :r) #:hcenter
align = Symbol(get(vmap, val.font.valign, :c), get(hmap, val.font.halign, :c)) align = Symbol(get(vmap, val.font.valign, :c), get(hmap, val.font.halign, :c))
fnt = InspectDR.Font(val.font.family, val.font.pointsize, fnt = InspectDR.Font(
color =_inspectdr_mapcolor(val.font.color) val.font.family,
val.font.pointsize,
color = _inspectdr_mapcolor(val.font.color),
) )
ann = InspectDR.atext(val.str, x=x, y=y, ann = InspectDR.atext(
font=fnt, angle=val.font.rotation, align=align texmath2unicode(val.str),
x = x,
y = y,
font = fnt,
angle = val.font.rotation,
align = align,
) )
InspectDR.add(plot, ann) InspectDR.add(plot, ann)
return return
@ -84,7 +91,9 @@ function _inspectdr_getaxisticks(ticks, gridlines, xfrm)
if ticks == :native if ticks == :native
#keep current #keep current
elseif ttype == :ticks_and_labels elseif ttype == :ticks_and_labels
pos = ticks[1]; labels = ticks[2]; nticks = length(ticks[1]) pos = ticks[1]
labels = ticks[2]
nticks = length(ticks[1])
newticks = TickCustom[TickCustom(_xfrm(pos[i]), labels[i]) for i in 1:nticks] newticks = TickCustom[TickCustom(_xfrm(pos[i]), labels[i]) for i in 1:nticks]
gridlines = InspectDR.GridLinesCustom(gridlines) gridlines = InspectDR.GridLinesCustom(gridlines)
gridlines.major = newticks gridlines.major = newticks
@ -129,8 +138,8 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
function _inspectdr_getscale(s::Symbol, yaxis::Bool) function _inspectdr_getscale(s::Symbol, yaxis::Bool)
#TODO: Support :asinh, :sqrt #TODO: Support :asinh, :sqrt
kwargs = yaxis ? (:tgtmajor=>8, :tgtminor=>2) : () #More grid lines on y-axis kwargs = yaxis ? (:tgtmajor => 8, :tgtminor => 2) : () #More grid lines on y-axis
if :log2 == s if :log2 == s
return InspectDR.AxisScale(:log2; kwargs...) return InspectDR.AxisScale(:log2; kwargs...)
elseif :log10 == s elseif :log10 == s
@ -145,13 +154,12 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
#Glyph used when plotting "Shape"s: #Glyph used when plotting "Shape"s:
INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline( INSPECTDR_GLYPH_SHAPE =
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y InspectDR.GlyphPolyline(2 * InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y)
)
mutable struct InspecDRPlotRef mutable struct InspecDRPlotRef
mplot::Union{Nothing, InspectDR.Multiplot} mplot::Union{Nothing,InspectDR.Multiplot}
gui::Union{Nothing, InspectDR.GtkPlot} gui::Union{Nothing,InspectDR.GtkPlot}
end end
_inspectdr_getmplot(::Any) = nothing _inspectdr_getmplot(::Any) = nothing
@ -200,7 +208,9 @@ end
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend}) function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
plot = sp.o plot = sp.o
#Don't do anything without a "subplot" object: Will process later. #Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end if nothing == plot
return
end
plot.data = [] plot.data = []
plot.userannot = [] #Clear old markers/text annotation/polyline "annotation" plot.userannot = [] #Clear old markers/text annotation/polyline "annotation"
return plot return plot
@ -219,7 +229,9 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
clims = get_clims(sp, series) clims = get_clims(sp, series)
#Don't do anything without a "subplot" object: Will process later. #Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end if nothing == plot
return
end
_vectorize(v) = isa(v, Vector) ? v : collect(v) #InspectDR only supports vectors _vectorize(v) = isa(v, Vector) ? v : collect(v) #InspectDR only supports vectors
x, y = if st == :straightline x, y = if st == :straightline
@ -230,30 +242,33 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
#No support for polar grid... but can still perform polar transformation: #No support for polar grid... but can still perform polar transformation:
if ispolar(sp) if ispolar(sp)
Θ = x; r = y Θ = x
x = r.*cos.(Θ); y = r.*sin.(Θ) r = y
x = r .* cos.(Θ)
y = r .* sin.(Θ)
end end
# doesn't handle mismatched x/y - wrap data (pyplot behaviour): # doesn't handle mismatched x/y - wrap data (pyplot behaviour):
nx = length(x); ny = length(y) nx = length(x)
ny = length(y)
if nx < ny if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny] series[:x] = Float64[x[mod1(i, nx)] for i in 1:ny]
elseif ny > nx elseif ny > nx
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx] series[:y] = Float64[y[mod1(i, ny)] for i in 1:nx]
end end
#= TODO: Eventually support #= TODO: Eventually support
series[:fillcolor] #I think this is fill under line series[:fillcolor] #I think this is fill under line
zorder = series[:series_plotindex] zorder = series[:series_plotindex]
For st in :shape: For st in :shape:
zorder = series[:series_plotindex], zorder = series[:series_plotindex],
=# =#
if st in (:shape,) if st in (:shape,)
x, y = shape_data(series) x, y = shape_data(series)
nmax = 0 nmax = 0
for (i,rng) in enumerate(iter_segments(x, y)) for (i, rng) in enumerate(iter_segments(x, y))
nmax = i nmax = i
if length(rng) > 1 if length(rng) > 1
linewidth = series[:linewidth] linewidth = series[:linewidth]
@ -261,11 +276,12 @@ For st in :shape:
linecolor = _inspectdr_mapcolor(_cycle(c, i)) linecolor = _inspectdr_mapcolor(_cycle(c, i))
c = plot_color(get_fillcolor(series), get_fillalpha(series)) c = plot_color(get_fillcolor(series), get_fillalpha(series))
fillcolor = _inspectdr_mapcolor(_cycle(c, i)) fillcolor = _inspectdr_mapcolor(_cycle(c, i))
line = InspectDR.line( line = InspectDR.line(style = :solid, width = linewidth, color = linecolor)
style=:solid, width=linewidth, color=linecolor
)
apline = InspectDR.PolylineAnnotation( apline = InspectDR.PolylineAnnotation(
x[rng], y[rng], line=line, fillcolor=fillcolor x[rng],
y[rng],
line = line,
fillcolor = fillcolor,
) )
InspectDR.add(plot, apline) InspectDR.add(plot, apline)
end end
@ -278,21 +294,24 @@ For st in :shape:
linecolor = _inspectdr_mapcolor(_cycle(c, i)) linecolor = _inspectdr_mapcolor(_cycle(c, i))
c = plot_color(get_fillcolor(series), get_fillalpha(series)) c = plot_color(get_fillcolor(series), get_fillalpha(series))
fillcolor = _inspectdr_mapcolor(_cycle(c, i)) fillcolor = _inspectdr_mapcolor(_cycle(c, i))
wfrm = InspectDR.add(plot, Float64[], Float64[], id=series[:label]) wfrm = InspectDR.add(plot, Float64[], Float64[], id = series[:label])
wfrm.line = InspectDR.line( wfrm.line = InspectDR.line(
style=:none, width=linewidth, #linewidth affects glyph style = :none,
width = linewidth, #linewidth affects glyph
) )
wfrm.glyph = InspectDR.glyph( wfrm.glyph = InspectDR.glyph(
shape = INSPECTDR_GLYPH_SHAPE, size = 8, shape = INSPECTDR_GLYPH_SHAPE,
color = linecolor, fillcolor = fillcolor size = 8,
color = linecolor,
fillcolor = fillcolor,
) )
end end
elseif st in (:path, :scatter, :straightline) #, :steppre, :stepmid, :steppost) elseif st in (:path, :scatter, :straightline) #, :steppre, :stepmid, :steppost)
#NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think). #NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think).
linewidth = series[:linewidth] linewidth = series[:linewidth]
#More efficient & allows some support for markerstrokewidth: #More efficient & allows some support for markerstrokewidth:
_style = (0==linewidth ? :none : series[:linestyle]) _style = (0 == linewidth ? :none : series[:linestyle])
wfrm = InspectDR.add(plot, x, y, id=series[:label]) wfrm = InspectDR.add(plot, x, y, id = series[:label])
wfrm.line = InspectDR.line( wfrm.line = InspectDR.line(
style = _style, style = _style,
width = series[:linewidth], width = series[:linewidth],
@ -306,14 +325,18 @@ For st in :shape:
wfrm.glyph = InspectDR.glyph( wfrm.glyph = InspectDR.glyph(
shape = _inspectdr_mapglyph(series[:markershape]), shape = _inspectdr_mapglyph(series[:markershape]),
size = _inspectdr_mapglyphsize(series[:markersize]), size = _inspectdr_mapglyphsize(series[:markersize]),
color = _inspectdr_mapcolor(plot_color(get_markerstrokecolor(series), get_markerstrokealpha(series))), color = _inspectdr_mapcolor(
fillcolor = _inspectdr_mapcolor(plot_color(get_markercolor(series, clims), get_markeralpha(series))), plot_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
),
fillcolor = _inspectdr_mapcolor(
plot_color(get_markercolor(series, clims), get_markeralpha(series)),
),
) )
end end
# this is all we need to add the series_annotations text # this is all we need to add the series_annotations text
anns = series[:series_annotations] anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, x, y) for (xi, yi, str, fnt) in EachAnn(anns, x, y)
_inspectdr_add_annotations(plot, xi, yi, PlotText(str, fnt)) _inspectdr_add_annotations(plot, xi, yi, PlotText(str, fnt))
end end
return return
@ -333,74 +356,81 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
plot = sp.o plot = sp.o
strip = plot.strips[1] #Only 1 strip supported with Plots.jl strip = plot.strips[1] #Only 1 strip supported with Plots.jl
xaxis = sp[:xaxis]; yaxis = sp[:yaxis] xaxis = sp[:xaxis]
yaxis = sp[:yaxis]
xgrid_show = xaxis[:grid] xgrid_show = xaxis[:grid]
ygrid_show = yaxis[:grid] ygrid_show = yaxis[:grid]
strip.grid = InspectDR.GridRect( strip.grid = InspectDR.GridRect(
vmajor=xgrid_show, # vminor=xgrid_show, vmajor = xgrid_show, # vminor=xgrid_show,
hmajor=ygrid_show, # hminor=ygrid_show, hmajor = ygrid_show, # hminor=ygrid_show,
) )
plot.xscale = _inspectdr_getscale(xaxis[:scale], false) plot.xscale = _inspectdr_getscale(xaxis[:scale], false)
strip.yscale = _inspectdr_getscale(yaxis[:scale], true) strip.yscale = _inspectdr_getscale(yaxis[:scale], true)
xmin, xmax = axis_limits(sp, :x) xmin, xmax = axis_limits(sp, :x)
ymin, ymax = axis_limits(sp, :y) ymin, ymax = axis_limits(sp, :y)
if ispolar(sp) if ispolar(sp)
#Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax) #Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax)
rmax = NaNMath.max(abs(ymin), abs(ymax)) rmax = NaNMath.max(abs(ymin), abs(ymax))
xmin, xmax = -rmax, rmax xmin, xmax = -rmax, rmax
ymin, ymax = -rmax, rmax ymin, ymax = -rmax, rmax
end end
plot.xext_full = InspectDR.PExtents1D(xmin, xmax) plot.xext_full = InspectDR.PExtents1D(xmin, xmax)
strip.yext_full = InspectDR.PExtents1D(ymin, ymax) strip.yext_full = InspectDR.PExtents1D(ymin, ymax)
#Set current extents = full extents (needed for _eval(strip.grid,...)) #Set current extents = full extents (needed for _eval(strip.grid,...))
plot.xext = plot.xext_full plot.xext = plot.xext_full
strip.yext = strip.yext_full strip.yext = strip.yext_full
_inspectdr_setticks(sp, plot, strip, xaxis, yaxis) _inspectdr_setticks(sp, plot, strip, xaxis, yaxis)
a = plot.annotation a = plot.annotation
a.title = sp[:title] a.title = texmath2unicode(sp[:title])
a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]] a.xlabel = texmath2unicode(xaxis[:guide])
a.ylabels = [texmath2unicode(yaxis[:guide])]
l = plot.layout #Modify base layout of new object:
#IMPORTANT: Don't forget to actually register changes l = plot.layout.defaults = deepcopy(InspectDR.defaults.plotlayout)
#(TODO: need to find a better way to set layout properties) #IMPORTANT: Must deepcopy to ensure we don't change layouts of other plots.
l[:frame_canvas].fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) #Works because plot uses defaults (not user-overwritten `layout.values`)
l[:frame_canvas] = l[:frame_canvas] #register changes l.frame_canvas.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
l[:frame_data].fillcolor = _inspectdr_mapcolor(sp[:background_color_inside]) l.frame_data.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l[:frame_data] = l[:frame_data] #register changes l.frame_data.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l.font_title = InspectDR.Font(
l[:frame_data].line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis]) sp[:titlefontfamily],
l[:frame_data] = l[:frame_data] #register changes _inspectdr_mapptsize(sp[:titlefontsize]),
l[:font_title] = InspectDR.Font(sp[:titlefontfamily], color = _inspectdr_mapcolor(sp[:titlefontcolor]),
_inspectdr_mapptsize(sp[:titlefontsize]), )
color = _inspectdr_mapcolor(sp[:titlefontcolor]) #Cannot independently control fonts of axes with InspectDR:
) l.font_axislabel = InspectDR.Font(
#Cannot independently control fonts of axes with InspectDR: xaxis[:guidefontfamily],
l[:font_axislabel] = InspectDR.Font(xaxis[:guidefontfamily], _inspectdr_mapptsize(xaxis[:guidefontsize]),
_inspectdr_mapptsize(xaxis[:guidefontsize]), color = _inspectdr_mapcolor(xaxis[:guidefontcolor]),
color = _inspectdr_mapcolor(xaxis[:guidefontcolor]) )
) l.font_ticklabel = InspectDR.Font(
l[:font_ticklabel] = InspectDR.Font(xaxis[:tickfontfamily], xaxis[:tickfontfamily],
_inspectdr_mapptsize(xaxis[:tickfontsize]), _inspectdr_mapptsize(xaxis[:tickfontsize]),
color = _inspectdr_mapcolor(xaxis[:tickfontcolor]) 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.halloc_legend = 150 #TODO: compute???
l[:font_legend] = InspectDR.Font(sp[:legendfontfamily], l.font_legend = InspectDR.Font(
_inspectdr_mapptsize(sp[:legendfontsize]), sp[:legend_font_family],
color = _inspectdr_mapcolor(sp[:legendfontcolor]) _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] = l[:frame_legend] #register changes 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
end end
# called just before updating layout bounding boxes... in case you need to prep # called just before updating layout bounding boxes... in case you need to prep
# for the calcs # for the calcs
function _before_layout_calcs(plt::Plot{InspectDRBackend}) function _before_layout_calcs(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o) mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end if nothing == mplot
return
end
mplot.title = plt[:plot_title] mplot.title = plt[:plot_title]
if "" == mplot.title if "" == mplot.title
@ -409,7 +439,7 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
end end
mplot.layout[:frame].fillcolor = _inspectdr_mapcolor(plt[:background_color_outside]) mplot.layout[:frame].fillcolor = _inspectdr_mapcolor(plt[:background_color_outside])
mplot.layout[:frame] = mplot.layout[:frame] #register changes mplot.layout[:frame] = mplot.layout[:frame] #register changes
resize!(mplot.subplots, length(plt.subplots)) resize!(mplot.subplots, length(plt.subplots))
nsubplots = length(plt.subplots) nsubplots = length(plt.subplots)
for (i, sp) in enumerate(plt.subplots) for (i, sp) in enumerate(plt.subplots)
@ -453,17 +483,19 @@ end
# to fit ticks, tick labels, guides, colorbars, etc. # to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{InspectDRBackend}) function _update_min_padding!(sp::Subplot{InspectDRBackend})
plot = sp.o plot = sp.o
if !isa(plot, InspectDR.Plot2D); return sp.minpad; end if !isa(plot, InspectDR.Plot2D)
return sp.minpad
end
#Computing plotbounds with 0-BoundingBox returns required padding: #Computing plotbounds with 0-BoundingBox returns required padding:
bb = InspectDR.plotbounds(plot.layout.values, InspectDR.BoundingBox(0,0,0,0)) bb = InspectDR.plotbounds(plot.layout.values, InspectDR.BoundingBox(0, 0, 0, 0))
#NOTE: plotbounds always pads for titles, legends, etc. even if not in use. #NOTE: plotbounds always pads for titles, legends, etc. even if not in use.
#TODO: possibly zero-out items not in use?? #TODO: possibly zero-out items not in use??
# add in the user-specified margin to InspectDR padding: # add in the user-specified margin to InspectDR padding:
leftpad = abs(bb.xmin)*px + sp[:left_margin] leftpad = abs(bb.xmin) * px + sp[:left_margin]
toppad = abs(bb.ymin)*px + sp[:top_margin] toppad = abs(bb.ymin) * px + sp[:top_margin]
rightpad = abs(bb.xmax)*px + sp[:right_margin] rightpad = abs(bb.xmax) * px + sp[:right_margin]
bottompad = abs(bb.ymax)*px + sp[:bottom_margin] bottompad = abs(bb.ymax) * px + sp[:bottom_margin]
sp.minpad = (leftpad, toppad, rightpad, bottompad) sp.minpad = (leftpad, toppad, rightpad, bottompad)
end end
@ -472,21 +504,25 @@ end
# Override this to update plot items (title, xlabel, etc), and add annotations (plotattributes[:annotations]) # Override this to update plot items (title, xlabel, etc), and add annotations (plotattributes[:annotations])
function _update_plot_object(plt::Plot{InspectDRBackend}) function _update_plot_object(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o) mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end if nothing == mplot
return
end
mplot.bblist = InspectDR.BoundingBox[] mplot.bblist = InspectDR.BoundingBox[]
for (i, sp) in enumerate(plt.subplots) for (i, sp) in enumerate(plt.subplots)
figw, figh = sp.plt[:size] figw, figh = sp.plt[:size]
pcts = bbox_to_pcts(sp.bbox, figw*px, figh*px) pcts = bbox_to_pcts(sp.bbox, figw * px, figh * px)
_left, _bottom, _width, _height = pcts _left, _bottom, _width, _height = pcts
ymax = 1.0-_bottom ymax = 1.0 - _bottom
ymin = ymax - _height ymin = ymax - _height
bb = InspectDR.BoundingBox(_left, _left+_width, ymin, ymax) bb = InspectDR.BoundingBox(_left, _left + _width, ymin, ymax)
push!(mplot.bblist, bb) push!(mplot.bblist, bb)
end end
gplot = _inspectdr_getgui(plt.o) gplot = _inspectdr_getgui(plt.o)
if nothing == gplot; return; end if nothing == gplot
return
end
gplot.src = mplot #Ensure still references current plot gplot.src = mplot #Ensure still references current plot
InspectDR.refresh(gplot) InspectDR.refresh(gplot)
@ -522,7 +558,9 @@ end
# Display/show the plot (open a GUI window, or browser page, for example). # Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{InspectDRBackend}) function _display(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o) mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end if nothing == mplot
return
end
gplot = _inspectdr_getgui(plt.o) gplot = _inspectdr_getgui(plt.o)
if nothing == gplot if nothing == gplot

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,13 @@ function _plotly_framestyle(style::Symbol)
return style return style
else else
default_style = get((semi = :box, origin = :zerolines), style, :axes) default_style = get((semi = :box, origin = :zerolines), style, :axes)
@warn("Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was cosen instead.") @warn(
"Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was chosen instead."
)
default_style default_style
end end
end end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
using UUIDs using UUIDs
@ -23,7 +24,7 @@ function labelfunc(scale::Symbol, backend::PlotlyBackend)
texfunc = labelfunc_tex(scale) texfunc = labelfunc_tex(scale)
function (x) function (x)
tex_x = texfunc(x) tex_x = texfunc(x)
sup_x = replace( tex_x, r"\^{(.*)}"=>s"<sup>\1</sup>" ) sup_x = replace(tex_x, r"\^{(.*)}" => s"<sup>\1</sup>")
# replace dash with \minus (U+2212) # replace dash with \minus (U+2212)
replace(sup_x, "-" => "") replace(sup_x, "-" => "")
end end
@ -32,30 +33,25 @@ end
function plotly_font(font::Font, color = font.color) function plotly_font(font::Font, color = font.color)
KW( KW(
:family => font.family, :family => font.family,
:size => round(Int, font.pointsize*1.4), :size => round(Int, font.pointsize * 1.4),
:color => rgba_string(color), :color => rgba_string(color),
) )
end end
function plotly_annotation_dict(x, y, val; xref = "paper", yref = "paper")
function plotly_annotation_dict(x, y, val; xref="paper", yref="paper") KW(:text => val, :xref => xref, :x => x, :yref => yref, :y => y, :showarrow => false)
KW(
:text => val,
:xref => xref,
:x => x,
:yref => yref,
:y => y,
:showarrow => false,
)
end end
function plotly_annotation_dict(x, y, ptxt::PlotText; xref="paper", yref="paper") function plotly_annotation_dict(x, y, ptxt::PlotText; xref = "paper", yref = "paper")
merge(plotly_annotation_dict(x, y, ptxt.str; xref=xref, yref=yref), KW( merge(
:font => plotly_font(ptxt.font), plotly_annotation_dict(x, y, ptxt.str; xref = xref, yref = yref),
:xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign, KW(
:yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign, :font => plotly_font(ptxt.font),
:rotation => -ptxt.font.rotation, :xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign,
)) :yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign,
:rotation => -ptxt.font.rotation,
),
)
end end
# function get_annotation_dict_for_arrow(plotattributes::KW, xyprev::Tuple, xy::Tuple, a::Arrow) # function get_annotation_dict_for_arrow(plotattributes::KW, xyprev::Tuple, xy::Tuple, a::Arrow)
@ -100,9 +96,9 @@ function plotly_apply_aspect_ratio(sp::Subplot, plotarea, pcts)
if aspect_ratio == :equal if aspect_ratio == :equal
aspect_ratio = 1.0 aspect_ratio = 1.0
end end
xmin,xmax = axis_limits(sp, :x) xmin, xmax = axis_limits(sp, :x)
ymin,ymax = axis_limits(sp, :y) ymin, ymax = axis_limits(sp, :y)
want_ratio = ((xmax-xmin) / (ymax-ymin)) / aspect_ratio want_ratio = ((xmax - xmin) / (ymax - ymin)) / aspect_ratio
parea_ratio = width(plotarea) / height(plotarea) parea_ratio = width(plotarea) / height(plotarea)
if want_ratio > parea_ratio if want_ratio > parea_ratio
# need to shrink y # need to shrink y
@ -118,33 +114,34 @@ function plotly_apply_aspect_ratio(sp::Subplot, plotarea, pcts)
pcts pcts
end end
# this method gets the start/end in percentage of the canvas for this axis direction # this method gets the start/end in percentage of the canvas for this axis direction
function plotly_domain(sp::Subplot) function plotly_domain(sp::Subplot)
figw, figh = sp.plt[:size] figw, figh = sp.plt[:size]
pcts = bbox_to_pcts(sp.plotarea, figw*px, figh*px) pcts = bbox_to_pcts(sp.plotarea, figw * px, figh * px)
pcts = plotly_apply_aspect_ratio(sp, sp.plotarea, pcts) pcts = plotly_apply_aspect_ratio(sp, sp.plotarea, pcts)
x_domain = [pcts[1], pcts[1] + pcts[3]] x_domain = [pcts[1], pcts[1] + pcts[3]]
y_domain = [pcts[2], pcts[2] + pcts[4]] y_domain = [pcts[2], pcts[2] + pcts[4]]
return x_domain, y_domain return x_domain, y_domain
end end
function plotly_axis(axis, sp, anchor = nothing, domain = nothing) function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
letter = axis[:letter] letter = axis[:letter]
framestyle = sp[:framestyle] framestyle = sp[:framestyle]
ax = KW( ax = KW(
:visible => framestyle != :none, :visible => framestyle != :none,
:title => axis[:guide], :title => axis[:guide],
:showgrid => axis[:grid], :showgrid => axis[:grid],
:gridcolor => rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])), :gridcolor =>
:gridwidth => axis[:gridlinewidth], rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])),
:zeroline => framestyle == :zerolines, :gridwidth => axis[:gridlinewidth],
:zeroline => framestyle == :zerolines,
:zerolinecolor => rgba_string(axis[:foreground_color_axis]), :zerolinecolor => rgba_string(axis[:foreground_color_axis]),
:showline => framestyle in (:box, :axes) && axis[:showaxis], :showline => framestyle in (:box, :axes) && axis[:showaxis],
:linecolor => rgba_string(plot_color(axis[:foreground_color_axis])), :linecolor => rgba_string(plot_color(axis[:foreground_color_axis])),
:ticks => axis[:tick_direction] == :out ? "outside" : "inside", :ticks =>
:mirror => framestyle == :box, axis[:tick_direction] === :out ? "outside" :
axis[:tick_direction] === :in ? "inside" : "",
:mirror => framestyle == :box,
:showticklabels => axis[:showaxis], :showticklabels => axis[:showaxis],
) )
if anchor !== nothing if anchor !== nothing
@ -165,7 +162,9 @@ function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
if !(axis[:ticks] in (nothing, :none, false)) if !(axis[:ticks] in (nothing, :none, false))
ax[:titlefont] = plotly_font(guidefont(axis)) ax[:titlefont] = plotly_font(guidefont(axis))
ax[:tickfont] = plotly_font(tickfont(axis)) ax[:tickfont] = plotly_font(tickfont(axis))
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis]) ax[:tickcolor] =
framestyle in (:zerolines, :grid) || !axis[:showaxis] ?
rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
ax[:linecolor] = rgba_string(axis[:foreground_color_axis]) ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
# ticks # ticks
@ -194,10 +193,7 @@ function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
end end
function plotly_polaraxis(sp::Subplot, axis::Axis) function plotly_polaraxis(sp::Subplot, axis::Axis)
ax = KW( ax = KW(:visible => axis[:showaxis], :showline => axis[:grid])
:visible => axis[:showaxis],
:showline => axis[:grid],
)
if axis[:letter] == :x if axis[:letter] == :x
ax[:range] = rad2deg.(axis_limits(sp, :x)) ax[:range] = rad2deg.(axis_limits(sp, :x))
@ -215,7 +211,7 @@ function plotly_layout(plt::Plot)
w, h = plt[:size] w, h = plt[:size]
plotattributes_out[:width], plotattributes_out[:height] = w, h plotattributes_out[:width], plotattributes_out[:height] = w, h
plotattributes_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside]) plotattributes_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
plotattributes_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20) plotattributes_out[:margin] = KW(:l => 0, :b => 20, :r => 0, :t => 20)
plotattributes_out[:annotations] = KW[] plotattributes_out[:annotations] = KW[]
@ -236,9 +232,12 @@ function plotly_layout(plt::Plot)
else else
0.5 * (left(bb) + right(bb)) 0.5 * (left(bb) + right(bb))
end end
titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px) titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w * px, h * px)
title_font = font(titlefont(sp), :top) title_font = font(titlefont(sp), :top)
push!(plotattributes_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font))) push!(
plotattributes_out[:annotations],
plotly_annotation_dict(titlex, titley, text(sp[:title], title_font)),
)
end end
plotattributes_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside]) plotattributes_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
@ -247,8 +246,10 @@ function plotly_layout(plt::Plot)
sp[:framestyle] = _plotly_framestyle(sp[:framestyle]) sp[:framestyle] = _plotly_framestyle(sp[:framestyle])
if ispolar(sp) if ispolar(sp)
plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis]) plotattributes_out[Symbol("angularaxis$(spidx)")] =
plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis]) plotly_polaraxis(sp, sp[:xaxis])
plotattributes_out[Symbol("radialaxis$(spidx)")] =
plotly_polaraxis(sp, sp[:yaxis])
else else
x_domain, y_domain = plotly_domain(sp) x_domain, y_domain = plotly_domain(sp)
if RecipesPipeline.is3d(sp) if RecipesPipeline.is3d(sp)
@ -263,15 +264,15 @@ function plotly_layout(plt::Plot)
#2.6 multiplier set camera eye such that whole plot can be seen #2.6 multiplier set camera eye such that whole plot can be seen
:camera => KW( :camera => KW(
:eye => KW( :eye => KW(
:x => cosd(azim)*sind(theta)*2.6, :x => cosd(azim) * sind(theta) * 2.6,
:y => sind(azim)*sind(theta)*2.6, :y => sind(azim) * sind(theta) * 2.6,
:z => cosd(theta)*2.6, :z => cosd(theta) * 2.6,
), ),
), ),
) )
else else
plotattributes_out[Symbol("xaxis$(x_idx)")] = plotattributes_out[Symbol("xaxis$(x_idx)")] =
plotly_axis(sp[:xaxis], sp, string("y", y_idx) , x_domain) plotly_axis(sp[:xaxis], sp, string("y", y_idx), x_domain)
# don't allow yaxis to be reupdated/reanchored in a linked subplot # don't allow yaxis to be reupdated/reanchored in a linked subplot
if spidx == y_idx if spidx == y_idx
plotattributes_out[Symbol("yaxis$(y_idx)")] = plotattributes_out[Symbol("yaxis$(y_idx)")] =
@ -285,16 +286,28 @@ function plotly_layout(plt::Plot)
# annotations # annotations
for ann in sp[:annotations] for ann in sp[:annotations]
append!(plotattributes_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")]) append!(
plotattributes_out[:annotations],
KW[plotly_annotation_dict(
locate_annotation(sp, ann...)...;
xref = "x$(x_idx)",
yref = "y$(y_idx)",
)],
)
end end
# series_annotations # series_annotations
for series in series_list(sp) for series in series_list(sp)
anns = series[:series_annotations] anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y]) for (xi, yi, str, fnt) in EachAnn(anns, series[:x], series[:y])
push!(plotattributes_out[:annotations], plotly_annotation_dict( push!(
xi, plotattributes_out[:annotations],
yi, plotly_annotation_dict(
PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)") xi,
yi,
PlotText(str, fnt);
xref = "x$(x_idx)",
yref = "y$(y_idx)",
),
) )
end end
end end
@ -317,31 +330,30 @@ function plotly_layout(plt::Plot)
end end
# turn off hover if nothing's using it # turn off hover if nothing's using it
if all(series -> series.plotattributes[:hover] in (false,:none), plt.series_list) if all(series -> series.plotattributes[:hover] in (false, :none), plt.series_list)
plotattributes_out[:hovermode] = "none" plotattributes_out[:hovermode] = "none"
end end
plotattributes_out = recursive_merge(plotattributes_out, plt.attr[:extra_plot_kwargs]) plotattributes_out = recursive_merge(plotattributes_out, plt.attr[:extra_plot_kwargs])
end end
function plotly_add_legend!(plotattributes_out::KW, sp::Subplot) function plotly_add_legend!(plotattributes_out::KW, sp::Subplot)
plotattributes_out[:showlegend] = sp[:legend] != :none plotattributes_out[:showlegend] = sp[:legend_position] != :none
legend_position = plotly_legend_pos(sp[:legend]) legend_position = plotly_legend_pos(sp[:legend_position])
if sp[:legend] != :none if sp[:legend_position] != :none
plotattributes_out[:legend] = KW( plotattributes_out[:legend_position] = KW(
:bgcolor => rgba_string(sp[:background_color_legend]), :bgcolor => rgba_string(sp[:legend_background_color]),
:bordercolor => rgba_string(sp[:foreground_color_legend]), :bordercolor => rgba_string(sp[:legend_foreground_color]),
:borderwidth => 1, :borderwidth => 1,
:traceorder => "normal", :traceorder => "normal",
:xanchor => legend_position.xanchor, :xanchor => legend_position.xanchor,
:yanchor => legend_position.yanchor, :yanchor => legend_position.yanchor,
:font => plotly_font(legendfont(sp)), :font => plotly_font(legendfont(sp)),
:tracegroupgap => 0, :tracegroupgap => 0,
:x => legend_position.coords[1], :x => legend_position.coords[1],
:y => legend_position.coords[2], :y => legend_position.coords[2],
:title => KW( :title => KW(
:text => sp[:legendtitle] === nothing ? "" : string(sp[:legendtitle]), :text => sp[:legend_title] === nothing ? "" : string(sp[:legend_title]),
:font => plotly_font(legendtitlefont(sp)), :font => plotly_font(legendtitlefont(sp)),
), ),
) )
@ -350,6 +362,7 @@ end
function plotly_legend_pos(pos::Symbol) function plotly_legend_pos(pos::Symbol)
xleft = 0.07 xleft = 0.07
xright = 1.0
ybot = 0.07 ybot = 0.07
ytop = 1.0 ytop = 1.0
xcenter = 0.55 xcenter = 0.55
@ -360,55 +373,71 @@ function plotly_legend_pos(pos::Symbol)
xouterright = 1.05 xouterright = 1.05
xouterleft = -0.15 xouterleft = -0.15
plotly_legend_position_mapping = ( 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"), left = (coords = [xleft, ycenter], xanchor = "left", yanchor = "middle"),
top = (coords = [xcenter, ytop], xanchor = "center", yanchor = "top"), top = (coords = [xcenter, ytop], xanchor = "center", yanchor = "top"),
bottom = (coords = [xcenter, ybot], xanchor = "center", yanchor = "bottom"), bottom = (coords = [xcenter, ybot], xanchor = "center", yanchor = "bottom"),
bottomleft = (coords = [xleft, ybot], xanchor = "left", yanchor = "bottom"), bottomleft = (coords = [xleft, ybot], xanchor = "left", yanchor = "bottom"),
bottomright = (coords = [1.0, ybot], xanchor = "right", yanchor = "bottom"), bottomright = (coords = [xright, ybot], xanchor = "right", yanchor = "bottom"),
topright = (coords = [1.0, 1.0], xanchor = "right", yanchor = "top"), topright = (coords = [xright, ytop], xanchor = "right", yanchor = "top"),
topleft = (coords = [xleft, 1.0], xanchor = "left", yanchor = "top"), topleft = (coords = [xleft, ytop], xanchor = "left", yanchor = "top"),
outertop =(coords = [center, youtertop ], xanchor = "upper", yanchor = "middle"), outertop = (coords = [center, youtertop], xanchor = "upper", yanchor = "middle"),
outerbottom =(coords = [center, youterbot], xanchor = "lower", yanchor = "middle"), outerbottom = (coords = [center, youterbot], xanchor = "lower", yanchor = "middle"),
outerleft =(coords = [xouterleft, center], xanchor = "left", yanchor = "top"), outerleft = (coords = [xouterleft, center], xanchor = "left", yanchor = "top"),
outerright =(coords = [xouterright, center], xanchor = "right", yanchor = "top"), outerright = (coords = [xouterright, center], xanchor = "right", yanchor = "top"),
outertopleft =(coords = [xouterleft, ytop], xanchor = "upper", yanchor = "left"), outertopleft = (coords = [xouterleft, ytop], xanchor = "upper", yanchor = "left"),
outertopright = (coords = [xouterright, ytop], xanchor = "upper", yanchor = "right"), outertopright = (
outerbottomleft =(coords = [xouterleft, ybot], xanchor = "lower", yanchor = "left"), coords = [xouterright, ytop],
outerbottomright =(coords = [xouterright, ybot], xanchor = "lower", yanchor = "right"), xanchor = "upper",
default = (coords = [1.0, 1.0], xanchor = "auto", yanchor = "auto") yanchor = "right",
),
outerbottomleft = (
coords = [xouterleft, ybot],
xanchor = "lower",
yanchor = "left",
),
outerbottomright = (
coords = [xouterright, ybot],
xanchor = "lower",
yanchor = "right",
),
default = (coords = [xright, ytop], xanchor = "auto", yanchor = "auto"),
) )
legend_position = get(plotly_legend_position_mapping, pos, plotly_legend_position_mapping.default) legend_position =
get(plotly_legend_position_mapping, pos, plotly_legend_position_mapping.default)
end end
plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = (coords=v, xanchor="left", yanchor="top") plotly_legend_pos(v::Tuple{S,T}) where {S<:Real,T<:Real} =
(coords = v, xanchor = "left", yanchor = "top")
plotly_legend_pos(theta::Real) = plotly_legend_pos((theta, :inner)) plotly_legend_pos(theta::Real) = plotly_legend_pos((theta, :inner))
function plotly_legend_pos(v::Tuple{S,Symbol}) where S<:Real function plotly_legend_pos(v::Tuple{S,Symbol}) where {S<:Real}
(s,c) = sincosd(v[1]) (s, c) = sincosd(v[1])
xanchors = ["left", "center", "right"] xanchors = ["left", "center", "right"]
yanchors = ["bottom", "middle", "top"] yanchors = ["bottom", "middle", "top"]
if v[2] === :inner if v[2] === :inner
rect = (0.07,0.5,1.0,0.07,0.52,1.0) rect = (0.07, 0.5, 1.0, 0.07, 0.52, 1.0)
xanchor = xanchors[legend_anchor_index(c)] xanchor = xanchors[legend_anchor_index(c)]
yanchor = yanchors[legend_anchor_index(s)] yanchor = yanchors[legend_anchor_index(s)]
else else
rect = (-0.15,0.5,1.05,-0.15,0.52,1.1) rect = (-0.15, 0.5, 1.05, -0.15, 0.52, 1.1)
xanchor = xanchors[4-legend_anchor_index(c)] xanchor = xanchors[4 - legend_anchor_index(c)]
yanchor = yanchors[4-legend_anchor_index(s)] yanchor = yanchors[4 - legend_anchor_index(s)]
end end
return (coords=legend_pos_from_angle(v[1],rect...), xanchor=xanchor, yanchor=yanchor) return (
coords = legend_pos_from_angle(v[1], rect...),
xanchor = xanchor,
yanchor = yanchor,
)
end end
function plotly_layout_json(plt::Plot) function plotly_layout_json(plt::Plot)
JSON.json(plotly_layout(plt), 4) JSON.json(plotly_layout(plt), 4)
end end
plotly_colorscale(cg::ColorGradient, α = nothing) = plotly_colorscale(cg::ColorGradient, α = nothing) =
[[v, rgba_string(plot_color(cg.colors[v], α))] for v in cg.values] [[v, rgba_string(plot_color(cg.colors[v], α))] for v in cg.values]
function plotly_colorscale(c::AbstractVector{<:Colorant}, α = nothing) function plotly_colorscale(c::AbstractVector{<:Colorant}, α = nothing)
@ -427,13 +456,12 @@ function plotly_colorscale(cg::PlotUtils.CategoricalColorGradient, α = nothing)
cinds = repeat(1:n, inner = 2) cinds = repeat(1:n, inner = 2)
vinds = vcat((i:(i + 1) for i in 1:n)...) vinds = vcat((i:(i + 1) for i in 1:n)...)
return [ return [
[cg.values[vinds[i]], rgba_string(plot_color(color_list(cg)[cinds[i]], α))] [cg.values[vinds[i]], rgba_string(plot_color(color_list(cg)[cinds[i]], α))] for
for i in eachindex(cinds) i in eachindex(cinds)
] ]
end end
plotly_colorscale(c, α = nothing) = plotly_colorscale(_as_gradient(c), α) plotly_colorscale(c, α = nothing) = plotly_colorscale(_as_gradient(c), α)
get_plotly_marker(k, def) = get( get_plotly_marker(k, def) = get(
( (
rect = "square", rect = "square",
@ -460,12 +488,11 @@ function plotly_link_indicies(plt::Plot, sp::Subplot)
x_idx, y_idx x_idx, y_idx
end end
# the Shape contructor will automatically close the shape. since we need it closed, # the Shape contructor will automatically close the shape. since we need it closed,
# we split by NaNs and then construct/destruct the shapes to get the closed coords # we split by NaNs and then construct/destruct the shapes to get the closed coords
function plotly_close_shapes(x, y) function plotly_close_shapes(x, y)
xs, ys = nansplit(x), nansplit(y) xs, ys = nansplit(x), nansplit(y)
for i=eachindex(xs) for i in eachindex(xs)
shape = Shape(xs[i], ys[i]) shape = Shape(xs[i], ys[i])
xs[i], ys[i] = coords(shape) xs[i], ys[i] = coords(shape)
end end
@ -473,12 +500,12 @@ function plotly_close_shapes(x, y)
end end
function plotly_data(series::Series, letter::Symbol, data) function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)] axis = series[:subplot][get_attr_symbol(letter, :axis)]
data = if axis[:ticks] == :native && data !== nothing data = if axis[:ticks] == :native && data !== nothing
plotly_native_data(axis, data) plotly_native_data(axis, data)
else else
data data
end end
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe, :mesh3d) if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe, :mesh3d)
@ -511,7 +538,9 @@ function plotly_convert_to_datetime(x::AbstractArray, formatter::Function)
elseif formatter == timeformatter elseif formatter == timeformatter
map(xi -> string(Dates.Date(Dates.now()), " ", formatter(xi)), x) map(xi -> string(Dates.Date(Dates.now()), " ", formatter(xi)), x)
else else
error("Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter") error(
"Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter",
)
end end
end end
#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z) #ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
@ -549,11 +578,12 @@ function plotly_series(plt::Plot, series::Series)
x, y = straightline_data(series, 100) x, y = straightline_data(series, 100)
z = series[:z] z = series[:z]
else else
x, y, z = series[:x], series[:y], series[:z] x, y, z = series[:x], series[:y], series[:z]
end end
x, y, z = (plotly_data(series, letter, data) x, y, z = (
for (letter, data) in zip((:x, :y, :z), (x, y, z)) plotly_data(series, letter, data) for
(letter, data) in zip((:x, :y, :z), (x, y, z))
) )
plotattributes_out[:name] = series[:label] plotattributes_out[:name] = series[:label]
@ -561,7 +591,8 @@ function plotly_series(plt::Plot, series::Series)
isscatter = st in (:scatter, :scatter3d, :scattergl) isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none hasmarker = isscatter || series[:markershape] != :none
hasline = st in (:path, :path3d, :straightline) hasline = st in (:path, :path3d, :straightline)
hasfillrange = st in (:path, :scatter, :scattergl, :straightline) && hasfillrange =
st in (:path, :scatter, :scattergl, :straightline) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple)) (isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
plotattributes_out[:colorbar] = KW(:title => sp[:colorbar_title]) plotattributes_out[:colorbar] = KW(:title => sp[:colorbar_title])
@ -579,32 +610,63 @@ function plotly_series(plt::Plot, series::Series)
y = heatmap_edges(y, sp[:yaxis][:scale]) y = heatmap_edges(y, sp[:yaxis][:scale])
plotattributes_out[:type] = "heatmap" plotattributes_out[:type] = "heatmap"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:colorscale] =
plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:showscale] = hascolorbar(sp) plotattributes_out[:showscale] = hascolorbar(sp)
elseif st == :contour elseif st == :contour
filled = isfilledcontour(series) filled = isfilledcontour(series)
plotattributes_out[:type] = "contour" plotattributes_out[:type] = "contour"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
plotattributes_out[:ncontours] = series[:levels] + 2 plotattributes_out[:contours] = KW(
plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true) :coloring => filled ? "fill" : "lines",
plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha]) :showlabels => series[:contour_labels] == true,
)
# Plotly does not support arbitrary sets of contours
# (https://github.com/plotly/plotly.js/issues/4503)
# so we distinguish AbstractRanges and AbstractVectors
let levels = series[:levels]
if levels isa AbstractRange
plotattributes_out[:contours][:start] = first(levels)
plotattributes_out[:contours][:end] = last(levels)
plotattributes_out[:contours][:size] = step(levels)
elseif levels isa AVec
levels_range =
range(first(levels), stop = last(levels), length = length(levels))
plotattributes_out[:contours][:start] = first(levels_range)
plotattributes_out[:contours][:end] = last(levels_range)
plotattributes_out[:contours][:size] = step(levels_range)
@warn(
"setting arbitrary contour levels with Plotly backend is not supported; " *
"use a range to set equally-spaced contours or an integer to set the " *
"approximate number of contours with the keyword `levels`. " *
"Setting levels to $(levels_range)"
)
elseif levels isa Integer
plotattributes_out[:ncontours] = levels + 2
end
end
plotattributes_out[:colorscale] =
plotly_colorscale(series[:linecolor], series[:linealpha])
plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series) plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series)
elseif st in (:surface, :wireframe) elseif st in (:surface, :wireframe)
plotattributes_out[:type] = "surface" plotattributes_out[:type] = "surface"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
if st == :wireframe if st == :wireframe
plotattributes_out[:hidesurface] = true plotattributes_out[:hidesurface] = true
wirelines = KW( wirelines = KW(
:show => true, :show => true,
:color => rgba_string(plot_color(series[:linecolor], series[:linealpha])), :color =>
rgba_string(plot_color(series[:linecolor], series[:linealpha])),
:highlightwidth => series[:linewidth], :highlightwidth => series[:linewidth],
) )
plotattributes_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines) plotattributes_out[:contours] =
KW(:x => wirelines, :y => wirelines, :z => wirelines)
plotattributes_out[:showscale] = false plotattributes_out[:showscale] = false
else else
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:colorscale] =
plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = series[:fillalpha] plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] !== nothing if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z]) plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
@ -612,24 +674,45 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:showscale] = hascolorbar(sp) plotattributes_out[:showscale] = hascolorbar(sp)
end end
elseif st == :mesh3d elseif st == :mesh3d
plotattributes_out[:type] = "mesh3d" plotattributes_out[:type] = "mesh3d"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
if series[:connections] !== nothing if series[:connections] !== nothing
if typeof(series[:connections]) <: Tuple{Array,Array,Array} if typeof(series[:connections]) <: Tuple{Array,Array,Array}
i,j,k = series[:connections] # 0-based indexing
if !(length(i) == length(j) == length(k)) i, j, k = series[:connections]
throw(ArgumentError("Argument connections must consist of equally sized arrays.")) if !(length(i) == length(j) == length(k))
end throw(
plotattributes_out[:i] = i ArgumentError(
plotattributes_out[:j] = j "Argument connections must consist of equally sized arrays.",
plotattributes_out[:k] = k ),
else )
throw(ArgumentError("Argument connections has to be a tuple of three arrays.")) end
end plotattributes_out[:i] = i
end plotattributes_out[:j] = j
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:k] = k
plotattributes_out[:color] = rgba_string(plot_color(series[:fillcolor], series[:fillalpha])) 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 either a tuple of three arrays (0-based indexing)
or an AbstractVector{NTuple{3,Int}} (1-based indexing).",
),
)
end
end
plotattributes_out[:colorscale] =
plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:color] =
rgba_string(plot_color(series[:fillcolor], series[:fillalpha]))
plotattributes_out[:opacity] = series[:fillalpha] plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] !== nothing if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z]) plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
@ -644,26 +727,39 @@ function plotly_series(plt::Plot, series::Series)
if hasmarker if hasmarker
inds = eachindex(x) inds = eachindex(x)
plotattributes_out[:marker] = KW( plotattributes_out[:marker] = KW(
:symbol => get_plotly_marker(series[:markershape], string(series[:markershape])), :symbol =>
get_plotly_marker(series[:markershape], string(series[:markershape])),
# :opacity => series[:markeralpha], # :opacity => series[:markeralpha],
:size => 2 * _cycle(series[:markersize], inds), :size => 2 * _cycle(series[:markersize], inds),
:color => rgba_string.(plot_color.(get_markercolor.(series, inds), get_markeralpha.(series, inds))), :color =>
rgba_string.(
plot_color.(
get_markercolor.(series, inds),
get_markeralpha.(series, inds),
),
),
:line => KW( :line => KW(
:color => rgba_string.(plot_color.(get_markerstrokecolor.(series, inds), get_markerstrokealpha.(series, inds))), :color =>
rgba_string.(
plot_color.(
get_markerstrokecolor.(series, inds),
get_markerstrokealpha.(series, inds),
),
),
:width => _cycle(series[:markerstrokewidth], inds), :width => _cycle(series[:markerstrokewidth], inds),
), ),
) )
end end
plotly_polar!(plotattributes_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(plotattributes_out, series[:hover]) plotly_adjust_hover_label!(plotattributes_out, series[:hover])
return [plotattributes_out] return [merge(plotattributes_out, series[:extra_kwargs])]
end end
function plotly_series_shapes(plt::Plot, series::Series, clims) function plotly_series_shapes(plt::Plot, series::Series, clims)
segments = collect(series_segments(series)) segments = series_segments(series; check = true)
plotattributes_outs = Vector{KW}(undef, length(segments)) plotattributes_outs = [KW() for _ in 1:length(segments)]
# TODO: create a plotattributes_out for each polygon # TODO: create a plotattributes_out for each polygon
# x, y = series[:x], series[:y] # x, y = series[:x], series[:y]
@ -677,41 +773,52 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
:legendgroup => series[:label], :legendgroup => series[:label],
) )
x, y = (plotly_data(series, letter, data) x, y = (
for (letter, data) in zip((:x, :y), shape_data(series, 100)) plotly_data(series, letter, data) for
(letter, data) in zip((:x, :y), shape_data(series, 100))
) )
for segment in segments for (k, segment) in enumerate(segments)
i, rng = segment.attr_index, segment.range i, rng = segment.attr_index, segment.range
length(rng) < 2 && continue length(rng) < 2 && continue
# to draw polygons, we actually draw lines with fill # to draw polygons, we actually draw lines with fill
plotattributes_out = merge(plotattributes_base, KW( plotattributes_out = merge(
:type => "scatter", plotattributes_base,
:mode => "lines", KW(
:x => vcat(x[rng], x[rng[1]]), :type => "scatter",
:y => vcat(y[rng], y[rng[1]]), :mode => "lines",
:fill => "tozeroy", :x => vcat(x[rng], x[rng[1]]),
:fillcolor => rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))), :y => vcat(y[rng], y[rng[1]]),
)) :fill => "tozeroy",
:fillcolor => rgba_string(
plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
),
),
)
if series[:markerstrokewidth] > 0 if series[:markerstrokewidth] > 0
plotattributes_out[:line] = KW( plotattributes_out[:line] = KW(
:color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))), :color => rgba_string(
plot_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
),
:width => get_linewidth(series, i), :width => get_linewidth(series, i),
:dash => string(get_linestyle(series, i)), :dash => string(get_linestyle(series, i)),
) )
end end
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false plotattributes_out[:showlegend] = k == 1 ? should_add_to_legend(series) : false
plotly_polar!(plotattributes_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(plotattributes_out, _cycle(series[:hover], i)) plotly_adjust_hover_label!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[i] = plotattributes_out plotattributes_outs[k] = merge(plotattributes_out, series[:extra_kwargs])
end end
if series[:fill_z] !== nothing if series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:line_z] !== nothing elseif series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:marker_z] !== nothing elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker)) push!(
plotattributes_outs,
plotly_colorbar_hack(series, plotattributes_base, :marker),
)
end end
plotattributes_outs plotattributes_outs
end end
@ -722,37 +829,46 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
isscatter = st in (:scatter, :scatter3d, :scattergl) isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none hasmarker = isscatter || series[:markershape] != :none
hasline = st in (:path, :path3d, :straightline) hasline = st in (:path, :path3d, :straightline)
hasfillrange = st in (:path, :scatter, :scattergl, :straightline) && hasfillrange =
st in (:path, :scatter, :scattergl, :straightline) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple)) (isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = collect(series_segments(series, st)) segments = collect(series_segments(series, st))
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments)) plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1) * length(segments))
needs_scatter_fix = !isscatter && hasmarker && !any(isnan,y) && length(segments) > 1 needs_scatter_fix = !isscatter && hasmarker && !any(isnan, y) && length(segments) > 1
for (k, segment) in enumerate(segments) for (k, segment) in enumerate(segments)
i, rng = segment.attr_index, segment.range i, rng = segment.attr_index, segment.range
plotattributes_out = deepcopy(plotattributes_base) plotattributes_out = deepcopy(plotattributes_base)
plotattributes_out[:showlegend] = k==1 ? should_add_to_legend(series) : false plotattributes_out[:showlegend] = k == 1 ? should_add_to_legend(series) : false
plotattributes_out[:legendgroup] = series[:label] plotattributes_out[:legendgroup] = series[:label]
# set the type # set the type
if st in (:path, :scatter, :scattergl, :straightline) if st in (:path, :scatter, :scattergl, :straightline)
plotattributes_out[:type] = st==:scattergl ? "scattergl" : "scatter" plotattributes_out[:type] = st == :scattergl ? "scattergl" : "scatter"
plotattributes_out[:mode] = if hasmarker plotattributes_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers" hasline ? "lines+markers" : "markers"
else else
hasline ? "lines" : "none" hasline ? "lines" : "none"
end end
if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple) if series[:fillrange] == true ||
series[:fillrange] == 0 ||
isa(series[:fillrange], Tuple)
plotattributes_out[:fill] = "tozeroy" plotattributes_out[:fill] = "tozeroy"
plotattributes_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))) plotattributes_out[:fillcolor] = rgba_string(
elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real} plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
)
elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real},Real}
plotattributes_out[:fill] = "tonexty" plotattributes_out[:fill] = "tonexty"
plotattributes_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))) plotattributes_out[:fillcolor] = rgba_string(
plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
)
elseif !(series[:fillrange] in (false, nothing)) elseif !(series[:fillrange] in (false, nothing))
@warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])") @warn(
"fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])"
)
end end
plotattributes_out[:x], plotattributes_out[:y] = x[rng], y[rng] plotattributes_out[:x], plotattributes_out[:y] = x[rng], y[rng]
@ -763,20 +879,32 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
else else
hasline ? "lines" : "none" hasline ? "lines" : "none"
end end
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x[rng], y[rng], z[rng] plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] =
x[rng], y[rng], z[rng]
end end
# add "marker" # add "marker"
if hasmarker if hasmarker
mcolor = rgba_string(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) mcolor = rgba_string(
lcolor = rgba_string(plot_color(get_markerstrokecolor(series, i), get_markerstrokealpha(series, i))) plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i)),
)
lcolor = rgba_string(
plot_color(
get_markerstrokecolor(series, i),
get_markerstrokealpha(series, i),
),
)
plotattributes_out[:marker] = KW( plotattributes_out[:marker] = KW(
:symbol => get_plotly_marker(_cycle(series[:markershape], i), string(_cycle(series[:markershape], i))), :symbol => get_plotly_marker(
_cycle(series[:markershape], i),
string(_cycle(series[:markershape], i)),
),
# :opacity => needs_scatter_fix ? [1, 0] : 1, # :opacity => needs_scatter_fix ? [1, 0] : 1,
:size => 2 * _cycle(series[:markersize], i), :size => 2 * _cycle(series[:markersize], i),
:color => needs_scatter_fix ? [mcolor, "rgba(0, 0, 0, 0.000)"] : mcolor, :color => needs_scatter_fix ? [mcolor, "rgba(0, 0, 0, 0.000)"] : mcolor,
:line => KW( :line => KW(
:color => needs_scatter_fix ? [lcolor, "rgba(0, 0, 0, 0.000)"] : lcolor, :color =>
needs_scatter_fix ? [lcolor, "rgba(0, 0, 0, 0.000)"] : lcolor,
:width => _cycle(series[:markerstrokewidth], i), :width => _cycle(series[:markerstrokewidth], i),
), ),
) )
@ -785,7 +913,9 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
# add "line" # add "line"
if hasline if hasline
plotattributes_out[:line] = KW( plotattributes_out[:line] = KW(
:color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))), :color => rgba_string(
plot_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
),
:width => get_linewidth(series, i), :width => get_linewidth(series, i),
:shape => if st == :steppre :shape => if st == :steppre
"vh" "vh"
@ -801,7 +931,7 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
end end
plotly_polar!(plotattributes_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(plotattributes_out, _cycle(series[:hover], rng)) plotly_adjust_hover_label!(plotattributes_out, _cycle(series[:hover], rng))
if hasfillrange if hasfillrange
# if hasfillrange is true, return two dictionaries (one for original # if hasfillrange is true, return two dictionaries (one for original
@ -810,11 +940,15 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
plotattributes_out_fillrange[:showlegend] = false plotattributes_out_fillrange[:showlegend] = false
# if fillrange is provided as real or tuple of real, expand to array # if fillrange is provided as real or tuple of real, expand to array
if typeof(series[:fillrange]) <: Real if typeof(series[:fillrange]) <: Real
series[:fillrange] = fill(series[:fillrange], length(rng)) plotattributes_out[:fillrange] = fill(series[:fillrange], length(rng))
elseif typeof(series[:fillrange]) <: Tuple elseif typeof(series[:fillrange]) <: Tuple
f1 = typeof(series[:fillrange][1]) <: Real ? fill(series[:fillrange][1], length(rng)) : series[:fillrange][1][rng] f1 =
f2 = typeof(series[:fillrange][2]) <: Real ? fill(series[:fillrange][2], length(rng)) : series[:fillrange][2][rng] typeof(series[:fillrange][1]) <: Real ?
series[:fillrange] = (f1, f2) fill(series[:fillrange][1], length(rng)) : series[:fillrange][1][rng]
f2 =
typeof(series[:fillrange][2]) <: Real ?
fill(series[:fillrange][2], length(rng)) : series[:fillrange][2][rng]
plotattributes_out[:fillrange] = (f1, f2)
end end
if isa(series[:fillrange], AbstractVector) if isa(series[:fillrange], AbstractVector)
plotattributes_out_fillrange[:y] = series[:fillrange][rng] plotattributes_out_fillrange[:y] = series[:fillrange][rng]
@ -823,16 +957,19 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
else else
# if fillrange is a tuple with upper and lower limit, plotattributes_out_fillrange # if fillrange is a tuple with upper and lower limit, plotattributes_out_fillrange
# is the series that will do the filling # is the series that will do the filling
plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] = concatenate_fillrange(x[rng], series[:fillrange]) plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] =
concatenate_fillrange(x[rng], series[:fillrange])
plotattributes_out_fillrange[:line][:width] = 0 plotattributes_out_fillrange[:line][:width] = 0
delete!(plotattributes_out, :fill) delete!(plotattributes_out, :fill)
delete!(plotattributes_out, :fillcolor) delete!(plotattributes_out, :fillcolor)
end end
plotattributes_outs[(2k-1):(2k)] = [plotattributes_out_fillrange, plotattributes_out] plotattributes_outs[(2k - 1):(2k)] =
[plotattributes_out_fillrange, plotattributes_out]
else else
plotattributes_outs[k] = plotattributes_out plotattributes_outs[k] = plotattributes_out
end end
plotattributes_outs[k] = merge(plotattributes_outs[k], series[:extra_kwargs])
end end
if series[:line_z] !== nothing if series[:line_z] !== nothing
@ -840,7 +977,10 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
elseif series[:fill_z] !== nothing elseif series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:marker_z] !== nothing elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker)) push!(
plotattributes_outs,
plotly_colorbar_hack(series, plotattributes_base, :marker),
)
end end
plotattributes_outs plotattributes_outs
@ -870,33 +1010,34 @@ function plotly_colorbar_hack(series::Series, plotattributes_base::KW, sym::Symb
return plotattributes_out return plotattributes_out
end end
function plotly_polar!(plotattributes_out::KW, series::Series) function plotly_polar!(plotattributes_out::KW, series::Series)
# convert polar plots x/y to theta/radius # convert polar plots x/y to theta/radius
if ispolar(series[:subplot]) if ispolar(series[:subplot])
theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y) theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
plotattributes_out[:t] = rad2deg.(theta) plotattributes_out[:theta] = rad2deg.(theta)
plotattributes_out[:r] = r plotattributes_out[:r] = r
plotattributes_out[:type] = :scatterpolar
end end
end end
function plotly_hover!(plotattributes_out::KW, hover) function plotly_adjust_hover_label!(plotattributes_out::KW, hover)
# hover text if hover === nothing
if hover === nothing || all(in([:none, false]), hover) return nothing
elseif all(in([:none, false]), hover)
plotattributes_out[:hoverinfo] = "none" plotattributes_out[:hoverinfo] = "none"
elseif any(!isnothing, hover) elseif any(!isnothing, hover)
plotattributes_out[:hoverinfo] = "text" plotattributes_out[:hoverinfo] = "text"
plotattributes_out[:text] = hover plotattributes_out[:text] = hover
end end
return nothing
end end
# get a list of dictionaries, each representing the series params # get a list of dictionaries, each representing the series params
function plotly_series(plt::Plot) function plotly_series(plt::Plot)
slist = [] if isempty(plt.series_list)
for series in plt.series_list return KW[]
append!(slist, plotly_series(plt, series))
end end
slist reduce(vcat, plotly_series(plt, series) for series in plt.series_list)
end end
# get json string for a list of dictionaries, each representing the series params # get json string for a list of dictionaries, each representing the series params
@ -909,11 +1050,15 @@ html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
function plotly_html_head(plt::Plot) function plotly_html_head(plt::Plot)
plotly = plotly =
use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) : "https://cdn.plot.ly/$(_plotly_min_js_filename)" use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) :
"https://cdn.plot.ly/$(_plotly_min_js_filename)"
include_mathjax = get(plt[:extra_plot_kwargs], :include_mathjax, "") include_mathjax = get(plt[:extra_plot_kwargs], :include_mathjax, "")
mathjax_file = include_mathjax != "cdn" ? ("file://" * include_mathjax) : "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML" mathjax_file =
mathjax_head = include_mathjax == "" ? "" : "<script src=\"$mathjax_file\"></script>\n\t\t" include_mathjax != "cdn" ? ("file://" * include_mathjax) :
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML"
mathjax_head =
include_mathjax == "" ? "" : "<script src=\"$mathjax_file\"></script>\n\t\t"
if isijulia() if isijulia()
mathjax_head mathjax_head
@ -933,8 +1078,9 @@ function plotly_html_body(plt, style = nothing)
if isijulia() if isijulia()
# require.js adds .js automatically # require.js adds .js automatically
plotly_no_ext = plotly_no_ext =
use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) : "https://cdn.plot.ly/$(_plotly_min_js_filename)" use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) :
plotly_no_ext = plotly_no_ext[1:end-3] "https://cdn.plot.ly/$(_plotly_min_js_filename)"
plotly_no_ext = plotly_no_ext[1:(end - 3)]
requirejs_prefix = """ requirejs_prefix = """
requirejs.config({ requirejs.config({
@ -952,8 +1098,7 @@ function plotly_html_body(plt, style = nothing)
<div id=\"$(uuid)\" style=\"$(style)\"></div> <div id=\"$(uuid)\" style=\"$(style)\"></div>
<script> <script>
$(requirejs_prefix) $(requirejs_prefix)
PLOT = document.getElementById('$(uuid)'); $(js_body(plt, uuid))
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
$(requirejs_suffix) $(requirejs_suffix)
</script> </script>
""" """
@ -962,16 +1107,12 @@ end
function js_body(plt::Plot, uuid) function js_body(plt::Plot, uuid)
js = """ js = """
PLOT = document.getElementById('$(uuid)'); Plotly.newPlot('$(uuid)', $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
""" """
end end
function plotly_show_js(io::IO, plot::Plot) function plotly_show_js(io::IO, plot::Plot)
data = [] data = plotly_series(plot)
for series in plot.series_list
append!(data, plotly_series(plot, series))
end
layout = plotly_layout(plot) layout = plotly_layout(plot)
JSON.print(io, Dict(:data => data, :layout => layout)) JSON.print(io, Dict(:data => data, :layout => layout))
end end
@ -984,12 +1125,10 @@ function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{Plotly
plotly_show_js(io, plot) plotly_show_js(io, plot)
end end
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend}) function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
write(io, standalone_html(plt)) write(io, embeddable_html(plt))
end end
function _display(plt::Plot{PlotlyBackend}) function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt) standalone_html_window(plt)
end end

View File

@ -8,6 +8,7 @@ function plotlyjs_syncplot(plt::Plot{PlotlyJSBackend})
traces = PlotlyJS.GenericTrace[] traces = PlotlyJS.GenericTrace[]
for series_dict in plotly_series(plt) for series_dict in plotly_series(plt)
plotly_type = pop!(series_dict, :type) plotly_type = pop!(series_dict, :type)
series_dict[:transpose] = false
push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...)) push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...))
end end
PlotlyJS.addtraces!(plt.o, traces...) PlotlyJS.addtraces!(plt.o, traces...)
@ -25,16 +26,19 @@ for (mime, fmt) in (
"image/svg+xml" => "svg", "image/svg+xml" => "svg",
"image/eps" => "eps", "image/eps" => "eps",
) )
@eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt) @eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) =
PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
end end
# Use the Plotly implementation for json and html: # Use the Plotly implementation for json and html:
_show(io::IO, mime::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) = plotly_show_js(io, plt) _show(io::IO, mime::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) =
plotly_show_js(io, plt)
html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt) html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt) html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt)
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, standalone_html(plt)) _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) =
write(io, embeddable_html(plt))
_display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt)) _display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt))

File diff suppressed because it is too large Load Diff

View File

@ -1,180 +1,373 @@
# https://github.com/JuliaPlots/UnicodePlots.jl
# https://github.com/Evizero/UnicodePlots.jl const _canvas_map = (
braille = UnicodePlots.BrailleCanvas,
density = UnicodePlots.DensityCanvas,
heatmap = UnicodePlots.HeatmapCanvas,
lookup = UnicodePlots.LookupCanvas,
ascii = UnicodePlots.AsciiCanvas,
block = UnicodePlots.BlockCanvas,
dot = UnicodePlots.DotCanvas,
)
should_warn_on_unsupported(::UnicodePlotsBackend) = false
# don't warn on unsupported... there's just too many warnings!! function _before_layout_calcs(plt::Plot{UnicodePlotsBackend})
warn_on_unsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing plt.o = UnicodePlots.Plot[]
up_width = UnicodePlots.DEFAULT_WIDTH[]
# -------------------------------------------------------------------------------------- up_height = UnicodePlots.DEFAULT_HEIGHT[]
function _canvas_map()
(
braille = UnicodePlots.BrailleCanvas,
ascii = UnicodePlots.AsciiCanvas,
block = UnicodePlots.BlockCanvas,
dot = UnicodePlots.DotCanvas,
density = UnicodePlots.DensityCanvas,
)
end
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
function rebuildUnicodePlot!(plt::Plot, width, height)
plt.o = []
has_layout = prod(size(plt.layout)) > 1
for sp in plt.subplots for sp in plt.subplots
sp_kw = sp[:extra_kwargs]
xaxis = sp[:xaxis] xaxis = sp[:xaxis]
yaxis = sp[:yaxis] yaxis = sp[:yaxis]
xlim = axis_limits(sp, :x) xlim = collect(axis_limits(sp, :x))
ylim = axis_limits(sp, :y) ylim = collect(axis_limits(sp, :y))
zlim = collect(axis_limits(sp, :z))
F = float(eltype(xlim))
# make vectors # We set x/y to have a single point,
xlim = [xlim[1], xlim[2]] # since we need to create the plot with some data.
ylim = [ylim[1], ylim[2]] # Since this point is at the bottom left corner of the plot,
# it should be hidden by consecutive plotting commands.
x = Vector{F}(xlim)
y = Vector{F}(ylim)
z = Vector{F}(zlim)
# we set x/y to have a single point, since we need to create the plot with some data. # create a plot window with xlim/ylim set,
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown # but the X/Y vectors are outside the bounds
x = Float64[xlim[1]] canvas = if (up_c = get(sp_kw, :canvas, :auto)) === :auto
y = Float64[ylim[1]] isijulia() ? :ascii : :braille
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
ct = _canvas_type[]
canvas_type = if ct == :auto
isijulia() ? UnicodePlots.AsciiCanvas : UnicodePlots.BrailleCanvas
else else
_canvas_map()[ct] up_c
end end
# special handling for spy border = if (up_b = get(sp_kw, :border, :auto)) === :auto
if length(sp.series_list) == 1 isijulia() ? :ascii : :solid
series = sp.series_list[1] else
if series[:seriestype] == :spy up_b
push!(plt.o, UnicodePlots.spy( end
series[:z].surf,
width = width, # blank plots will not be shown
height = height, width = has_layout && isempty(series_list(sp)) ? 0 : get(sp_kw, :width, up_width)
title = sp[:title], height = get(sp_kw, :height, up_height)
canvas = canvas_type
)) plot_3d = is3d(sp)
continue blend = get(sp_kw, :blend, true)
grid = xaxis[:grid] && yaxis[:grid]
quiver = contour = false
for series in series_list(sp)
st = series[:seriestype]
blend &= get(series[:extra_kwargs], :blend, true)
quiver |= series[:arrow] isa Arrow # post-pipeline detection (:quiver -> :path)
contour |= st === :contour
if st === :histogram2d
xlim = ylim = (0, 0)
elseif st === :spy || st === :heatmap
width = height = 0
grid = false
end end
end end
grid &= !(quiver || contour)
blend &= !(quiver || contour)
# # make it a bar canvas if plotting bar plot_3d && (xlim = ylim = (0, 0)) # determined using projection
# if any(series -> series[:seriestype] == :bar, series_list(sp)) azimuth, elevation = sp[:camera] # PyPlot: azimuth = -60 & elevation = 30
# canvas_type = UnicodePlots.BarplotGraphics projection = plot_3d ? get(sp_kw, :projection, :orthographic) : nothing
# end
o = UnicodePlots.Plot(x, y, canvas_type; kw = (
width = width, compact = true,
title = texmath2unicode(sp[:title]),
xlabel = texmath2unicode(xaxis[:guide]),
ylabel = texmath2unicode(yaxis[:guide]),
grid = grid,
blend = blend,
height = height, height = height,
title = sp[:title], width = width,
xscale = xaxis[:scale],
yscale = yaxis[:scale],
border = border,
xlim = xlim, xlim = xlim,
ylim = ylim, ylim = ylim,
border = isijulia() ? :ascii : :solid # 3d
projection = projection,
elevation = elevation,
azimuth = azimuth,
zoom = get(sp_kw, :zoom, 1),
up = get(sp_kw, :up, :z),
) )
# set the axis labels o = UnicodePlots.Plot(x, y, plot_3d ? z : nothing, _canvas_map[canvas]; kw...)
UnicodePlots.xlabel!(o, xaxis[:guide])
UnicodePlots.ylabel!(o, yaxis[:guide])
# now use the ! functions to add to the plot
for series in series_list(sp) for series in series_list(sp)
addUnicodeSeries!(o, series.plotattributes, sp[:legend] != :none, xlim, ylim) o = addUnicodeSeries!(
sp,
o,
kw,
series,
sp[:legend_position] !== :none,
plot_3d,
)
end end
# save the object for ann in sp[:annotations]
push!(plt.o, o) 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
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
function up_cmap(series)
rng = range(0, 1, length = length(UnicodePlots.COLOR_MAP_DATA[:viridis]))
[(red(c), green(c), blue(c)) for c in get(get_colorgradient(series), rng)]
end
# add a single series # add a single series
function addUnicodeSeries!(o, plotattributes, addlegend::Bool, xlim, ylim) function addUnicodeSeries!(
# get the function, or special handling for step/bar/hist sp::Subplot{UnicodePlotsBackend},
st = plotattributes[:seriestype] up::UnicodePlots.Plot,
if st == :histogram2d kw,
UnicodePlots.densityplot!(o, plotattributes[:x], plotattributes[:y]) series,
return addlegend::Bool,
end plot_3d::Bool,
)
if st in (:path, :straightline) st = series[:seriestype]
func = UnicodePlots.lineplot! se_kw = series[:extra_kwargs]
elseif st == :scatter || plotattributes[:markershape] != :none
func = UnicodePlots.scatterplot!
# elseif st == :bar
# func = UnicodePlots.barplot!
elseif st == :shape
func = UnicodePlots.lineplot!
else
error("Linestyle $st not supported by UnicodePlots")
end
# get the series data and label # get the series data and label
x, y = if st == :straightline x, y = if st === :straightline
straightline_data(plotattributes) straightline_data(series)
elseif st == :shape elseif st === :shape
shape_data(plotattributes) shape_data(series)
else else
[collect(float(plotattributes[s])) for s in (:x, :y)] series[:x], series[:y]
end
label = addlegend ? plotattributes[:label] : ""
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = plotattributes[:linecolor] in UnicodePlots.color_cycle ? plotattributes[:linecolor] : :auto
# add the series
x, y = RecipesPipeline.unzip(collect(Base.Iterators.filter(xy->isfinite(xy[1])&&isfinite(xy[2]), zip(x,y))))
func(o, x, y; color = color, name = label)
end
# -------------------------------
# since this is such a hack, it's only callable using `png`... should error during normal `show`
function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
fn = addExtension(fn, "png")
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
# @osx_only begin
@static if Sys.isapple()
# 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??)
run(`screencapture -R50,600,700,420 $fn`)
# END HACK (phew)
return
end end
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)") if ispolar(sp) || ispolar(series)
return UnicodePlots.polarplot(x, y)
end
# special handling (src/interface)
fix_ar = get(se_kw, :fix_ar, true)
if st === :histogram2d
return UnicodePlots.densityplot(x, y; kw...)
elseif st === :spy
return UnicodePlots.spy(Array(series[:z]); fix_ar = fix_ar, kw...)
elseif st in (:contour, :heatmap) # 2D
colormap = get(se_kw, :colormap, :none)
kw = (
kw...,
zlabel = sp[:colorbar_title],
colormap = colormap === :none ? up_cmap(series) : colormap,
colorbar = hascolorbar(sp),
)
if st === :contour
isfilledcontour(series) &&
@warn "Plots(UnicodePlots): filled contour is not implemented"
return UnicodePlots.contourplot(
x,
y,
Array(series[:z]);
kw...,
levels = series[:levels],
)
elseif st === :heatmap
return UnicodePlots.heatmap(Array(series[:z]); fix_ar = fix_ar, kw...)
end
elseif st in (:surface, :wireframe) # 3D
colormap = get(se_kw, :colormap, :none)
lines = get(se_kw, :lines, st === :wireframe)
zscale = get(se_kw, :zscale, :identity)
kw = (
kw...,
zlabel = sp[:colorbar_title],
colormap = colormap === :none ? up_cmap(series) : colormap,
colorbar = hascolorbar(sp),
color = st === :wireframe ? up_color(get_linecolor(series, 1)) : nothing,
zscale = zscale,
lines = lines,
)
return UnicodePlots.surfaceplot(x, y, Array(series[:z]); kw...)
elseif st === :mesh3d
return UnicodePlots.lineplot!(
up,
mesh3d_triangles(x, y, series[:z], series[:connections])...,
)
end
# now use the ! functions to add to the plot
if st in (:path, :path3d, :straightline, :shape, :mesh3d)
func = UnicodePlots.lineplot!
series_kw = (; head_tail = series[:arrow] isa Arrow ? series[:arrow].side : nothing)
elseif st in (:scatter, :scatter3d) || series[:markershape] !== :none
func = UnicodePlots.scatterplot!
series_kw = (; marker = series[:markershape])
else
error("Plots(UnicodePlots): series type $st not supported")
end
label = addlegend ? series[:label] : ""
for (n, segment) in enumerate(series_segments(series, st; check = true))
i, rng = segment.attr_index, segment.range
lc = get_linecolor(series, i)
up = func(
up,
x[rng],
y[rng],
plot_3d ? series[:z][rng] : nothing;
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
up
end end
# ------------------------------- # ------------------------------------------------------------------------------------------
# we don't do very much for subplots... just stack them vertically function _show(io::IO, ::MIME"image/png", plt::Plot{UnicodePlotsBackend})
prepare_output(plt)
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) nr, nc = size(plt.layout)
w, h = plt[:size] s1 = zeros(Int, nr, nc)
plt.attr[:color_palette] = [RGB(0,0,0)] s2 = zeros(Int, nr, nc)
rebuildUnicodePlot!(plt, div(w, 10), div(h, 20)) canvas_type = nothing
imgs = []
sps = 0
for r in 1:nr
for c in 1:nc
if (l = plt.layout[r, c]) isa GridLayout && size(l) != (1, 1)
error("Plots(UnicodePlots): complex nested layout is currently unsupported")
else
img = UnicodePlots.png_image(plt.o[sps += 1])
canvas_type = eltype(img)
h, w = size(img)
s1[r, c] = h
s2[r, c] = w
push!(imgs, img)
end
end
end
if canvas_type !== nothing
m1 = maximum(s1; dims = 2)
m2 = maximum(s2; dims = 1)
img = zeros(canvas_type, sum(m1), sum(m2))
sps = 0
n1 = 1
for r in 1:nr
n2 = 1
for c in 1:nc
sp = imgs[sps += 1]
h, w = size(sp)
img[n1:(n1 + (h - 1)), n2:(n2 + (w - 1))] = sp
n2 += m2[c]
end
n1 += m1[r]
end
stream = UnicodePlots.FileIO.Stream{UnicodePlots.FileIO.format"PNG"}(io)
UnicodePlots.FileIO.save(stream, img)
end
nothing
end end
Base.show(plt::Plot{UnicodePlotsBackend}) = show(stdout, plt)
Base.show(io::IO, plt::Plot{UnicodePlotsBackend}) = _show(io, MIME("text/plain"), plt)
# NOTE: _show(...) must be kept for Base.showable (src/output.jl)
function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend}) function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt) prepare_output(plt)
foreach(x -> show(io, x), plt.o) nr, nc = size(plt.layout)
if nr == 1 && nc == 1 # fast path
n = length(plt.o)
for (i, p) in enumerate(plt.o)
show(io, p)
i < n && println(io)
end
else
have_color = Base.get_have_color()
buf = IOContext(PipeBuffer(), :color => have_color)
lines_colored = Array{Union{Nothing,Vector{String}}}(undef, nr, nc)
lines_uncolored = have_color ? similar(lines_colored) : lines_colored
l_max = zeros(Int, nr)
w_max = zeros(Int, nc)
sps = 0
for r in 1:nr
lmax = 0
for c in 1:nc
if (l = plt.layout[r, c]) isa GridLayout && size(l) != (1, 1)
error(
"Plots(UnicodePlots): complex nested layout is currently unsupported",
)
else
if get(l.attr, :blank, false)
lines_colored[r, c] = lines_uncolored[r, c] = nothing
else
sp = plt.o[sps += 1]
show(buf, sp)
colored = read(buf, String)
lines_colored[r, c] = lu = lc = split(colored, '\n')
if have_color
uncolored = UnicodePlots.no_ansi_escape(colored)
lines_uncolored[r, c] = lu = split(uncolored, '\n')
end
lmax = max(length(lc), lmax)
w_max[c] = max(maximum(length.(lu)), w_max[c])
end
end
end
l_max[r] = lmax
end
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[c])
else
lu = lines_uncolored[r, c]
print(io, pre, lc[n], ' '^(w_max[c] - length(lu[n])))
end
end
n < l_max[r] && println(io)
end
r < nr && println(io)
end
end
nothing nothing
end end
# we only support MIME"text/plain", hence display(...) falls back to plain-text on stdout
function _display(plt::Plot{UnicodePlotsBackend}) function _display(plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt) show(stdout, plt)
map(show, plt.o) println(stdout)
nothing
end end

View File

@ -3,7 +3,10 @@
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl # CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl")) function standalone_html(
plt::AbstractPlot;
title::AbstractString = get(plt.attr, :window_title, "Plots.jl"),
)
""" """
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -19,6 +22,10 @@ function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr
""" """
end end
function embeddable_html(plt::AbstractPlot)
html_head(plt) * html_body(plt)
end
function open_browser_window(filename::AbstractString) function open_browser_window(filename::AbstractString)
@static if Sys.isapple() @static if Sys.isapple()
return run(`open $(filename)`) return run(`open $(filename)`)
@ -45,7 +52,8 @@ function standalone_html_window(plt::AbstractPlot)
old = use_local_dependencies[] # save state to restore afterwards old = use_local_dependencies[] # save state to restore afterwards
# if we open a browser ourself, we can host local files, so # if we open a browser ourself, we can host local files, so
# when we have a local plotly downloaded this is the way to go! # when we have a local plotly downloaded this is the way to go!
use_local_dependencies[] = plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[]) use_local_dependencies[] =
plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[])
filename = write_temp_html(plt) filename = write_temp_html(plt)
open_browser_window(filename) open_browser_window(filename)
# restore for other backends # restore for other backends
@ -54,7 +62,9 @@ end
# uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html # uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html
function html_to_png(html_fn, png_fn, w, h) function html_to_png(html_fn, png_fn, w, h)
run(`wkhtmltoimage -f png -q --width $w --height $h --disable-smart-width $html_fn $png_fn`) run(
`wkhtmltoimage -f png -q --width $w --height $h --disable-smart-width $html_fn $png_fn`,
)
end end
function show_png_from_html(io::IO, plt::AbstractPlot) function show_png_from_html(io::IO, plt::AbstractPlot)

View File

@ -1,48 +1,61 @@
# These functions return an operator for use in `get_clims(::Seres, op)` # These functions return an operator for use in `get_clims(::Seres, op)`
process_clims(lims::Tuple{<:Number,<:Number}) = (zlims -> ifelse.(isfinite.(lims), lims, zlims)) ignorenan_extrema process_clims(lims::Tuple{<:Number,<:Number}) =
(zlims -> ifelse.(isfinite.(lims), lims, zlims)) ignorenan_extrema
process_clims(s::Union{Symbol,Nothing,Missing}) = ignorenan_extrema process_clims(s::Union{Symbol,Nothing,Missing}) = ignorenan_extrema
# don't specialize on ::Function otherwise python functions won't work # don't specialize on ::Function otherwise python functions won't work
process_clims(f) = f 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 zmin, zmax = Inf, -Inf
for series in series_list(sp) for series in series_list(sp)
if series[:colorbar_entry] if series[:colorbar_entry]::Bool
zmin, zmax = _update_clims(zmin, zmax, get_clims(series, op)...) zmin, zmax = _update_clims(zmin, zmax, update_clims(series, op)...)
else
update_clims(series, op)
end end
end end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN) return sp[:clims_calculated] = 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)
end 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`, 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 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 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]) # keeping this unrolled has higher performance
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real}) if series[:seriestype] _z_colored_series && series[:z] !== nothing
zmin, zmax = _update_clims(zmin, zmax, op(vals.surf)...) zmin, zmax = update_clims(zmin, zmax, series[:z], op)
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
zmin, zmax = _update_clims(zmin, zmax, op(vals)...)
end
end 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 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) _update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax)
@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines @enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
@ -60,8 +73,8 @@ function colorbar_style(series::Series)
cbar_fill cbar_fill
elseif iscontour(series) elseif iscontour(series)
cbar_lines cbar_lines
elseif series[:seriestype] (:heatmap,:surface) || elseif series[:seriestype] (:heatmap, :surface) ||
any(series[z] !== nothing for z [:marker_z,:line_z,:fill_z]) any(series[z] !== nothing for z in [:marker_z, :line_z, :fill_z])
cbar_gradient cbar_gradient
else else
nothing nothing
@ -69,7 +82,8 @@ function colorbar_style(series::Series)
end end
hascolorbar(series::Series) = colorbar_style(series) !== nothing hascolorbar(series::Series) = colorbar_style(series) !== nothing
hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp)) hascolorbar(sp::Subplot) =
sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
function get_colorbar_ticks(sp::Subplot; update = true) function get_colorbar_ticks(sp::Subplot; update = true)
if update || !haskey(sp.attr, :colorbar_optimized_ticks) if update || !haskey(sp.attr, :colorbar_optimized_ticks)
@ -87,4 +101,5 @@ end
function _update_subplot_colorbars(sp::Subplot) function _update_subplot_colorbars(sp::Subplot)
# Dynamic callback from the pipeline if needed # Dynamic callback from the pipeline if needed
update_clims(sp)
end end

File diff suppressed because it is too large Load Diff

88
src/consts.jl Normal file
View File

@ -0,0 +1,88 @@
const _deprecated_attributes = Dict{Symbol,Symbol}(:orientation => :permute)
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 = Set(keys(_axis_defaults))
const _series_args = Set(keys(_series_defaults))
const _subplot_args = Set(keys(_subplot_defaults))
const _plot_args = Set(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_magic_args =
Set(union(_magic_axis_args, _magic_series_args, _magic_subplot_args))
const _all_axis_args = union(_axis_args, _magic_axis_args)
const _lettered_all_axis_args =
Set([Symbol(letter, kw) for letter in (:x, :y, :z) for kw in _all_axis_args])
const _all_subplot_args = union(_subplot_args, _magic_subplot_args)
const _all_series_args = union(_series_args, _magic_series_args)
const _all_plot_args = _plot_args
const _all_args =
union(_lettered_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)

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
# --------------------------------------------------------- # ---------------------------------------------------------
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert # A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
_fileio_load(@nospecialize(filename::AbstractString)) = FileIO.load(filename::AbstractString) _fileio_load(@nospecialize(filename::AbstractString)) =
_fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) = FileIO.save(filename::AbstractString, x) FileIO.load(filename::AbstractString)
_fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) =
FileIO.save(filename::AbstractString, x)
function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot) function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot)
fn = tempname() fn = tempname()
@ -21,4 +23,5 @@ function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot)
write(io, read(open(pngfn), String)) write(io, read(open(pngfn), String))
end end
const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend} const PDFBackends =
Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}

View File

@ -1,15 +1,14 @@
const use_local_dependencies = Ref(false) const use_local_dependencies = Ref(false)
const use_local_plotlyjs = Ref(false) const use_local_plotlyjs = Ref(false)
function _init_ijulia_plotting() function _init_ijulia_plotting()
# IJulia is more stable with local file # IJulia is more stable with local file
use_local_plotlyjs[] = plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[]) use_local_plotlyjs[] =
plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[])
ENV["MPLBACKEND"] = "Agg" ENV["MPLBACKEND"] = "Agg"
end end
""" """
Add extra jupyter mimetypes to display_dict based on the plot backed. Add extra jupyter mimetypes to display_dict based on the plot backed.
@ -20,22 +19,17 @@ frontends like jupyterlab and nteract.
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out _ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict) function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict( out["application/vnd.plotly.v1+json"] =
:data => plotly_series(plt), Dict(:data => plotly_series(plt), :layout => plotly_layout(plt))
:layout => plotly_layout(plt)
)
out out
end end
function _ijulia__extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict) function _ijulia__extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict( out["application/vnd.plotly.v1+json"] =
:data => plotly_series(plt), Dict(:data => plotly_series(plt), :layout => plotly_layout(plt))
:layout => plotly_layout(plt)
)
out out
end end
function _ijulia_display_dict(plt::Plot) function _ijulia_display_dict(plt::Plot)
output_type = Symbol(plt.attr[:html_output_format]) output_type = Symbol(plt.attr[:html_output_format])
if output_type == :auto if output_type == :auto
@ -55,6 +49,9 @@ function _ijulia_display_dict(plt::Plot)
mime = "text/html" mime = "text/html"
out[mime] = sprint(show, MIME(mime), plt) out[mime] = sprint(show, MIME(mime), plt)
_ijulia__extra_mime_info!(plt, out) _ijulia__extra_mime_info!(plt, out)
elseif output_type == :pdf
mime = "application/pdf"
out[mime] = base64encode(show, MIME(mime), plt)
else else
error("Unsupported output type $output_type") error("Unsupported output type $output_type")
end end

View File

@ -1,8 +1,7 @@
using REPL using REPL
using Scratch using Scratch
const plotly_local_file_path = Ref{Union{Nothing, String}}(nothing) const plotly_local_file_path = Ref{Union{Nothing,String}}(nothing)
function _plots_defaults() function _plots_defaults()
if isdefined(Main, :PLOTS_DEFAULTS) if isdefined(Main, :PLOTS_DEFAULTS)
@ -12,7 +11,6 @@ function _plots_defaults()
end end
end end
function __init__() function __init__()
user_defaults = _plots_defaults() user_defaults = _plots_defaults()
if haskey(user_defaults, :theme) if haskey(user_defaults, :theme)
@ -21,14 +19,27 @@ function __init__()
default(; user_defaults...) default(; user_defaults...)
end end
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) insert!(
Base.Multimedia.displays,
findlast(
x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay,
Base.Multimedia.displays,
) + 1,
PlotsDisplay(),
)
atreplinit(i -> begin atreplinit(
while PlotsDisplay() in Base.Multimedia.displays i -> begin
popdisplay(PlotsDisplay()) while PlotsDisplay() in Base.Multimedia.displays
end popdisplay(PlotsDisplay())
insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay()) end
end) insert!(
Base.Multimedia.displays,
findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1,
PlotsDisplay(),
)
end,
)
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin @require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin
fn = joinpath(@__DIR__, "backends", "hdf5.jl") fn = joinpath(@__DIR__, "backends", "hdf5.jl")
@ -70,18 +81,26 @@ function __init__()
include(fn) include(fn)
end end
@require Gaston = "4b11ee91-296f-5714-9832-002c20994614" begin
fn = joinpath(@__DIR__, "backends", "gaston.jl")
include(fn)
end
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin @require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited if IJulia.inited
_init_ijulia_plotting() _init_ijulia_plotting()
IJulia.display_dict(plt::Plot) = _ijulia_display_dict(plt) IJulia.display_dict(plt::Plot) = _ijulia_display_dict(plt)
end end
end end
if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true" if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true"
global plotly_local_file_path[] = joinpath(@get_scratch!("plotly"), _plotly_min_js_filename) global plotly_local_file_path[] =
joinpath(@get_scratch!("plotly"), _plotly_min_js_filename)
if !isfile(plotly_local_file_path[]) if !isfile(plotly_local_file_path[])
download("https://cdn.plot.ly/$(_plotly_min_js_filename)", plotly_local_file_path[]) Downloads.download(
"https://cdn.plot.ly/$(_plotly_min_js_filename)",
plotly_local_file_path[],
)
end end
use_local_plotlyjs[] = true use_local_plotlyjs[] = true
@ -89,8 +108,8 @@ function __init__()
use_local_dependencies[] = use_local_plotlyjs[] use_local_dependencies[] = use_local_plotlyjs[]
@require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin @require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin
_show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt) _show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) =
_show_pdfbackends(io, mime, plt)
end end
end end

View File

@ -18,16 +18,16 @@ ispositive(m::Measure) = m.value > 0
# union together bounding boxes # union together bounding boxes
function Base.:+(bb1::BoundingBox, bb2::BoundingBox) function Base.:+(bb1::BoundingBox, bb2::BoundingBox)
# empty boxes don't change the union # empty boxes don't change the union
ispositive(width(bb1)) || return bb2 ispositive(width(bb1)) || return bb2
ispositive(height(bb1)) || return bb2 ispositive(height(bb1)) || return bb2
ispositive(width(bb2)) || return bb1 ispositive(width(bb2)) || return bb1
ispositive(height(bb2)) || return bb1 ispositive(height(bb2)) || return bb1
l = min(left(bb1), left(bb2)) l = min(left(bb1), left(bb2))
t = min(top(bb1), top(bb2)) t = min(top(bb1), top(bb2))
r = max(right(bb1), right(bb2)) r = max(right(bb1), right(bb2))
b = max(bottom(bb1), bottom(bb2)) b = max(bottom(bb1), bottom(bb2))
BoundingBox(l, t, r-l, b-t) BoundingBox(l, t, r - l, b - t)
end end
# this creates a bounding box in the parent's scope, where the child bounding box # this creates a bounding box in the parent's scope, where the child bounding box
@ -53,7 +53,7 @@ end
# convert a bounding box from absolute coords to percentages... # convert a bounding box from absolute coords to percentages...
# returns an array of percentages of figure size: [left, bottom, width, height] # returns an array of percentages of figure size: [left, bottom, width, height]
function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true) function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true)
mms = Float64[f(bb).value for f in (left,bottom,width,height)] mms = Float64[f(bb).value for f in (left, bottom, width, height)]
if flipy if flipy
mms[2] = figh.value - mms[2] # flip y when origin in bottom-left mms[2] = figh.value - mms[2] # flip y when origin in bottom-left
end end
@ -61,7 +61,10 @@ function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true)
end end
function Base.show(io::IO, bbox::BoundingBox) function Base.show(io::IO, bbox::BoundingBox)
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}") print(
io,
"BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}",
)
end end
# ----------------------------------------------------------- # -----------------------------------------------------------
@ -83,12 +86,11 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
end end
if pct != 0 if pct != 0
amin, amax = axis_limits(sp, letter) amin, amax = axis_limits(sp, letter)
xy += pct * (amax-amin) xy += pct * (amax - amin)
end end
xy xy
end end
# ----------------------------------------------------------- # -----------------------------------------------------------
# AbstractLayout # AbstractLayout
@ -160,7 +162,8 @@ parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
# padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout)) # padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
update_position!(layout::AbstractLayout) = nothing update_position!(layout::AbstractLayout) = nothing
update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm, 0mm, 0mm, 0mm]) =
nothing
left(layout::AbstractLayout) = left(bbox(layout)) left(layout::AbstractLayout) = left(bbox(layout))
top(layout::AbstractLayout) = top(bbox(layout)) top(layout::AbstractLayout) = top(bbox(layout))
@ -206,7 +209,7 @@ mutable struct EmptyLayout <: AbstractLayout
end end
EmptyLayout(parent = RootLayout(); kw...) = EmptyLayout(parent, defaultbox, KW(kw)) EmptyLayout(parent = RootLayout(); kw...) = EmptyLayout(parent, defaultbox, KW(kw))
Base.size(layout::EmptyLayout) = (0,0) Base.size(layout::EmptyLayout) = (0, 0)
Base.length(layout::EmptyLayout) = 0 Base.length(layout::EmptyLayout) = 0
Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
@ -235,22 +238,25 @@ columns of different width.
""" """
grid(args...; kw...) = GridLayout(args...; kw...) grid(args...; kw...) = GridLayout(args...; kw...)
function GridLayout(dims...; function GridLayout(
parent = RootLayout(), dims...;
widths = zeros(dims[2]), parent = RootLayout(),
heights = zeros(dims[1]), widths = zeros(dims[2]),
kw...) heights = zeros(dims[1]),
kw...,
)
grid = Matrix{AbstractLayout}(undef, dims...) grid = Matrix{AbstractLayout}(undef, dims...)
layout = GridLayout( layout = GridLayout(
parent, parent,
(20mm, 5mm, 2mm, 10mm), (20mm, 5mm, 2mm, 10mm),
defaultbox, defaultbox,
grid, grid,
Measure[w*pct for w in widths], Measure[w * pct for w in widths],
Measure[h*pct for h in heights], Measure[h * pct for h in heights],
# convert(Vector{Float64}, widths), # convert(Vector{Float64}, widths),
# convert(Vector{Float64}, heights), # convert(Vector{Float64}, heights),
KW(kw)) KW(kw),
)
for i in eachindex(grid) for i in eachindex(grid)
grid[i] = EmptyLayout(layout) grid[i] = EmptyLayout(layout)
end end
@ -259,9 +265,12 @@ end
Base.size(layout::GridLayout) = size(layout.grid) Base.size(layout::GridLayout) = size(layout.grid)
Base.length(layout::GridLayout) = length(layout.grid) Base.length(layout::GridLayout) = length(layout.grid)
Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r,c] Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r, c]
function Base.setindex!(layout::GridLayout, v, r::Int, c::Int) function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
layout.grid[r,c] = v layout.grid[r, c] = v
end
function Base.setindex!(layout::GridLayout, v, ci::CartesianIndex)
layout.grid[ci] = v
end end
leftpad(layout::GridLayout) = layout.minpad[1] leftpad(layout::GridLayout) = layout.minpad[1]
@ -269,7 +278,6 @@ toppad(layout::GridLayout) = layout.minpad[2]
rightpad(layout::GridLayout) = layout.minpad[3] rightpad(layout::GridLayout) = layout.minpad[3]
bottompad(layout::GridLayout) = layout.minpad[4] bottompad(layout::GridLayout) = layout.minpad[4]
# here's how this works... first we recursively "update the minimum padding" (which # here's how this works... first we recursively "update the minimum padding" (which
# means to calculate the minimum size needed from the edge of the subplot to plot area) # means to calculate the minimum size needed from the edge of the subplot to plot area)
# for the whole layout tree. then we can compute the "padding borders" of this # for the whole layout tree. then we can compute the "padding borders" of this
@ -281,14 +289,13 @@ bottompad(layout::GridLayout) = layout.minpad[4]
function _update_min_padding!(layout::GridLayout) function _update_min_padding!(layout::GridLayout)
map(_update_min_padding!, layout.grid) map(_update_min_padding!, layout.grid)
layout.minpad = ( layout.minpad = (
maximum(map(leftpad, layout.grid[:,1])), maximum(map(leftpad, layout.grid[:, 1])),
maximum(map(toppad, layout.grid[1,:])), maximum(map(toppad, layout.grid[1, :])),
maximum(map(rightpad, layout.grid[:,end])), maximum(map(rightpad, layout.grid[:, end])),
maximum(map(bottompad, layout.grid[end,:])) maximum(map(bottompad, layout.grid[end, :])),
) )
end end
function update_position!(layout::GridLayout) function update_position!(layout::GridLayout)
map(update_position!, layout.grid) map(update_position!, layout.grid)
end end
@ -307,7 +314,9 @@ function recompute_lengths(v)
end end
leftover = 1.0pct - tot leftover = 1.0pct - tot
if cnt > 1 && leftover.value <= 0 if cnt > 1 && leftover.value <= 0
error("Not enough length left over in layout! v = $v, cnt = $cnt, leftover = $leftover") error(
"Not enough length left over in layout! v = $v, cnt = $cnt, leftover = $leftover",
)
end end
# now fill in the blanks # now fill in the blanks
@ -315,21 +324,21 @@ function recompute_lengths(v)
end end
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!) # recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm, 0mm, 0mm, 0mm])
nr, nc = size(layout) nr, nc = size(layout)
# # create a matrix for each minimum padding direction # # create a matrix for each minimum padding direction
# _update_min_padding!(layout) # _update_min_padding!(layout)
minpad_left = map(leftpad, layout.grid) minpad_left = map(leftpad, layout.grid)
minpad_top = map(toppad, layout.grid) minpad_top = map(toppad, layout.grid)
minpad_right = map(rightpad, layout.grid) minpad_right = map(rightpad, layout.grid)
minpad_bottom = map(bottompad, layout.grid) minpad_bottom = map(bottompad, layout.grid)
# get the max horizontal (left and right) padding over columns, # get the max horizontal (left and right) padding over columns,
# and max vertical (bottom and top) padding over rows # and max vertical (bottom and top) padding over rows
# TODO: add extra padding here # TODO: add extra padding here
pad_left = maximum(minpad_left, dims = 1) pad_left = maximum(minpad_left, dims = 1)
pad_top = maximum(minpad_top, dims = 2) pad_top = maximum(minpad_top, dims = 2)
pad_right = maximum(minpad_right, dims = 1) pad_right = maximum(minpad_right, dims = 1)
pad_bottom = maximum(minpad_bottom, dims = 2) pad_bottom = maximum(minpad_bottom, dims = 2)
# make sure the perimeter match the parent # make sure the perimeter match the parent
@ -343,7 +352,7 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
total_pad_vertical = sum(pad_top + pad_bottom) total_pad_vertical = sum(pad_top + pad_bottom)
# now we can compute the total plot area in each direction # now we can compute the total plot area in each direction
total_plotarea_horizontal = width(layout) - total_pad_horizontal total_plotarea_horizontal = width(layout) - total_pad_horizontal
total_plotarea_vertical = height(layout) - total_pad_vertical total_plotarea_vertical = height(layout) - total_pad_vertical
# recompute widths/heights # recompute widths/heights
@ -355,19 +364,22 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
# denom_h = sum(layout.heights) # denom_h = sum(layout.heights)
# we have all the data we need... lets compute the plot areas and set the bounding boxes # we have all the data we need... lets compute the plot areas and set the bounding boxes
for r=1:nr, c=1:nc for r in 1:nr, c in 1:nc
child = layout[r,c] child = layout[r, c]
# get the top-left corner of this child... the first one is top-left of the parent (i.e. layout) # get the top-left corner of this child... the first one is top-left of the parent (i.e. layout)
child_left = (c == 1 ? left(layout.bbox) : right(layout[r, c-1].bbox)) child_left = (c == 1 ? left(layout.bbox) : right(layout[r, c - 1].bbox))
child_top = (r == 1 ? top(layout.bbox) : bottom(layout[r-1, c].bbox)) child_top = (r == 1 ? top(layout.bbox) : bottom(layout[r - 1, c].bbox))
# compute plot area # compute plot area
plotarea_left = child_left + pad_left[c] plotarea_left = child_left + pad_left[c]
plotarea_top = child_top + pad_top[r] plotarea_top = child_top + pad_top[r]
plotarea_width = total_plotarea_horizontal * layout.widths[c] plotarea_width = total_plotarea_horizontal * layout.widths[c]
plotarea_height = total_plotarea_vertical * layout.heights[r] plotarea_height = total_plotarea_vertical * layout.heights[r]
plotarea!(child, BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height)) plotarea!(
child,
BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height),
)
# compute child bbox # compute child bbox
child_width = pad_left[c] + plotarea_width + pad_right[c] child_width = pad_left[c] + plotarea_width + pad_right[c]
@ -377,10 +389,10 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
# this is the minimum perimeter as decided by this child's parent, so that # this is the minimum perimeter as decided by this child's parent, so that
# all children on this border have the same value # all children on this border have the same value
min_child_perimeter = [ min_child_perimeter = [
c == 1 ? layout.minpad[1] : pad_left[c], c == 1 ? layout.minpad[1] : pad_left[c],
r == 1 ? layout.minpad[2] : pad_top[r], r == 1 ? layout.minpad[2] : pad_top[r],
c == nc ? layout.minpad[3] : pad_right[c], c == nc ? layout.minpad[3] : pad_right[c],
r == nr ? layout.minpad[4] : pad_bottom[r] r == nr ? layout.minpad[4] : pad_bottom[r],
] ]
# recursively update the child's children # recursively update the child's children
@ -395,18 +407,21 @@ function update_inset_bboxes!(plt::Plot)
p_area = Measures.resolve(plotarea(sp.parent), sp[:relative_bbox]) p_area = Measures.resolve(plotarea(sp.parent), sp[:relative_bbox])
plotarea!(sp, p_area) plotarea!(sp, p_area)
bbox!(sp, bbox( bbox!(
left(p_area) - leftpad(sp), sp,
top(p_area) - toppad(sp), bbox(
width(p_area) + leftpad(sp) + rightpad(sp), left(p_area) - leftpad(sp),
height(p_area) + toppad(sp) + bottompad(sp) top(p_area) - toppad(sp),
)) width(p_area) + leftpad(sp) + rightpad(sp),
height(p_area) + toppad(sp) + bottompad(sp),
),
)
end end
end end
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
calc_num_subplots(layout::AbstractLayout) = 1 calc_num_subplots(layout::AbstractLayout) = get(layout.attr, :blank, false) ? 0 : 1
function calc_num_subplots(layout::GridLayout) function calc_num_subplots(layout::GridLayout)
tot = 0 tot = 0
for l in layout.grid for l in layout.grid
@ -441,7 +456,9 @@ end
function layout_args(plotattributes::AKW, n_override::Integer) function layout_args(plotattributes::AKW, n_override::Integer)
layout, n = layout_args(n_override, get(plotattributes, :layout, n_override)) layout, n = layout_args(n_override, get(plotattributes, :layout, n_override))
if n != n_override if n != n_override
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.") error(
"When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.",
)
end end
layout, n layout, n
end end
@ -451,32 +468,45 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n GridLayout(nr, nc), n
end end
function layout_args(sztup::NTuple{2, Integer}) function layout_args(sztup::NTuple{2,Integer})
nr, nc = sztup nr, nc = sztup
GridLayout(nr, nc), nr*nc GridLayout(nr, nc), nr * nc
end end
layout_args(n_override::Integer, n::Integer) = layout_args(n) layout_args(n_override::Integer, n::Integer) = layout_args(n)
layout_args(n, sztup::NTuple{2, Integer}) = layout_args(sztup) layout_args(n, sztup::NTuple{2,Integer}) = layout_args(sztup)
function layout_args(n, sztup::Tuple{Colon, Integer}) function layout_args(n, sztup::Tuple{Colon,Integer})
nc = sztup[2] nc = sztup[2]
nr = ceil(Int, n / nc) nr = ceil(Int, n / nc)
GridLayout(nr, nc), n GridLayout(nr, nc), n
end end
function layout_args(n, sztup::Tuple{Integer, Colon}) function layout_args(n, sztup::Tuple{Integer,Colon})
nr = sztup[1] nr = sztup[1]
nc = ceil(Int, n / nr) nc = ceil(Int, n / nr)
GridLayout(nr, nc), n GridLayout(nr, nc), n
end end
function layout_args(sztup::NTuple{3, Integer}) function layout_args(sztup::NTuple{3,Integer})
n, nr, nc = sztup n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc) nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n GridLayout(nr, nc), n
end 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 # compute number of subplots
function layout_args(layout::GridLayout) function layout_args(layout::GridLayout)
# recursively get the size of the grid # recursively get the size of the grid
@ -484,57 +514,63 @@ function layout_args(layout::GridLayout)
layout, n layout, n
end 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") layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
function build_layout(args...) function build_layout(args...)
layout, n = layout_args(args...) layout, n = layout_args(args...)
build_layout(layout, n) build_layout(layout, n, Array{Plot}(undef, 0))
end end
# # just a single subplot # n is the number of subplots...
# function build_layout(sp::Subplot, n::Integer) function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot})
# sp, Subplot[sp], SubplotMap(gensym() => sp)
# end
# n is the number of subplots... build a grid and initialize the inner subplots recursively
function build_layout(layout::GridLayout, n::Integer)
nr, nc = size(layout) nr, nc = size(layout)
subplots = Subplot[] subplots = Subplot[]
spmap = SubplotMap() spmap = SubplotMap()
empty = isempty(plts)
i = 0 i = 0
for r=1:nr, c=1:nc for r in 1:nr, c in 1:nc
l = layout[r,c] l = layout[r, c]
if isa(l, EmptyLayout) && !get(l.attr, :blank, false) if isa(l, EmptyLayout) && !get(l.attr, :blank, false)
sp = Subplot(backend(), parent=layout) if empty
layout[r,c] = sp # initialize the inner subplots recursively
push!(subplots, sp) sp = Subplot(backend(), parent = layout)
spmap[attr(l,:label,gensym())] = sp layout[r, c] = sp
push!(subplots, sp)
spmap[attr(l, :label, gensym())] = sp
inc = 1
else
# build a layout from a list of existing Plot objects
plt = popfirst!(plts) # grab the first plot out of the list
layout[r, c] = plt.layout
append!(subplots, plt.subplots)
merge!(spmap, plt.spmap)
inc = length(plt.subplots)
end
if get(l.attr, :width, :auto) != :auto if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width) layout.widths[c] = attr(l, :width)
end end
if get(l.attr, :height, :auto) != :auto if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height) layout.heights[r] = attr(l, :height)
end end
i += 1 i += inc
elseif isa(l, GridLayout) elseif isa(l, GridLayout)
# sub-grid # sub-grid
if get(l.attr, :width, :auto) != :auto if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width) layout.widths[c] = attr(l, :width)
end end
if get(l.attr, :height, :auto) != :auto if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height) layout.heights[r] = attr(l, :height)
end end
l, sps, m = build_layout(l, n-i) l, sps, m = build_layout(l, n - i, plts)
append!(subplots, sps) append!(subplots, sps)
merge!(spmap, m) merge!(spmap, m)
i += length(sps) i += length(sps)
elseif isa(l, Subplot) elseif isa(l, Subplot) && empty
error("Subplot exists. Cannot re-use existing layout. Please make a new one.") error("Subplot exists. Cannot re-use existing layout. Please make a new one.")
end end
i >= n && break # only add n subplots i >= n && break # only add n subplots
@ -543,161 +579,13 @@ function build_layout(layout::GridLayout, n::Integer)
layout, subplots, spmap layout, subplots, spmap
end end
# build a layout from a list of existing Plot objects
# TODO... much of the logic overlaps with the method above... can we merge?
function build_layout(layout::GridLayout, numsp::Integer, plts::AVec{Plot})
nr, nc = size(layout)
subplots = Subplot[]
spmap = SubplotMap()
i = 0
for r=1:nr, c=1:nc
l = layout[r,c]
if isa(l, EmptyLayout) && !get(l.attr, :blank, false)
plt = popfirst!(plts) # grab the first plot out of the list
layout[r,c] = plt.layout
append!(subplots, plt.subplots)
merge!(spmap, plt.spmap)
if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width)
end
if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height)
end
i += length(plt.subplots)
elseif isa(l, GridLayout)
# sub-grid
if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width)
end
if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height)
end
l, sps, m = build_layout(l, numsp-i, plts)
append!(subplots, sps)
merge!(spmap, m)
i += length(sps)
end
i >= numsp && break # only add n subplots
end
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=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
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# make all reference the same axis extrema/values. # make all reference the same axis extrema/values.
# merge subplot lists. # merge subplot lists.
function link_axes!(axes::Axis...) function link_axes!(axes::Axis...)
a1 = axes[1] a1 = axes[1]
for i=2:length(axes) for i in 2:length(axes)
a2 = axes[i] a2 = axes[i]
expand_extrema!(a1, ignorenan_extrema(a2)) expand_extrema!(a1, ignorenan_extrema(a2))
for k in (:extrema, :discrete_values, :continuous_values, :discrete_map) for k in (:extrema, :discrete_values, :continuous_values, :discrete_map)
@ -719,8 +607,8 @@ function link_subplots(a::AbstractArray{AbstractLayout}, axissym::Symbol)
for l in a for l in a
if isa(l, Subplot) if isa(l, Subplot)
push!(subplots, l) push!(subplots, l)
elseif isa(l, GridLayout) && size(l) == (1,1) elseif isa(l, GridLayout) && size(l) == (1, 1)
push!(subplots, l[1,1]) push!(subplots, l[1, 1])
end end
end end
subplots subplots
@ -736,20 +624,19 @@ function link_axes!(a::AbstractArray{AbstractLayout}, axissym::Symbol)
end end
# don't do anything for most layout types # don't do anything for most layout types
function link_axes!(l::AbstractLayout, link::Symbol) function link_axes!(l::AbstractLayout, link::Symbol) end
end
# process a GridLayout, recursively linking axes according to the link symbol # process a GridLayout, recursively linking axes according to the link symbol
function link_axes!(layout::GridLayout, link::Symbol) function link_axes!(layout::GridLayout, link::Symbol)
nr, nc = size(layout) nr, nc = size(layout)
if link in (:x, :both) if link in (:x, :both)
for c=1:nc for c in 1:nc
link_axes!(layout.grid[:,c], :xaxis) link_axes!(layout.grid[:, c], :xaxis)
end end
end end
if link in (:y, :both) if link in (:y, :both)
for r=1:nr for r in 1:nr
link_axes!(layout.grid[r,:], :yaxis) link_axes!(layout.grid[r, :], :yaxis)
end end
end end
if link == :square if link == :square
@ -775,11 +662,20 @@ end
"Adds a new, empty subplot overlayed on top of `sp`, with a mirrored y-axis and linked x-axis." "Adds a new, empty subplot overlayed on top of `sp`, with a mirrored y-axis and linked x-axis."
function twinx(sp::Subplot) function twinx(sp::Subplot)
sp[:right_margin] = max(sp[:right_margin], 30px) plot!(
plot!(sp.plt, inset = (sp[:subplot_index], bbox(0,0,1,1))) sp.plt,
inset = (sp[:subplot_index], bbox(0, 0, 1, 1)),
right_margin = sp[:right_margin],
left_margin = sp[:left_margin],
top_margin = sp[:top_margin],
bottom_margin = sp[:bottom_margin],
)
twinsp = sp.plt.subplots[end] twinsp = sp.plt.subplots[end]
twinsp[:xaxis][:grid] = false
twinsp[:yaxis][:grid] = false
twinsp[:xaxis][:showaxis] = false
twinsp[:yaxis][:mirror] = true twinsp[:yaxis][:mirror] = true
twinsp[:background_color_inside] = RGBA{Float64}(0,0,0,0) twinsp[:background_color_inside] = RGBA{Float64}(0, 0, 0, 0)
link_axes!(sp[:xaxis], twinsp[:xaxis]) link_axes!(sp[:xaxis], twinsp[:xaxis])
twinsp twinsp
end end

View File

@ -4,24 +4,22 @@ legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax, inout)
``` ```
Return `(x,y)` at an angle `theta` degrees from Return `(x,y)` at an angle `theta` degrees from
`(xcenter,ycenter)` on a rectangle defined by (`xmin`, `(xcenter,ycenter)` on a rectangle defined by (`xmin`, `xmax`, `ymin`, `ymax`).
`xmax`, `ymin`, `ymax`).
""" """
function legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax) function legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax)
(s,c) = sincosd(theta) (s, c) = sincosd(theta)
x = c < 0 ? (xmin-xcenter)/c : (xmax-xcenter)/c x = c < 0 ? (xmin - xcenter) / c : (xmax - xcenter) / c
y = s < 0 ? (ymin-ycenter)/s : (ymax-ycenter)/s y = s < 0 ? (ymin - ycenter) / s : (ymax - ycenter) / s
A = min(x,y) A = min(x, y)
return (xcenter + A*c, ycenter + A*s) return (xcenter + A * c, ycenter + A * s)
end end
""" """
Split continuous range `[-1,1]` evenly into an integer `[1,2,3]` Split continuous range `[-1,1]` evenly into an integer `[1,2,3]`
""" """
function legend_anchor_index(x) function legend_anchor_index(x)
x<-1//3 && return 1 x < -1 // 3 && return 1
x<1//3 && return 2 x < 1 // 3 && return 2
return 3 return 3
end end
@ -32,28 +30,28 @@ so :topleft exactly corresponds to (45, :inner) etc.
If `leg` is a (::Real,::Real) tuple, keep it as is. If `leg` is a (::Real,::Real) tuple, keep it as is.
""" """
legend_angle(leg::Real) = (leg,:inner) legend_angle(leg::Real) = (leg, :inner)
legend_angle(leg::Tuple{S,T}) where {S<:Real,T<:Real} = leg legend_angle(leg::Tuple{S,T}) where {S<:Real,T<:Real} = leg
legend_angle(leg::Tuple{S,Symbol}) where S<:Real = leg legend_angle(leg::Tuple{S,Symbol}) where {S<:Real} = leg
legend_angle(leg::Symbol) = get( legend_angle(leg::Symbol) = get(
( (
topleft = (135,:inner), topleft = (135, :inner),
top = (90, :inner), top = (90, :inner),
topright = (45, :inner), topright = (45, :inner),
left = (180,:inner), left = (180, :inner),
right = (0, :inner), right = (0, :inner),
bottomleft = (225,:inner), bottomleft = (225, :inner),
bottom = (270,:inner), bottom = (270, :inner),
bottomright = (315,:inner), bottomright = (315, :inner),
outertopleft = (135,:outer), outertopleft = (135, :outer),
outertop = (90, :outer), outertop = (90, :outer),
outertopright = (45, :outer), outertopright = (45, :outer),
outerleft = (180,:outer), outerleft = (180, :outer),
outerright = (0, :outer), outerright = (0, :outer),
outerbottomleft = (225,:outer), outerbottomleft = (225, :outer),
outerbottom = (270,:outer), outerbottom = (270, :outer),
outerbottomright = (315,:outer), outerbottomright = (315, :outer),
), ),
leg, leg,
(45, :inner) (45, :inner),
) )

View File

@ -2,78 +2,68 @@
defaultOutputFormat(plt::Plot) = "png" defaultOutputFormat(plt::Plot) = "png"
function png(plt::Plot, fn::AbstractString) function png(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "png") open(addExtension(fn, "png"), "w") do io
io = open(fn, "w") show(io, MIME("image/png"), plt)
show(io, MIME("image/png"), plt) end
close(io)
end end
png(fn::AbstractString) = png(current(), fn) png(fn::AbstractString) = png(current(), fn)
function svg(plt::Plot, fn::AbstractString) function svg(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "svg") open(addExtension(fn, "svg"), "w") do io
io = open(fn, "w") show(io, MIME("image/svg+xml"), plt)
show(io, MIME("image/svg+xml"), plt) end
close(io)
end end
svg(fn::AbstractString) = svg(current(), fn) svg(fn::AbstractString) = svg(current(), fn)
function pdf(plt::Plot, fn::AbstractString) function pdf(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "pdf") open(addExtension(fn, "pdf"), "w") do io
io = open(fn, "w") show(io, MIME("application/pdf"), plt)
show(io, MIME("application/pdf"), plt) end
close(io)
end end
pdf(fn::AbstractString) = pdf(current(), fn) pdf(fn::AbstractString) = pdf(current(), fn)
function ps(plt::Plot, fn::AbstractString) function ps(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "ps") open(addExtension(fn, "ps"), "w") do io
io = open(fn, "w") show(io, MIME("application/postscript"), plt)
show(io, MIME("application/postscript"), plt) end
close(io)
end end
ps(fn::AbstractString) = ps(current(), fn) ps(fn::AbstractString) = ps(current(), fn)
function eps(plt::Plot, fn::AbstractString) function eps(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "eps") open(addExtension(fn, "eps"), "w") do io
io = open(fn, "w") show(io, MIME("image/eps"), plt)
show(io, MIME("image/eps"), plt) end
close(io)
end end
eps(fn::AbstractString) = eps(current(), fn) eps(fn::AbstractString) = eps(current(), fn)
function tex(plt::Plot, fn::AbstractString) function tex(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "tex") open(addExtension(fn, "tex"), "w") do io
io = open(fn, "w") show(io, MIME("application/x-tex"), plt)
show(io, MIME("application/x-tex"), plt) end
close(io)
end end
tex(fn::AbstractString) = tex(current(), fn) tex(fn::AbstractString) = tex(current(), fn)
function json(plt::Plot, fn::AbstractString) function json(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "json") open(addExtension(fn, "json"), "w") do io
io = open(fn, "w") show(io, MIME("application/vnd.plotly.v1+json"), plt)
show(io, MIME("application/vnd.plotly.v1+json"), plt) end
close(io)
end end
json(fn::AbstractString) = json(current(), fn) json(fn::AbstractString) = json(current(), fn)
function html(plt::Plot, fn::AbstractString) function html(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "html") open(addExtension(fn, "html"), "w") do io
io = open(fn, "w") show(io, MIME("text/html"), plt)
show(io, MIME("text/html"), plt) end
close(io)
end end
html(fn::AbstractString) = html(current(), fn) html(fn::AbstractString) = html(current(), fn)
function txt(plt::Plot, fn::AbstractString) function txt(plt::Plot, fn::AbstractString; color::Bool = true)
fn = addExtension(fn, "txt") open(addExtension(fn, "txt"), "w") do io
io = open(fn, "w") show(IOContext(io, :color => color), MIME("text/plain"), plt)
show(io, MIME("text/plain"), plt) end
close(io)
end end
txt(fn::AbstractString) = txt(current(), fn) txt(fn::AbstractString) = txt(current(), fn)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
const _savemap = Dict( const _savemap = Dict(
@ -89,6 +79,13 @@ const _savemap = Dict(
"txt" => txt, "txt" => txt,
) )
for out in Symbol.(unique(values(_savemap)))
@eval @doc """
$($out)([plot,], filename)
Save plot as $($out)-file.
""" $out
end
const _extension_map = Dict("tikz" => "tex") const _extension_map = Dict("tikz" => "tex")
function addExtension(fn::AbstractString, ext::AbstractString) function addExtension(fn::AbstractString, ext::AbstractString)
@ -128,7 +125,6 @@ function savefig(plt::Plot, fn::AbstractString)
end end
savefig(fn::AbstractString) = savefig(current(), fn) savefig(fn::AbstractString) = savefig(current(), fn)
# --------------------------------------------------------- # ---------------------------------------------------------
""" """
@ -186,8 +182,8 @@ function _show(io::IO, ::MIME"text/html", plt::Plot)
end end
# delegate showable to _show instead # delegate showable to _show instead
function Base.showable(m::M, plt::P) where {M <: MIME, P <: Plot} function Base.showable(m::M, plt::P) where {M<:MIME,P<:Plot}
return hasmethod(_show, Tuple{IO, M, P}) return hasmethod(_show, Tuple{IO,M,P})
end end
function _display(plt::Plot) function _display(plt::Plot)
@ -198,6 +194,7 @@ Base.show(io::IO, m::MIME"text/plain", plt::Plot) = show(io, plt)
# for writing to io streams... first prepare, then callback # for writing to io streams... first prepare, then callback
for mime in ( for mime in (
"text/html", "text/html",
"text/latex",
"image/png", "image/png",
"image/eps", "image/eps",
"image/svg+xml", "image/svg+xml",
@ -218,13 +215,14 @@ for mime in (
end end
end end
Base.showable(::MIME"text/html", plt::Plot{UnicodePlotsBackend}) = false # Pluto
Base.show(io::IO, m::MIME"application/prs.juno.plotpane+html", plt::Plot) = Base.show(io::IO, m::MIME"application/prs.juno.plotpane+html", plt::Plot) =
showjuno(io, MIME("text/html"), plt) showjuno(io, MIME("text/html"), plt)
"Close all open gui windows of the current backend" "Close all open gui windows of the current backend"
closeall() = closeall(backend()) closeall() = closeall(backend())
# function html_output_format(fmt) # function html_output_format(fmt)
# if fmt == "png" # if fmt == "png"
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot) # @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
@ -241,7 +239,6 @@ closeall() = closeall(backend())
# #
# html_output_format("svg") # html_output_format("svg")
# --------------------------------------------------------- # ---------------------------------------------------------
# Atom PlotPane # Atom PlotPane
# --------------------------------------------------------- # ---------------------------------------------------------

View File

@ -8,29 +8,18 @@ function RecipesPipeline.warn_on_recipe_aliases!(
recipe_type::Symbol, recipe_type::Symbol,
@nospecialize(args) @nospecialize(args)
) )
for k in keys(plotattributes) pkeys = keys(plotattributes)
if !is_default_attribute(k) for k in pkeys
dk = get(_keyAliases, k, k) dk = get(_keyAliases, k, nothing)
if k !== dk if dk !== nothing
if recipe_type == :user kv = RecipesPipeline.pop_kw!(plotattributes, k)
signature_string = RecipesPipeline.userrecipe_signature_string(args) if dk pkeys
elseif recipe_type == :type plotattributes[dk] = kv
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`."
end end
plotattributes[dk] = RecipesPipeline.pop_kw!(plotattributes, k)
end end
end end
end end
## Grouping ## Grouping
RecipesPipeline.splittable_attribute(plt::Plot, key, val::SeriesAnnotations, len) = RecipesPipeline.splittable_attribute(plt::Plot, key, val::SeriesAnnotations, len) =
@ -41,7 +30,6 @@ function RecipesPipeline.split_attribute(plt::Plot, key, val::SeriesAnnotations,
return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor) return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor)
end end
## Preprocessing attributes ## Preprocessing attributes
function RecipesPipeline.preprocess_axis_args!(plt::Plot, plotattributes, letter) function RecipesPipeline.preprocess_axis_args!(plt::Plot, plotattributes, letter)
# Fix letter for seriestypes that are x only but data gets passed as y # Fix letter for seriestypes that are x only but data gets passed as y
@ -62,7 +50,6 @@ RecipesPipeline.is_axis_attribute(plt::Plot, attr) = is_axis_attr_noletter(attr)
RecipesPipeline.is_subplot_attribute(plt::Plot, attr) = is_subplot_attr(attr) # in src/args.jl RecipesPipeline.is_subplot_attribute(plt::Plot, attr) = is_subplot_attr(attr) # in src/args.jl
## User recipes ## User recipes
function RecipesPipeline.process_userrecipe!(plt::Plot, kw_list, kw) function RecipesPipeline.process_userrecipe!(plt::Plot, kw_list, kw)
@ -81,23 +68,32 @@ end
function _preprocess_userrecipe(kw::AKW) function _preprocess_userrecipe(kw::AKW)
_add_markershape(kw) _add_markershape(kw)
if get(kw, :permute, default(:permute)) != :none
l1, l2 = kw[:permute]
for k in _axis_args
k1 = _attrsymbolcache[l1][k]
k2 = _attrsymbolcache[l2][k]
kwk = keys(kw)
if k1 in kwk || k2 in kwk
kw[k1], kw[k2] = get(kw, k2, default(k2)), get(kw, k1, default(k1))
end
end
end
# map marker_z if it's a Function # map marker_z if it's a Function
if isa(get(kw, :marker_z, nothing), Function) if isa(get(kw, :marker_z, default(:marker_z)), Function)
# TODO: should this take y and/or z as arguments? # TODO: should this take y and/or z as arguments?
kw[:marker_z] = isa(kw[:z], Nothing) ? map(kw[:marker_z], kw[:x], kw[:y]) : kw[:marker_z] =
isa(kw[:z], Nothing) ? map(kw[:marker_z], kw[:x], kw[:y]) :
map(kw[:marker_z], kw[:x], kw[:y], kw[:z]) map(kw[:marker_z], kw[:x], kw[:y], kw[:z])
end end
# map line_z if it's a Function # map line_z if it's a Function
if isa(get(kw, :line_z, nothing), Function) if isa(get(kw, :line_z, default(:line_z)), Function)
kw[:line_z] = isa(kw[:z], Nothing) ? map(kw[:line_z], kw[:x], kw[:y]) : kw[:line_z] =
isa(kw[:z], Nothing) ? map(kw[:line_z], kw[:x], kw[:y]) :
map(kw[:line_z], kw[:x], kw[:y], kw[:z]) map(kw[:line_z], kw[:x], kw[:y], kw[:z])
end end
# convert a ribbon into a fillrange
if get(kw, :ribbon, nothing) !== nothing
make_fillrange_from_ribbon(kw)
end
return return
end end
@ -140,15 +136,12 @@ function _add_smooth_kw(kw_list::Vector{KW}, kw::AKW)
end end
end end
RecipesPipeline.get_axis_limits(plt::Plot, letter) = axis_limits(plt[1], letter, false)
RecipesPipeline.get_axis_limits(plt::Plot, letter) = axis_limits(plt[1], letter)
## Plot recipes ## Plot recipes
RecipesPipeline.type_alias(plt::Plot) = get(_typeAliases, st, st) RecipesPipeline.type_alias(plt::Plot) = get(_typeAliases, st, st)
## Plot setup ## Plot setup
function RecipesPipeline.plot_setup!(plt::Plot, plotattributes, kw_list) function RecipesPipeline.plot_setup!(plt::Plot, plotattributes, kw_list)
@ -159,18 +152,34 @@ end
function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_list) function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_list)
# swap errors # swap errors
err_inds = findall(kw -> get(kw, :seriestype, :path) in (:xerror, :yerror, :zerror), kw_list) err_inds =
findall(kw -> get(kw, :seriestype, :path) in (:xerror, :yerror, :zerror), kw_list)
for ind in err_inds for ind in err_inds
if get(kw_list[ind-1],:seriestype,:path) == :scatter if get(kw_list[ind - 1], :seriestype, :path) == :scatter
tmp = copy(kw_list[ind]) tmp = copy(kw_list[ind])
kw_list[ind] = copy(kw_list[ind-1]) kw_list[ind] = copy(kw_list[ind - 1])
kw_list[ind-1] = tmp kw_list[ind - 1] = tmp
end
end
for kw in kw_list
rib = get(kw, :ribbon, default(:ribbon))
fr = get(kw, :fillrange, default(:fillrange))
# map ribbon if it's a Function
if rib isa Function
kw[:ribbon] = map(rib, kw[:x])
end
# convert a ribbon into a fillrange
if rib !== nothing
make_fillrange_from_ribbon(kw)
# map fillrange if it's a Function
elseif fr !== nothing && fr isa Function
kw[:fillrange] = map(fr, kw[:x])
end end
end end
return nothing return nothing
end end
# TODO: Should some of this logic be moved to RecipesPipeline? # TODO: Should some of this logic be moved to RecipesPipeline?
function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW}) function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
# merge in anything meant for the Plot # merge in anything meant for the Plot
@ -193,7 +202,6 @@ function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
plt.init = true plt.init = true
end end
# handle inset subplots # handle inset subplots
insets = plt[:inset_subplots] insets = plt[:inset_subplots]
if insets !== nothing if insets !== nothing
@ -226,7 +234,7 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
# Subplot/Axis attributes set by a user/series recipe apply only to the # Subplot/Axis attributes set by a user/series recipe apply only to the
# Subplot object which they belong to. # Subplot object which they belong to.
# TODO: allow matrices to still apply to all subplots # TODO: allow matrices to still apply to all subplots
sp_attrs = Dict{Subplot, Any}() sp_attrs = Dict{Subplot,Any}()
for kw in kw_list for kw in kw_list
# get the Subplot object to which the series belongs. # get the Subplot object to which the series belongs.
sps = get(kw, :subplot, :auto) sps = get(kw, :subplot, :auto)
@ -243,25 +251,33 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
attr = KW() attr = KW()
for (k, v) in collect(kw) for (k, v) in collect(kw)
if is_subplot_attr(k) || is_axis_attr(k) if is_subplot_attr(k) || is_axis_attr(k)
attr[k] = pop!(kw, k) v = pop!(kw, k)
if sps isa AbstractArray && v isa AbstractArray && length(v) == length(sps)
v = v[series_idx(kw_list, kw)]
end
attr[k] = v
end end
if is_axis_attr_noletter(k) if is_axis_attr_noletter(k)
v = pop!(kw, k) v = pop!(kw, k)
if sps isa AbstractArray && v isa AbstractArray && length(v) == length(sps)
v = v[series_idx(kw_list, kw)]
end
for letter in (:x, :y, :z) for letter in (:x, :y, :z)
attr[Symbol(letter, k)] = v attr[get_attr_symbol(letter, k)] = v
end end
end end
for k in (:scale,), letter in (:x, :y, :z) end
# Series recipes may need access to this information for k in (:scale,), letter in (:x, :y, :z)
lk = Symbol(letter, k) # Series recipes may need access to this information
if haskey(attr, lk) lk = get_attr_symbol(letter, k)
kw[lk] = attr[lk] if haskey(attr, lk)
end kw[lk] = attr[lk]
end end
end end
sp_attrs[sp] = attr sp_attrs[sp] = attr
end end
_add_plot_title!(plt)
# override subplot/axis args. `sp_attrs` take precendence # override subplot/axis args. `sp_attrs` take precendence
for (idx, sp) in enumerate(plt.subplots) for (idx, sp) in enumerate(plt.subplots)
attr = if !haskey(plotattributes, :subplot) || plotattributes[:subplot] == idx attr = if !haskey(plotattributes, :subplot) || plotattributes[:subplot] == idx
@ -274,12 +290,48 @@ function _subplot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
# do we need to link any axes together? # do we need to link any axes together?
link_axes!(plt.layout, plt[:link]) link_axes!(plt.layout, plt[:link])
return nothing
end end
function series_idx(kw_list::AVec{KW}, kw::AKW) function series_idx(kw_list::AVec{KW}, kw::AKW)
Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1 Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1
end end
function _add_plot_title!(plt)
plot_title = plt[:plot_title]
plot_titleindex = nothing
if plot_title != ""
# make new subplot for plot title
if plt[:plot_titleindex] == 0
the_layout = plt.layout
vspan = plt[:plot_titlevspan]
plt.layout = grid(2, 1, heights = (vspan, 1 - vspan))
plt.layout.grid[1, 1] =
subplot = Subplot(plt.backend, parent = plt.layout[1, 1])
plt.layout.grid[2, 1] = the_layout
subplot.plt = plt
top = plt.backend isa PyPlotBackend ? nothing : 0mm
bot = 0mm
plt[:force_minpad] = nothing, top, nothing, bot
subplot[:subplot_index] = last(plt.subplots)[:subplot_index] + 1
plt[:plot_titleindex] = subplot[:subplot_index]
subplot[:framestyle] = :none
subplot[:margin] = 0px
push!(plt.subplots, subplot)
end
# propagate arguments plt[:plot_titleXXX] --> subplot[:titleXXX]
plot_titleindex = plt[:plot_titleindex]
subplot = plt.subplots[plot_titleindex]
for sym in filter(x -> startswith(string(x), "plot_title"), keys(_plot_defaults))
subplot[Symbol(string(sym)[(length("plot_") + 1):end])] = plt[sym]
end
end
return plot_titleindex
end
## Series recipes ## Series recipes
@ -297,6 +349,19 @@ RecipesPipeline.is_seriestype_supported(plt::Plot, st) = is_seriestype_supported
function RecipesPipeline.add_series!(plt::Plot, plotattributes) function RecipesPipeline.add_series!(plt::Plot, plotattributes)
sp = _prepare_subplot(plt, plotattributes) sp = _prepare_subplot(plt, plotattributes)
if plotattributes[:permute] != :none
letter1, letter2 = plotattributes[:permute]
if plotattributes[:markershape] == :hline &&
(plotattributes[:permute] == (:x, :y) || plotattributes[:permute] == (:y, :x))
plotattributes[:markershape] = :vline
elseif plotattributes[:markershape] == :vline && (
plotattributes[:permute] == (:x, :y) || plotattributes[:permute] == (:y, :x)
)
plotattributes[:markershape] = :hline
end
plotattributes[letter1], plotattributes[letter2] =
plotattributes[letter2], plotattributes[letter1]
end
_expand_subplot_extrema(sp, plotattributes, plotattributes[:seriestype]) _expand_subplot_extrema(sp, plotattributes, plotattributes[:seriestype])
_update_series_attributes!(plotattributes, plt, sp) _update_series_attributes!(plotattributes, plt, sp)
_add_the_series(plt, sp, plotattributes) _add_the_series(plt, sp, plotattributes)
@ -313,7 +378,10 @@ function _prepare_subplot(plt::Plot{T}, plotattributes::AKW) where {T}
st = _override_seriestype_check(plotattributes, st) st = _override_seriestype_check(plotattributes, st)
# change to a 3d projection for this subplot? # change to a 3d projection for this subplot?
if RecipesPipeline.needs_3d_axes(st) if (
RecipesPipeline.needs_3d_axes(st) ||
(st == :quiver && plotattributes[:z] !== nothing)
)
sp.attr[:projection] = "3d" sp.attr[:projection] = "3d"
end end
@ -329,8 +397,10 @@ function _override_seriestype_check(plotattributes::AKW, st::Symbol)
# do we want to override the series type? # do we want to override the series type?
if !RecipesPipeline.is3d(st) && !(st in (:contour, :contour3d, :quiver)) if !RecipesPipeline.is3d(st) && !(st in (:contour, :contour3d, :quiver))
z = plotattributes[:z] z = plotattributes[:z]
if !isa(z, Nothing) && if (
(size(plotattributes[:x]) == size(plotattributes[:y]) == size(z)) z !== nothing &&
(size(plotattributes[:x]) == size(plotattributes[:y]) == size(z))
)
st = (st == :scatter ? :scatter3d : :path3d) st = (st == :scatter ? :scatter3d : :path3d)
plotattributes[:seriestype] = st plotattributes[:seriestype] = st
end end
@ -338,6 +408,14 @@ function _override_seriestype_check(plotattributes::AKW, st::Symbol)
st st
end end
function needs_any_3d_axes(sp::Subplot)
any(
RecipesPipeline.needs_3d_axes(
_override_seriestype_check(s.plotattributes, s.plotattributes[:seriestype]),
) for s in series_list(sp)
)
end
function _expand_subplot_extrema(sp::Subplot, plotattributes::AKW, st::Symbol) function _expand_subplot_extrema(sp::Subplot, plotattributes::AKW, st::Symbol)
# adjust extrema and discrete info # adjust extrema and discrete info
if st == :image if st == :image
@ -358,9 +436,9 @@ end
function _add_the_series(plt, sp, plotattributes) function _add_the_series(plt, sp, plotattributes)
extra_kwargs = warn_on_unsupported_args(plt.backend, plotattributes) extra_kwargs = warn_on_unsupported_args(plt.backend, plotattributes)
if (kw = plt[:extra_kwargs]) isa AbstractDict if (kw = plt[:extra_kwargs]) isa AbstractDict
plt[:extra_plot_kwargs] = get(kw,:plot,KW()) plt[:extra_plot_kwargs] = get(kw, :plot, KW())
sp[:extra_kwargs] = get(kw,:subplot, KW()) sp[:extra_kwargs] = get(kw, :subplot, KW())
plotattributes[:extra_kwargs] = get(kw,:series,KW()) plotattributes[:extra_kwargs] = get(kw, :series, KW())
elseif plt[:extra_kwargs] == :plot elseif plt[:extra_kwargs] == :plot
plt[:extra_plot_kwargs] = extra_kwargs plt[:extra_plot_kwargs] = extra_kwargs
elseif plt[:extra_kwargs] == :subplot elseif plt[:extra_kwargs] == :subplot
@ -373,6 +451,16 @@ function _add_the_series(plt, sp, plotattributes)
warn_on_unsupported(plt.backend, plotattributes) warn_on_unsupported(plt.backend, plotattributes)
series = Series(plotattributes) series = Series(plotattributes)
push!(plt.series_list, series) push!(plt.series_list, series)
push!(sp.series_list, series) z_order = plotattributes[:z_order]
if z_order == :front
push!(sp.series_list, series)
elseif z_order == :back
pushfirst!(sp.series_list, series)
elseif z_order isa Integer
insert!(sp.series_list, z_order, series)
else
@error "Wrong type $(typeof(z_order)) for attribute z_order"
end
_series_added(plt, series) _series_added(plt, series)
_update_subplot_colorbars(sp)
end end

View File

@ -1,6 +1,6 @@
mutable struct CurrentPlot mutable struct CurrentPlot
nullableplot::Union{AbstractPlot, Nothing} nullableplot::Union{AbstractPlot,Nothing}
end end
const CURRENT_PLOT = CurrentPlot(nothing) const CURRENT_PLOT = CurrentPlot(nothing)
@ -20,10 +20,44 @@ current(plot::AbstractPlot) = (CURRENT_PLOT.nullableplot = plot)
# --------------------------------------------------------- # ---------------------------------------------------------
Base.string(plt::Plot) = "Plot{$(plt.backend) n=$(plt.n)}" Base.string(plt::Plot) = "Plot{$(plt.backend) n=$(plt.n)}"
Base.print(io::IO, plt::Plot) = print(io, string(plt)) Base.print(io::IO, plt::Plot) = print(io, string(plt))
Base.show(io::IO, plt::Plot) = print(io, string(plt)) function Base.show(io::IO, plt::Plot)
print(io, string(plt))
sp_ekwargs = getindex.(plt.subplots, :extra_kwargs)
s_ekwargs = getindex.(plt.series_list, :extra_kwargs)
if (
isempty(plt[:extra_plot_kwargs]) &&
all(isempty, sp_ekwargs) &&
all(isempty, s_ekwargs)
)
return
end
print(io, "\nCaptured extra kwargs:\n")
do_show = true
for (key, value) in plt[:extra_plot_kwargs]
do_show && println(io, " Plot:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
for (i, ekwargs) in enumerate(sp_ekwargs)
for (key, value) in ekwargs
do_show && println(io, " SubplotPlot{$i}:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
end
for (i, ekwargs) in enumerate(s_ekwargs)
for (key, value) in ekwargs
do_show && println(io, " Series{$i}:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
end
end
getplot(plt::Plot) = plt getplot(plt::Plot) = plt
getattr(plt::Plot, idx::Int = 1) = plt.attr getattr(plt::Plot, idx::Int = 1) = plt.attr
@ -31,7 +65,6 @@ convertSeriesIndex(plt::Plot, n::Int) = n
# --------------------------------------------------------- # ---------------------------------------------------------
""" """
The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one: The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one:
@ -42,7 +75,7 @@ The main plot command. Use `plot` to create a new plot object, and `plot!` to ad
``` ```
There are lots of ways to pass in data, and lots of keyword arguments... just try it and it will likely work as expected. There are lots of ways to pass in data, and lots of keyword arguments... just try it and it will likely work as expected.
When you pass in matrices, it splits by columns. To see the list of available attributes, use the `plotattr([attr])` When you pass in matrices, it splits by columns. To see the list of available attributes, use the `plotattr(attr)`
function, where `attr` is the symbol `:Series`, `:Subplot`, `:Plot`, or `:Axis`. Pass any attribute to `plotattr` function, where `attr` is the symbol `:Series`, `:Subplot`, `:Plot`, or `:Axis`. Pass any attribute to `plotattr`
as a String to look up its docstring, e.g., `plotattr("seriestype")`. as a String to look up its docstring, e.g., `plotattr("seriestype")`.
""" """
@ -59,18 +92,21 @@ function plot(args...; kw...)
end end
# build a new plot from existing plots # build a new plot from existing plots
# note: we split into plt1 and plts_tail so we can dispatch correctly # note: we split into plt1, plt2 and plts_tail so we can dispatch correctly
function plot(plt1::Plot, plts_tail::Plot...; kw...) plot(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...) =
plot!(deepcopy(plt1), deepcopy(plt2), deepcopy.(plts_tail)...; kw...)
function plot!(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...)
@nospecialize @nospecialize
plotattributes = KW(kw) plotattributes = KW(kw)
RecipesPipeline.preprocess_attributes!(plotattributes) RecipesPipeline.preprocess_attributes!(plotattributes)
# build our plot vector from the args # build our plot vector from the args
n = length(plts_tail) + 1 n = length(plts_tail) + 2
plts = Array{Plot}(undef, n) plts = Array{Plot}(undef, n)
plts[1] = plt1 plts[1] = plt1
for (i,plt) in enumerate(plts_tail) plts[2] = plt2
plts[i+1] = plt for (i, plt) in enumerate(plts_tail)
plts[i + 2] = plt
end end
# compute the layout # compute the layout
@ -97,9 +133,9 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
plt.init = true plt.init = true
series_attr = KW() series_attr = KW()
for (k,v) in plotattributes for (k, v) in plotattributes
if is_series_attr(k) if is_series_attr(k)
series_attr[k] = pop!(plotattributes,k) series_attr[k] = pop!(plotattributes, k)
end end
end end
@ -127,10 +163,11 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
cmdidx += 1 cmdidx += 1
end end
end end
ttl_idx = _add_plot_title!(plt)
# first apply any args for the subplots # first apply any args for the subplots
for (idx,sp) in enumerate(plt.subplots) for (idx, sp) in enumerate(plt.subplots)
_update_subplot_args(plt, sp, plotattributes, idx, false) _update_subplot_args(plt, sp, idx == ttl_idx ? KW() : plotattributes, idx, false)
end end
# finish up # finish up
@ -139,8 +176,6 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
plt plt
end end
# this adds to the current plot, or creates a new plot if none are current # this adds to the current plot, or creates a new plot if none are current
function plot!(args...; kw...) function plot!(args...; kw...)
@nospecialize @nospecialize
@ -154,6 +189,7 @@ function plot!(args...; kw...)
end end
# this adds to a specific plot... most plot commands will flow through here # this adds to a specific plot... most plot commands will flow through here
plot(plt::Plot, args...; kw...) = plot!(deepcopy(plt), args...; kw...)
function plot!(plt::Plot, args...; kw...) function plot!(plt::Plot, args...; kw...)
@nospecialize @nospecialize
plotattributes = KW(kw) plotattributes = KW(kw)
@ -175,14 +211,13 @@ function _plot!(plt::Plot, plotattributes, args)
return plt return plt
end end
# we're getting ready to display/output. prep for layout calcs, then update # we're getting ready to display/output. prep for layout calcs, then update
# the plot object after # the plot object after
function prepare_output(plt::Plot) function prepare_output(plt::Plot)
_before_layout_calcs(plt) _before_layout_calcs(plt)
w, h = plt.attr[:size] w, h = plt.attr[:size]
plt.layout.bbox = BoundingBox(0mm, 0mm, w*px, h*px) plt.layout.bbox = BoundingBox(0mm, 0mm, w * px, h * px)
# One pass down and back up the tree to compute the minimum padding # One pass down and back up the tree to compute the minimum padding
# of the children on the perimeter. This is an backend callback. # of the children on the perimeter. This is an backend callback.
@ -191,6 +226,17 @@ function prepare_output(plt::Plot)
_update_min_padding!(sp) _update_min_padding!(sp)
end end
# spedific to :plot_title see _add_plot_title!
force_minpad = get(plt, :force_minpad, ())
if !isempty(force_minpad)
for i in eachindex(plt.layout.grid)
plt.layout.grid[i].minpad = Tuple(
i === nothing ? j : i for
(i, j) in zip(force_minpad, plt.layout.grid[i].minpad)
)
end
end
# now another pass down, to update the bounding boxes # now another pass down, to update the bounding boxes
update_child_bboxes!(plt.layout) update_child_bboxes!(plt.layout)
@ -201,6 +247,12 @@ function prepare_output(plt::Plot)
_update_plot_object(plt) _update_plot_object(plt)
end end
"""
backend_object(plot)
Returns the backend representation of a Plot object.
Returns `nothing` if the backend does not support this.
"""
function backend_object(plt::Plot) function backend_object(plt::Plot)
prepare_output(plt) prepare_output(plt)
plt.o plt.o

View File

@ -1,8 +1,10 @@
const _attribute_defaults = Dict(:Series => _series_defaults, const _attribute_defaults = Dict(
:Subplot => _subplot_defaults, :Series => _series_defaults,
:Plot => _plot_defaults, :Subplot => _subplot_defaults,
:Axis => _axis_defaults) :Plot => _plot_defaults,
:Axis => _axis_defaults,
)
attrtypes() = join(keys(_attribute_defaults), ", ") attrtypes() = join(keys(_attribute_defaults), ", ")
attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype]))) attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype])))
@ -21,7 +23,9 @@ Look up the properties of a Plots attribute, or specify an attribute type. Call
The information is the same as that given on https://docs.juliaplots.org/latest/attributes/. The information is the same as that given on https://docs.juliaplots.org/latest/attributes/.
""" """
function plotattr() function plotattr()
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())") println(
"Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())",
)
end end
function plotattr(attrtype::Symbol) function plotattr(attrtype::Symbol)
@ -44,27 +48,32 @@ printnothing(x) = x
printnothing(x::Nothing) = "nothing" printnothing(x::Nothing) = "nothing"
function plotattr(attrtype::Symbol, attribute::AbstractString) function plotattr(attrtype::Symbol, attribute::AbstractString)
in(attrtype, keys(_attribute_defaults)) || ArgumentError("`attrtype` must match one of $(attrtypes())") in(attrtype, keys(_attribute_defaults)) ||
ArgumentError("`attrtype` must match one of $(attrtypes())")
attribute = Symbol(lookup_aliases(attrtype, attribute)) attribute = Symbol(lookup_aliases(attrtype, attribute))
desc = get(_arg_desc, attribute, "") desc = get(_arg_desc, attribute, "")
first_period_idx = findfirst(isequal('.'), desc) first_period_idx = findfirst(isequal('.'), desc)
if isnothing(first_period_idx) if isnothing(first_period_idx)
typedesc = "" typedesc = ""
desc = strip(desc) desc = strip(desc)
else else
typedesc = desc[1:first_period_idx-1] typedesc = desc[1:(first_period_idx - 1)]
desc = strip(desc[first_period_idx+1:end]) desc = strip(desc[(first_period_idx + 1):end])
end end
als = keys(filter(x->x[2]==attribute, _keyAliases)) |> collect |> sort als = keys(filter(x -> x[2] == attribute, _keyAliases)) |> collect |> sort
als = join(map(string,als), ", ") als = join(map(string, als), ", ")
def = _attribute_defaults[attrtype][attribute] def = _attribute_defaults[attrtype][attribute]
# Looks up the different elements and plots them # Looks up the different elements and plots them
println("$(printnothing(attribute)) ", typedesc == "" ? "" : "{$(printnothing(typedesc))}", "\n", println(
"$(printnothing(attribute)) ",
typedesc == "" ? "" : "{$(printnothing(typedesc))}",
"\n",
als == "" ? "" : "$(printnothing(als))\n", als == "" ? "" : "$(printnothing(als))\n",
"\n$(printnothing(desc))\n", "\n$(printnothing(desc))\n",
"$(printnothing(attrtype)) attribute, ", def == "" ? "" : " default: $(printnothing(def))") "$(printnothing(attrtype)) attribute, ",
def == "" ? "" : " default: $(printnothing(def))",
)
end end

View File

@ -1,20 +1,40 @@
should_precompile = true #! format: off
should_precompile = true
# Don't edit the following! Instead change the script for `snoop_bot`. # Don't edit the following! Instead change the script for `snoop_bot`.
ismultios = false ismultios = false
ismultiversion = false ismultiversion = true
# precompile_enclosure # precompile_enclosure
@static if !should_precompile @static if !should_precompile
# nothing # nothing
elseif !ismultios && !ismultiversion elseif !ismultios && !ismultiversion
@static if isfile(joinpath( @static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_Plots.jl"))
@__DIR__,
"../deps/SnoopCompile/precompile/precompile_Plots.jl",
))
include("../deps/SnoopCompile/precompile/precompile_Plots.jl") include("../deps/SnoopCompile/precompile/precompile_Plots.jl")
_precompile_() _precompile_()
end end
else else
@static if v"1.6.0-DEV" <= VERSION <= v"1.6.9"
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.6/precompile_Plots.jl"))
include("../deps/SnoopCompile/precompile//1.6/precompile_Plots.jl")
_precompile_()
end
elseif v"1.7.0-DEV" <= VERSION <= v"1.7.9"
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.7/precompile_Plots.jl"))
include("../deps/SnoopCompile/precompile//1.7/precompile_Plots.jl")
_precompile_()
end
elseif v"1.8.0-DEV" <= VERSION <= v"1.8.9"
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.8/precompile_Plots.jl"))
include("../deps/SnoopCompile/precompile//1.8/precompile_Plots.jl")
_precompile_()
end
elseif v"1.9.0-DEV" <= VERSION <= v"1.9.9"
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.9/precompile_Plots.jl"))
include("../deps/SnoopCompile/precompile//1.9/precompile_Plots.jl")
_precompile_()
end
else
end
end # precompile_enclosure end # precompile_enclosure

View File

@ -41,17 +41,16 @@ function all_seriestypes()
sort(collect(sts)) sort(collect(sts))
end end
# ---------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------
num_series(x::AMat) = size(x, 2) num_series(x::AMat) = size(x, 2)
num_series(x) = 1 num_series(x) = 1
RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T")) RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} =
nothing
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# for seriestype `line`, need to sort by x values # for seriestype `line`, need to sort by x values
const POTENTIAL_VECTOR_ARGUMENTS = [ const POTENTIAL_VECTOR_ARGUMENTS = [
@ -114,8 +113,8 @@ end
@recipe function f(::Type{Val{:hline}}, x, y, z) @recipe function f(::Type{Val{:hline}}, x, y, z)
n = length(y) n = length(y)
newx = repeat(Float64[1, 2, NaN], n) newx = repeat(Float64[1, 2, NaN], n)
newy = vec(Float64[yi for i = 1:3, yi in y]) newy = vec(Float64[yi for i in 1:3, yi in y])
x := newx x := newx
y := newy y := newy
seriestype := :straightline seriestype := :straightline
@ -125,7 +124,7 @@ end
@recipe function f(::Type{Val{:vline}}, x, y, z) @recipe function f(::Type{Val{:vline}}, x, y, z)
n = length(y) n = length(y)
newx = vec(Float64[yi for i = 1:3, yi in y]) newx = vec(Float64[yi for i in 1:3, yi in y])
x := newx x := newx
y := repeat(Float64[1, 2, NaN], n) y := repeat(Float64[1, 2, NaN], n)
seriestype := :straightline seriestype := :straightline
@ -136,7 +135,7 @@ end
@recipe function f(::Type{Val{:hspan}}, x, y, z) @recipe function f(::Type{Val{:hspan}}, x, y, z)
n = div(length(y), 2) n = div(length(y), 2)
newx = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n) newx = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n)
newy = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...) newy = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i in 1:n]...)
linewidth --> 0 linewidth --> 0
x := newx x := newx
y := newy y := newy
@ -147,7 +146,7 @@ end
@recipe function f(::Type{Val{:vspan}}, x, y, z) @recipe function f(::Type{Val{:vspan}}, x, y, z)
n = div(length(y), 2) n = div(length(y), 2)
newx = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...) newx = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i in 1:n]...)
newy = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n) newy = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n)
linewidth --> 0 linewidth --> 0
x := newx x := newx
@ -165,18 +164,43 @@ end
x := x x := x
y := y y := y
seriestype := :scatter seriestype := :scatter
@series begin
()
end
@series begin @series begin
seriestype := :path seriestype := :path
label := "" label := ""
primary := false primary := false
() ()
end end
primary := false
() ()
end end
@deps scatterpath path scatter @deps scatterpath path scatter
@specialize # ---------------------------------------------------------------------------
# regression line and scatter
# plots line corresponding to linear regression of y on a constant and x
@recipe function f(::Type{Val{:linearfit}}, x, y, z)
x := x
y := y
seriestype := :scatter
@series begin
()
end
@series begin
y := mean(y) .+ cov(x, y) / var(x) .* (x .- mean(x))
seriestype := :path
label := ""
primary := false
()
end
primary := false
()
end
@specialize
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# steps # steps
@ -187,10 +211,10 @@ function make_steps(x::AbstractArray, st, even)
n == 0 && return zeros(0) n == 0 && return zeros(0)
newx = zeros(2n - (even ? 0 : 1)) newx = zeros(2n - (even ? 0 : 1))
newx[1] = x[1] newx[1] = x[1]
for i = 2:n for i in 2:n
idx = 2i - 1 idx = 2i - 1
if st == :mid if st == :mid
newx[idx] = newx[idx-1] = (x[i] + x[i-1]) / 2 newx[idx] = newx[idx - 1] = (x[i] + x[i - 1]) / 2
else else
newx[idx] = x[i] newx[idx] = x[i]
newx[idx - 1] = x[st == :pre ? i : i - 1] newx[idx - 1] = x[st == :pre ? i : i - 1]
@ -201,7 +225,6 @@ function make_steps(x::AbstractArray, st, even)
end end
make_steps(t::Tuple, st, even) = Tuple(make_steps(ti, st, even) for ti in t) make_steps(t::Tuple, st, even) = Tuple(make_steps(ti, st, even) for ti in t)
@nospecialize @nospecialize
# create a path from steps # create a path from steps
@ -279,7 +302,6 @@ end
end end
@deps steppost path scatter @deps steppost path scatter
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# sticks # sticks
@ -298,7 +320,7 @@ end
end end
newx, newy = zeros(3n), zeros(3n) newx, newy = zeros(3n), zeros(3n)
newz = z !== nothing ? zeros(3n) : nothing newz = z !== nothing ? zeros(3n) : nothing
for (i, (xi, yi, zi)) = enumerate(zip(x, y, z !== nothing ? z : 1:n)) for (i, (xi, yi, zi)) in enumerate(zip(x, y, z !== nothing ? z : 1:n))
rng = (3i - 2):(3i) rng = (3i - 2):(3i)
newx[rng] = [xi, xi, NaN] newx[rng] = [xi, xi, NaN]
if z !== nothing if z !== nothing
@ -315,7 +337,11 @@ end
end end
fillrange := nothing fillrange := nothing
seriestype := :path seriestype := :path
if plotattributes[:linecolor] == :auto && plotattributes[:marker_z] !== nothing && plotattributes[:line_z] === nothing if (
plotattributes[:linecolor] == :auto &&
plotattributes[:marker_z] !== nothing &&
plotattributes[:line_z] === nothing
)
line_z := plotattributes[:marker_z] line_z := plotattributes[:marker_z]
end end
@ -340,7 +366,6 @@ end
@specialize @specialize
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# bezier curves # bezier curves
@ -410,17 +435,18 @@ end
# create a bar plot as a filled step function # create a bar plot as a filled step function
@recipe function f(::Type{Val{:bar}}, x, y, z) @recipe function f(::Type{Val{:bar}}, x, y, z)
procx, procy, xscale, yscale, baseline = procx, procy, xscale, yscale, baseline = _preprocess_barlike(plotattributes, x, y)
_preprocess_barlike(plotattributes, x, y)
nx, ny = length(procx), length(procy) nx, ny = length(procx), length(procy)
axis = plotattributes[:subplot][isvertical(plotattributes) ? :xaxis : :yaxis] axis = plotattributes[:subplot][isvertical(plotattributes) ? :xaxis : :yaxis]
cv = [discrete_value!(axis, xi)[1] for xi in procx] cv = [discrete_value!(plotattributes, :x, xi)[1] for xi in procx]
procx = if nx == ny procx = if nx == ny
cv cv
elseif nx == ny + 1 elseif nx == ny + 1
0.5 * diff(cv) + cv[1:(end - 1)] 0.5 * diff(cv) + cv[1:(end - 1)]
else else
error("bar recipe: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))") error(
"bar recipe: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))",
)
end end
# compute half-width of bars # compute half-width of bars
@ -444,18 +470,8 @@ end
fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto) fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto)
end end
if !isnothing(plotattributes[:series_annotations])
if isvertical(plotattributes)
annotations := (x,y,plotattributes[:series_annotations].strs,:bottom)
else
annotations := (y,x,plotattributes[:series_annotations].strs,:left)
end
series_annotations := nothing
end
# create the bar shapes by adding x/y segments
xseg, yseg = Segments(), Segments() xseg, yseg = Segments(), Segments()
for i = 1:ny for i in 1:ny
yi = procy[i] yi = procy[i]
if !isnan(yi) if !isnan(yi)
center = procx[i] center = procx[i]
@ -479,15 +495,42 @@ end
# switch back # switch back
if !isvertical(plotattributes) if !isvertical(plotattributes)
xseg, yseg = yseg, xseg xseg, yseg = yseg, xseg
x, y = y, x
end end
# reset orientation # reset orientation
orientation := default(:orientation) orientation := default(:orientation)
x := xseg.pts # draw the bar shapes
y := yseg.pts @series begin
seriestype := :shape seriestype := :shape
series_annotations := nothing
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
# add empty series
primary := false
seriestype := :scatter
markersize := 0
markeralpha := 0
fillrange := nothing
x := x
y := y
() ()
end end
@deps bar shape @deps bar shape
@ -499,8 +542,8 @@ end
m, n = size(z.surf) m, n = size(z.surf)
x_pts, y_pts = fill(NaN, 6 * m * n), fill(NaN, 6 * m * n) x_pts, y_pts = fill(NaN, 6 * m * n), fill(NaN, 6 * m * n)
fz = zeros(m * n) fz = zeros(m * n)
for i = 1:m # y for i in 1:m # y
for j = 1:n # x for j in 1:n # x
k = (j - 1) * m + i k = (j - 1) * m + i
inds = (6 * (k - 1) + 1):(6 * k - 1) inds = (6 * (k - 1) + 1):(6 * k - 1)
x_pts[inds] .= [xe[j], xe[j + 1], xe[j + 1], xe[j], xe[j]] x_pts[inds] .= [xe[j], xe[j + 1], xe[j + 1], xe[j], xe[j]]
@ -547,7 +590,6 @@ function _scale_adjusted_values(
end end
end end
function _binbarlike_baseline(min_value::T, scale::Symbol) where {T<:Real} function _binbarlike_baseline(min_value::T, scale::Symbol) where {T<:Real}
if (scale in _logScales) if (scale in _logScales)
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3) !isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
@ -556,7 +598,6 @@ function _binbarlike_baseline(min_value::T, scale::Symbol) where {T<:Real}
end end
end end
function _preprocess_binbarlike_weights( function _preprocess_binbarlike_weights(
::Type{T}, ::Type{T},
w, w,
@ -585,12 +626,10 @@ function _preprocess_binlike(plotattributes, x, y)
edge, weights, xscale, yscale, baseline edge, weights, xscale, yscale, baseline
end end
@nospecialize @nospecialize
@recipe function f(::Type{Val{:barbins}}, x, y, z) @recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
_preprocess_binlike(plotattributes, x, y)
if (plotattributes[:bar_width] === nothing) if (plotattributes[:bar_width] === nothing)
bar_width := diff(edge) bar_width := diff(edge)
end end
@ -601,10 +640,8 @@ end
end end
@deps barbins bar @deps barbins bar
@recipe function f(::Type{Val{:scatterbins}}, x, y, z) @recipe function f(::Type{Val{:scatterbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
_preprocess_binlike(plotattributes, x, y)
@series begin @series begin
x := _bin_centers(edge) x := _bin_centers(edge)
xerror := diff(edge) / 2 xerror := diff(edge) / 2
@ -621,13 +658,7 @@ end
@specialize @specialize
function _stepbins_path( function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol)
edge,
weights,
baseline::Real,
xscale::Symbol,
yscale::Symbol,
)
log_scale_x = xscale in _logScales log_scale_x = xscale in _logScales
log_scale_y = yscale in _logScales log_scale_y = yscale in _logScales
@ -689,11 +720,9 @@ end
@recipe function f(::Type{Val{:stepbins}}, x, y, z) @recipe function f(::Type{Val{:stepbins}}, x, y, z)
@nospecialize @nospecialize
axis = axis = plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis]
plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis]
edge, weights, xscale, yscale, baseline = edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
_preprocess_binlike(plotattributes, x, y)
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
if !isvertical(plotattributes) if !isvertical(plotattributes)
@ -745,12 +774,9 @@ function _auto_binning_nbins(
# The nd estimator is the key to most automatic binning methods, and is modified for twodimensional histograms to include correlation # The nd estimator is the key to most automatic binning methods, and is modified for twodimensional histograms to include correlation
nd = n_samples^(1 / (2 + N)) nd = n_samples^(1 / (2 + N))
nd = N == 2 ? nd =
min( N == 2 ?
n_samples^(1 / (2 + N)), min(n_samples^(1 / (2 + N)), nd / (1 - cor(first(vs), last(vs))^2)^(3 // 8)) : nd # the >2-dimensional case does not have a nice solution to correlations
nd / (1 - cor(first(vs), last(vs))^2)^(3 // 8),
) :
nd # the >2-dimensional case does not have a nice solution to correlations
v = vs[dim] v = vs[dim]
@ -769,7 +795,7 @@ function _auto_binning_nbins(
elseif mode == :fd # FreedmanDiaconis rule elseif mode == :fd # FreedmanDiaconis rule
_cl(_span(v) / (2 * _iqr(v) / nd)) _cl(_span(v) / (2 * _iqr(v) / nd))
elseif mode == :wand elseif mode == :wand
_cl(wand_edges(v)) # this makes this function not type stable, but the type instability does not propagate wand_edges(v) # this makes this function not type stable, but the type instability does not propagate
else else
error("Unknown auto-binning mode $mode") error("Unknown auto-binning mode $mode")
end end
@ -779,11 +805,8 @@ _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {
StatsBase.histrange(vs[dim], binning, :left) StatsBase.histrange(vs[dim], binning, :left)
_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} =
_hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning))
_hist_edge( _hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} =
vs::NTuple{N,AbstractVector}, binning
dim::Integer,
binning::AbstractVector,
) where {N} = binning
_hist_edges(vs::NTuple{N,AbstractVector}, binning::NTuple{N,Any}) where {N} = _hist_edges(vs::NTuple{N,AbstractVector}, binning::NTuple{N,Any}) where {N} =
map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...,)) map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...,))
@ -813,8 +836,8 @@ function _make_hist(
edges = _hist_edges(localvs, binning) edges = _hist_edges(localvs, binning)
h = float( h = float(
weights === nothing ? weights === nothing ?
StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) : StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) :
StatsBase.fit( StatsBase.fit(
StatsBase.Histogram, StatsBase.Histogram,
localvs, localvs,
StatsBase.Weights(weights), StatsBase.Weights(weights),
@ -875,7 +898,6 @@ end
end end
@deps scatterhist scatterbins @deps scatterhist scatterbins
@recipe function f(h::StatsBase.Histogram{T,1,E}) where {T,E} @recipe function f(h::StatsBase.Histogram{T,1,E}) where {T,E}
seriestype --> :barbins seriestype --> :barbins
@ -885,8 +907,7 @@ end
:step => :stepbins, :step => :stepbins,
:steppost => :stepbins, # :step can be mapped to :steppost in pre-processing :steppost => :stepbins, # :step can be mapped to :steppost in pre-processing
) )
seriestype := seriestype := get(st_map, plotattributes[:seriestype], plotattributes[:seriestype])
get(st_map, plotattributes[:seriestype], plotattributes[:seriestype])
if plotattributes[:seriestype] == :scatterbins if plotattributes[:seriestype] == :scatterbins
# Workaround, error bars currently not set correctly by scatterbins # Workaround, error bars currently not set correctly by scatterbins
@ -900,7 +921,6 @@ end
end end
end end
@recipe function f(hv::AbstractVector{H}) where {H<:StatsBase.Histogram} @recipe function f(hv::AbstractVector{H}) where {H<:StatsBase.Histogram}
for h in hv for h in hv
@series begin @series begin
@ -909,7 +929,6 @@ end
end end
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Histogram 2D # Histogram 2D
@ -936,7 +955,6 @@ end
end end
Plots.@deps bins2d heatmap Plots.@deps bins2d heatmap
@recipe function f(::Type{Val{:histogram2d}}, x, y, z) @recipe function f(::Type{Val{:histogram2d}}, x, y, z)
h = _make_hist( h = _make_hist(
(x, y), (x, y),
@ -952,13 +970,11 @@ Plots.@deps bins2d heatmap
end end
@deps histogram2d bins2d @deps histogram2d bins2d
@recipe function f(h::StatsBase.Histogram{T,2,E}) where {T,E} @recipe function f(h::StatsBase.Histogram{T,2,E}) where {T,E}
seriestype --> :bins2d seriestype --> :bins2d
(h.edges[1], h.edges[2], Surface(h.weights)) (h.edges[1], h.edges[2], Surface(h.weights))
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# pie # pie
@recipe function f(::Type{Val{:pie}}, x, y, z) @recipe function f(::Type{Val{:pie}}, x, y, z)
@ -980,7 +996,6 @@ end
end end
@deps pie shape @deps pie shape
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# mesh 3d replacement for non-plotly backends # mesh 3d replacement for non-plotly backends
@ -988,12 +1003,15 @@ end
# As long as no i,j,k are supplied this should work with PyPlot and GR # As long as no i,j,k are supplied this should work with PyPlot and GR
seriestype := :surface seriestype := :surface
if plotattributes[:connections] !== nothing if plotattributes[:connections] !== nothing
throw(ArgumentError("Giving triangles using the connections argument is only supported on Plotly backend.")) throw(
ArgumentError(
"Giving triangles using the connections argument is only supported on Plotly backend.",
),
)
end end
() ()
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# scatter 3d # scatter 3d
@ -1011,7 +1029,7 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# lens! - magnify a region of a plot # lens! - magnify a region of a plot
lens!(args...;kwargs...) = plot!(args...; seriestype=:lens, kwargs...) lens!(args...; kwargs...) = plot!(args...; seriestype = :lens, kwargs...)
export lens! export lens!
@recipe function f(::Type{Val{:lens}}, plt::AbstractPlot) @recipe function f(::Type{Val{:lens}}, plt::AbstractPlot)
sp_index, inset_bbox = plotattributes[:inset_subplots] sp_index, inset_bbox = plotattributes[:inset_subplots]
@ -1019,36 +1037,45 @@ export lens!
throw(ArgumentError("Inset bounding box needs to in relative coordinates.")) throw(ArgumentError("Inset bounding box needs to in relative coordinates."))
end end
sp = plt.subplots[sp_index] sp = plt.subplots[sp_index]
xl1, xl2 = xlims(plt.subplots[sp_index]) xscale = sp[:xaxis][:scale]
yscale = sp[:yaxis][:scale]
xl1, xl2 = xlims(sp)
bbx1 = xl1 + left(inset_bbox).value * (xl2 - xl1) bbx1 = xl1 + left(inset_bbox).value * (xl2 - xl1)
bbx2 = bbx1 + width(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) bby1 = yl1 + (1 - bottom(inset_bbox).value) * (yl2 - yl1)
bby2 = bby1 + height(inset_bbox).value * (yl2 - yl1) bby2 = bby1 + height(inset_bbox).value * (yl2 - yl1)
bbx = bbx1 + width(inset_bbox).value * (xl2 - xl1) / 2 bbx = bbx1 + width(inset_bbox).value * (xl2 - xl1) / 2 * (sp[:xaxis][:flip] ? -1 : 1)
bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2 bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2 * (sp[:yaxis][:flip] ? -1 : 1)
lens_index = last(plt.subplots)[:subplot_index] + 1 lens_index = last(plt.subplots)[:subplot_index] + 1
x1, x2 = plotattributes[:x] x1, x2 = RecipesPipeline.inverse_scale_func(xscale).(plotattributes[:x])
y1, y2 = plotattributes[:y] y1, y2 = RecipesPipeline.inverse_scale_func(yscale).(plotattributes[:y])
backup = copy(plotattributes) backup = copy(plotattributes)
empty!(plotattributes) empty!(plotattributes)
series_plotindex := backup[:series_plotindex] series_plotindex := backup[:series_plotindex]
seriestype := :path seriestype := :path
primary := false 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 bbx_mag = (x1 + x2) / 2
bby_mag = (y1 + y2) / 2 bby_mag = (y1 + y2) / 2
xi_lens, yi_lens = intersection_point(bbx_mag, bby_mag, bbx, bby, abs(bby2 - bby1), abs(bbx2 - bbx1)) xi_lens, yi_lens =
xi_mag, yi_mag = intersection_point(bbx, bby, bbx_mag, bby_mag, abs(y2 - y1), abs(x2 - x1)) intersection_point(bbx_mag, bby_mag, bbx, bby, abs(bby2 - bby1), abs(bbx2 - bbx1))
xi_mag, yi_mag =
intersection_point(bbx, bby, bbx_mag, bby_mag, abs(y2 - y1), abs(x2 - x1))
# add lines # add lines
if xl1 < xi_lens < xl2 && if xl1 < xi_lens < xl2 && yl1 < yi_lens < yl2
yl1 < yi_lens < yl2
@series begin @series begin
primary := false primary := false
subplot := sp_index subplot := sp_index
x := [xi_mag, xi_lens] x := RecipesPipeline.scale_func(xscale).([xi_mag, xi_lens])
y := [yi_mag, yi_lens] y := RecipesPipeline.scale_func(yscale).([yi_mag, yi_lens])
() ()
end end
end end
@ -1056,8 +1083,8 @@ export lens!
@series begin @series begin
primary := false primary := false
subplot := sp_index subplot := sp_index
x := [x1, x1, x2, x2, x1] x := RecipesPipeline.scale_func(xscale).([x1, x1, x2, x2, x1])
y := [y1, y2, y2, y1, y1] y := RecipesPipeline.scale_func(yscale).([y1, y2, y2, y1, y1])
() ()
end end
# add subplot # add subplot
@ -1066,8 +1093,8 @@ export lens!
plotattributes = merge(backup, copy(series.plotattributes)) plotattributes = merge(backup, copy(series.plotattributes))
subplot := lens_index subplot := lens_index
primary := false primary := false
xlims := (x1, x2) xlims := RecipesPipeline.scale_func(xscale).((x1, x2))
ylims := (y1, y2) ylims := RecipesPipeline.scale_func(yscale).((y1, y2))
() ()
end end
end end
@ -1088,14 +1115,14 @@ function intersection_point(xA, yA, xB, yB, h, w)
else # left else # left
return xB - hw, yB - s * hw return xB - hw, yB - s * hw
end end
# top or bot? # top or bot?
elseif -hw <= hh/s <= hw elseif -hw <= hh / s <= hw
if yA > yB if yA > yB
# top # top
return xB + hh/s, yB + hh return xB + hh / s, yB + hh
else else
# bottom # bottom
return xB - hh/s, yB - hh return xB - hh / s, yB - hh
end end
end end
end end
@ -1113,6 +1140,13 @@ end
# Error Bars # Error Bars
function error_style!(plotattributes::AKW) function error_style!(plotattributes::AKW)
# errorbar color should soley determined by markerstrokecolor
if haskey(plotattributes, :marker_z)
reset_kw!(plotattributes, :marker_z)
end
if haskey(plotattributes, :line_z)
reset_kw!(plotattributes, :line_z)
end
msc = plotattributes[:markerstrokecolor] msc = plotattributes[:markerstrokecolor]
msc = if msc === :match msc = if msc === :match
plotattributes[:subplot][:foreground_color_subplot] plotattributes[:subplot][:foreground_color_subplot]
@ -1235,15 +1269,15 @@ function quiver_using_arrows(plotattributes::AKW)
if !isa(plotattributes[:arrow], Arrow) if !isa(plotattributes[:arrow], Arrow)
plotattributes[:arrow] = arrow() plotattributes[:arrow] = arrow()
end end
is_3d = haskey(plotattributes,:z) && !isnothing(plotattributes[:z]) is_3d = haskey(plotattributes, :z) && !isnothing(plotattributes[:z])
velocity = error_zipit(plotattributes[:quiver]) velocity = error_zipit(plotattributes[:quiver])
xorig, yorig = plotattributes[:x], plotattributes[:y] xorig, yorig = plotattributes[:x], plotattributes[:y]
zorig = is_3d ? plotattributes[:z] : [] zorig = is_3d ? plotattributes[:z] : []
# for each point, we create an arrow of velocity vi, translated to the x/y coordinates # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
x, y = zeros(0), zeros(0) x, y = zeros(0), zeros(0)
is_3d && ( z = zeros(0)) is_3d && (z = zeros(0))
for i = 1:max(length(xorig), length(yorig), is_3d ? 0 : length(zorig)) for i in 1:max(length(xorig), length(yorig), is_3d ? 0 : length(zorig))
# get the starting position # get the starting position
xi = _cycle(xorig, i) xi = _cycle(xorig, i)
yi = _cycle(yorig, i) yi = _cycle(yorig, i)
@ -1293,7 +1327,7 @@ function quiver_using_hack(plotattributes::AKW)
# for each point, we create an arrow of velocity vi, translated to the x/y coordinates # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
pts = P2[] pts = P2[]
for i = 1:max(length(xorig), length(yorig)) for i in 1:max(length(xorig), length(yorig))
# get the starting position # get the starting position
xi = _cycle(xorig, i) xi = _cycle(xorig, i)
@ -1322,10 +1356,7 @@ function quiver_using_hack(plotattributes::AKW)
U2 *= arrow_w U2 *= arrow_w
ppv = p + v ppv = p + v
nanappend!( nanappend!(pts, P2[p, ppv - U1, ppv - U1 + U2, ppv, ppv - U1 - U2, ppv - U1])
pts,
P2[p, ppv - U1, ppv - U1 + U2, ppv, ppv - U1 - U2, ppv - U1],
)
end end
plotattributes[:x], plotattributes[:y] = RecipesPipeline.unzip(pts[2:end]) plotattributes[:x], plotattributes[:y] = RecipesPipeline.unzip(pts[2:end])
@ -1344,7 +1375,6 @@ end
end end
@deps quiver shape path @deps quiver shape path
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# 1 argument # 1 argument
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -1359,7 +1389,8 @@ function clamp_greys!(mat::AMat{<:Gray})
end end
@recipe function f(mat::AMat{<:Gray}) @recipe function f(mat::AMat{<:Gray})
n, m = axes(mat) n, m = map(a -> range(0.5, stop = a.stop + 0.5), axes(mat))
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
@ -1376,8 +1407,8 @@ end
@nospecialize @nospecialize
# images - colors # images - colors
@recipe function f(mat::AMat{T}) where {T <: Colorant} @recipe function f(mat::AMat{T}) where {T<:Colorant}
n, m = axes(mat) n, m = map(a -> range(0.5, stop = a.stop + 0.5), axes(mat))
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
@ -1400,35 +1431,34 @@ end
coords(shape) coords(shape)
end end
@recipe function f(shapes::AVec{Shape}) @recipe function f(shapes::AVec{<:Shape})
seriestype --> :shape seriestype --> :shape
# For backwards compatibility, column vectors of segmenting attributes are # For backwards compatibility, column vectors of segmenting attributes are
# interpreted as having one element per shape # interpreted as having one element per shape
for attr in union(_segmenting_array_attributes, _segmenting_vector_attributes) for attr in union(_segmenting_array_attributes, _segmenting_vector_attributes)
v = get(plotattributes, attr, nothing) v = get(plotattributes, attr, nothing)
if v isa AVec || v isa AMat && size(v,2) == 1 if v isa AVec || v isa AMat && size(v, 2) == 1
@warn "Column vector attribute `$attr` reinterpreted as row vector (one value per shape).\n" * @warn "Column vector attribute `$attr` reinterpreted as row vector (one value per shape).\n" *
"Pass a row vector instead (e.g. using `permutedims`) to suppress this warning." "Pass a row vector instead (e.g. using `permutedims`) to suppress this warning."
plotattributes[attr] = permutedims(v) plotattributes[attr] = permutedims(v)
end end
end end
coords(shapes) coords(shapes)
end end
@recipe function f(shapes::AMat{Shape}) @recipe function f(shapes::AMat{<:Shape})
seriestype --> :shape seriestype --> :shape
for j in axes(shapes, 2) for j in axes(shapes, 2)
@series coords(vec(shapes[:, j])) @series coords(vec(shapes[:, j]))
end end
end end
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# 3 arguments # 3 arguments
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# images - grays # images - grays
@recipe function f(x::AVec, y::AVec, mat::AMat{T}) where {T <: Gray} @recipe function f(x::AVec, y::AVec, mat::AMat{T}) where {T<:Gray}
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
@ -1443,7 +1473,7 @@ end
end end
# images - colors # images - colors
@recipe function f(x::AVec, y::AVec, mat::AMat{T}) where {T <: Colorant} @recipe function f(x::AVec, y::AVec, mat::AMat{T}) where {T<:Colorant}
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
@ -1464,7 +1494,7 @@ end
@recipe f(p::GeometryBasics.Point) = [p] @recipe f(p::GeometryBasics.Point) = [p]
# Special case for 4-tuples in :ohlc series # Special case for 4-tuples in :ohlc series
@recipe f(xyuv::AVec{<:Tuple{R1, R2, R3, R4}}) where {R1, R2, R3, R4} = @recipe f(xyuv::AVec{<:Tuple{R1,R2,R3,R4}}) where {R1,R2,R3,R4} =
get(plotattributes, :seriestype, :path) == :ohlc ? OHLC[OHLC(t...) for t in xyuv] : get(plotattributes, :seriestype, :path) == :ohlc ? OHLC[OHLC(t...) for t in xyuv] :
RecipesPipeline.unzip(xyuv) RecipesPipeline.unzip(xyuv)
@ -1521,8 +1551,7 @@ end
@recipe f( @recipe f(
x::AVec, x::AVec,
ohlc::AVec{Tuple{R1,R2,R3,R4}}, ohlc::AVec{Tuple{R1,R2,R3,R4}},
) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = ) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = x, OHLC[OHLC(t...) for t in ohlc]
x, OHLC[OHLC(t...) for t in ohlc]
@recipe function f(x::AVec, v::AVec{OHLC}) @recipe function f(x::AVec, v::AVec{OHLC})
seriestype := :path seriestype := :path
@ -1541,7 +1570,6 @@ end
# TODO: everything below here should be either changed to a # TODO: everything below here should be either changed to a
# series recipe or moved to PlotRecipes # series recipe or moved to PlotRecipes
# "Sparsity plot... heatmap of non-zero values of a matrix" # "Sparsity plot... heatmap of non-zero values of a matrix"
# function spy{T<:Real}(z::AMat{T}; kw...) # function spy{T<:Real}(z::AMat{T}; kw...)
# mat = reshape(map(zi->float(zi!=0), z),1,:) # mat = reshape(map(zi->float(zi!=0), z),1,:)
@ -1589,7 +1617,6 @@ end
@specialize @specialize
Plots.findnz(A::AbstractSparseMatrix) = SparseArrays.findnz(A) Plots.findnz(A::AbstractSparseMatrix) = SparseArrays.findnz(A)
# fallback function for finding non-zero elements of non-sparse matrices # fallback function for finding non-zero elements of non-sparse matrices
@ -1605,7 +1632,6 @@ end
@nospecialize @nospecialize
"Adds ax+b... straight line over the current plot, without changing the axis limits"
abline!(plt::Plot, a, b; kw...) = abline!(plt::Plot, a, b; kw...) =
plot!(plt, [0, 1], [b, b + a]; seriestype = :straightline, kw...) plot!(plt, [0, 1], [b, b + a]; seriestype = :straightline, kw...)
@ -1629,7 +1655,6 @@ end
x, real.(y), imag.(y) x, real.(y), imag.(y)
end end
# Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246 # Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246
@userplot PortfolioComposition @userplot PortfolioComposition
@ -1651,16 +1676,6 @@ end
end end
end end
"""
areaplot([x,] y)
areaplot!([x,] y)
Draw a stacked area plot of the matrix y.
# Examples
```julia-repl
julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4])
```
"""
@userplot AreaPlot @userplot AreaPlot
@recipe function f(a::AreaPlot) @recipe function f(a::AreaPlot)

View File

@ -241,7 +241,6 @@ julia> ohlc(y)
""" """
@shorthands ohlc @shorthands ohlc
""" """
contour(x,y,z) contour(x,y,z)
contour!(x,y,z) contour!(x,y,z)
@ -263,7 +262,6 @@ julia> contour(x, y, (x, y) -> x^2 + y^2)
"An alias for `contour` with fill = true." "An alias for `contour` with fill = true."
@shorthands contourf @shorthands contourf
@shorthands contour3d @shorthands contour3d
""" """
@ -350,10 +348,10 @@ Make a box and whisker plot.
# Keyword arguments # Keyword arguments
- `notch`: Bool. Notch the box plot? (false) - `notch`: Bool. Notch the box plot? (false)
- `range`: Real. Values more than range*IQR below the first quartile - `whisker_range`: Real. Whiskers extend `whisker_range`*IQR below the first quartile
or above the third quartile are shown as outliers (1.5) and above the third quartile. Values outside this range are shown as outliers (1.5)
- `outliers`: Bool. Show outliers? (true) - `outliers`: Bool. Show outliers? (true)
- `whisker_width`: Real or Symbol. Length of whiskers (:match) - `whisker_width`: Real or Symbol. Length of whiskers; the options are `:match` to match the box width, `:half`, or a number to indicate the total length. (:half)
# Example # Example
```julia-repl ```julia-repl
@ -408,17 +406,17 @@ julia> curves([1,2,3,4],[1,1,2,4])
@shorthands pie @shorthands pie
"Plot with seriestype :path3d" "Plot with seriestype :path3d"
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
"Add title to an existing plot" "Add title to an existing plot"
title!(s::AbstractString; kw...) = plot!(; title = s, kw...) title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
"Add xlabel to an existing plot" "Add xlabel to an existing plot"
xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...) xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
"Add ylabel to an existing plot" "Add ylabel to an existing plot"
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...) ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
"Set xlims for an existing plot" "Set xlims for an existing plot"
xlims!(lims::Tuple; kw...) = plot!(; xlims = lims, kw...) xlims!(lims::Tuple; kw...) = plot!(; xlims = lims, kw...)
@ -429,21 +427,20 @@ ylims!(lims::Tuple; kw...) = plot!(; ylims = lims, kw...)
"Set zlims for an existing plot" "Set zlims for an existing plot"
zlims!(lims::Tuple; kw...) = plot!(; zlims = lims, kw...) zlims!(lims::Tuple; kw...) = plot!(; zlims = lims, kw...)
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...) xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin, xmax), kw...)
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...) ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin, ymax), kw...)
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...) zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin, zmax), kw...)
"Set xticks for an existing plot" "Set xticks for an existing plot"
xticks!(v::TicksArgs; kw...) = plot!(; xticks = v, kw...) xticks!(v::TicksArgs; kw...) = plot!(; xticks = v, kw...)
"Set yticks for an existing plot" "Set yticks for an existing plot"
yticks!(v::TicksArgs; kw...) = plot!(; yticks = v, kw...) yticks!(v::TicksArgs; kw...) = plot!(; yticks = v, kw...)
xticks!( xticks!(ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} =
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...) plot!(; xticks = (ticks, labels), kw...)
yticks!( yticks!(ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} =
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...) plot!(; yticks = (ticks, labels), kw...)
""" """
annotate!(anns...) annotate!(anns...)
@ -453,30 +450,55 @@ Add annotations to an existing plot.
# Arguments # Arguments
- `anns`: An `AbstractVector` of tuples of the form `(x,y,text)`. The `text` object - `anns`: An `AbstractVector` of tuples of the form `(x,y,text)`. The `text` object
can be a `String` or `PlotText`. can be a `String`, `PlotText` PlotText (created with `text(args...)`),
or a tuple of arguments to `text` (e.g., `("Label", 8, :red, :top)`).
# Example # Example
```julia-repl ```julia-repl
julia> plot(1:10) julia> plot(1:10)
julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))]) julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))])
julia> annotate!([(4, 4, ("More text", 8, 45.0, :bottom, :red))])
``` ```
""" """
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...) annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
annotate!(anns::Tuple...; kw...) = plot!(; annotation = collect(anns), kw...) annotate!(anns::Tuple...; kw...) = plot!(; annotation = collect(anns), kw...)
annotate!(anns::AVec{<:Tuple}; kw...) = plot!(; annotation = anns, kw...) annotate!(anns::AVec{<:Tuple}; kw...) = plot!(; annotation = anns, kw...)
"Flip the current plots' x axis" "Flip the current plots' x axis"
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...) xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
"Flip the current plots' y axis" "Flip the current plots' y axis"
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...) yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
"Specify x axis attributes for an existing plot" "Specify x axis attributes for an existing plot"
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...) xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
"Specify y axis attributes for an existing plot" "Specify y axis attributes for an existing plot"
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...) yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...) ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
@doc """
abline!([plot,] a, b; kwargs...)
Adds ax+b... straight line over the current plot, without changing the axis limits
""" abline!
@doc """
areaplot([x,] y)
areaplot!([x,] y)
Draw a stacked area plot of the matrix y.
# Examples
```julia-repl
julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], fillalpha = [0.2 0.3 0.4])
```
""" areaplot
@doc """
lens!([plot,] x, y, inset = (sp_index, bbox(x1, x2, y1, y2)))
Magnify a region of a plot given by `x` and `y`.
`sp_index` is the index of the subplot and `x1`, `x2`, `y1` and `y2` should be between `0` and `1`.
""" lens!
@specialize @specialize

View File

@ -1,6 +1,5 @@
function Subplot(::T; parent = RootLayout()) where {T<:AbstractBackend}
function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
Subplot{T}( Subplot{T}(
parent, parent,
Series[], Series[],
@ -9,7 +8,7 @@ function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
defaultbox, defaultbox,
DefaultsDict(KW(), _subplot_defaults), DefaultsDict(KW(), _subplot_defaults),
nothing, nothing,
nothing nothing,
) )
end end
@ -21,8 +20,7 @@ Return the bounding box of a subplot
plotarea(sp::Subplot) = sp.plotarea plotarea(sp::Subplot) = sp.plotarea
plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox) plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox)
Base.size(sp::Subplot) = (1, 1)
Base.size(sp::Subplot) = (1,1)
Base.length(sp::Subplot) = 1 Base.length(sp::Subplot) = 1
Base.getindex(sp::Subplot, r::Int, c::Int) = sp Base.getindex(sp::Subplot, r::Int, c::Int) = sp
@ -43,23 +41,23 @@ series_list(sp::Subplot) = sp.series_list # filter(series -> series.plotattribut
function should_add_to_legend(series::Series) function should_add_to_legend(series::Series)
series.plotattributes[:primary] && series.plotattributes[:primary] &&
series.plotattributes[:label] != "" && series.plotattributes[:label] != "" &&
!( !(
series.plotattributes[:seriestype] in ( series.plotattributes[:seriestype] in (
:hexbin, :hexbin,
:bins2d, :bins2d,
:histogram2d, :histogram2d,
:hline, :hline,
:vline, :vline,
:contour, :contour,
:contourf, :contourf,
:contour3d, :contour3d,
:surface, :surface,
:wireframe, :wireframe,
:heatmap, :heatmap,
:image, :image,
)
) )
)
end end
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -34,11 +34,8 @@ end
@userplot ShowTheme @userplot ShowTheme
_color_functions = KW( _color_functions =
:protanopic => protanopic, KW(:protanopic => protanopic, :deuteranopic => deuteranopic, :tritanopic => tritanopic)
:deuteranopic => deuteranopic,
:tritanopic => tritanopic,
)
_get_showtheme_args(thm::Symbol) = thm, identity _get_showtheme_args(thm::Symbol) = thm, identity
_get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func, identity) _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func, identity)
@ -110,8 +107,8 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
subplot := 4 subplot := 4
seriestype := :heatmap seriestype := :heatmap
seriescolor := colorgradient seriescolor := colorgradient
xticks := (-2π:2π:2π, string.(-2:2:2, "π")) xticks := ((-2π):(2π):(2π), string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π")) yticks := ((-2π):(2π):(2π), string.(-2:2:2, "π"))
x, y, z x, y, z
end end
@ -119,8 +116,8 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
subplot := 5 subplot := 5
seriestype := :surface seriestype := :surface
seriescolor := colorgradient seriescolor := colorgradient
xticks := (-2π:2π:2π, string.(-2:2:2, "π")) xticks := ((-2π):(2π):(2π), string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π")) yticks := ((-2π):(2π):(2π), string.(-2:2:2, "π"))
x, y, z x, y, z
end end
@ -137,5 +134,4 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
line_z := z line_z := z
x, y, z x, y, z
end end
end end

View File

@ -6,7 +6,8 @@ const AVec = AbstractVector
const AMat = AbstractMatrix const AMat = AbstractMatrix
const KW = Dict{Symbol,Any} const KW = Dict{Symbol,Any}
const AKW = AbstractDict{Symbol,Any} const AKW = AbstractDict{Symbol,Any}
const TicksArgs = Union{AVec{T}, Tuple{AVec{T}, AVec{S}}, Symbol} where {T<:Real, S<:AbstractString} const TicksArgs =
Union{AVec{T},Tuple{AVec{T},AVec{S}},Symbol} where {T<:Real,S<:AbstractString}
struct PlotsDisplay <: AbstractDisplay end struct PlotsDisplay <: AbstractDisplay end
@ -59,11 +60,10 @@ Extrema() = Extrema(Inf, -Inf)
# ----------------------------------------------------------- # -----------------------------------------------------------
const SubplotMap = Dict{Any, Subplot} const SubplotMap = Dict{Any,Subplot}
# ----------------------------------------------------------- # -----------------------------------------------------------
mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T} mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
backend::T # the backend type backend::T # the backend type
n::Int # number of series n::Int # number of series
@ -78,9 +78,18 @@ mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
end end
function Plot() function Plot()
Plot(backend(), 0, DefaultsDict(KW(), _plot_defaults), Series[], nothing, Plot(
Subplot[], SubplotMap(), EmptyLayout(), backend(),
Subplot[], false) 0,
DefaultsDict(KW(), _plot_defaults),
Series[],
nothing,
Subplot[],
SubplotMap(),
EmptyLayout(),
Subplot[],
false,
)
end end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
@ -89,7 +98,7 @@ Base.getindex(plt::Plot, i::Integer) = plt.subplots[i]
Base.length(plt::Plot) = length(plt.subplots) Base.length(plt::Plot) = length(plt.subplots)
Base.lastindex(plt::Plot) = length(plt) Base.lastindex(plt::Plot) = length(plt)
Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r,c] Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r, c]
Base.size(plt::Plot) = size(plt.layout) Base.size(plt::Plot) = size(plt.layout)
Base.size(plt::Plot, i::Integer) = size(plt.layout)[i] Base.size(plt::Plot, i::Integer) = size(plt.layout)[i]
Base.ndims(plt::Plot) = 2 Base.ndims(plt::Plot) = 2

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,16 @@ import Plots._current_plots_version
# replace `f(args...)` with `f(rng, args...)` for `f ∈ (rand, randn)` # replace `f(args...)` with `f(rng, args...)` for `f ∈ (rand, randn)`
function replace_rand!(ex) end function replace_rand!(ex) end
function replace_rand!(ex::Expr) function replace_rand!(ex::Expr)
for arg in ex.args for arg in ex.args
replace_rand!(arg) replace_rand!(arg)
end end
if ex.head === :call && ex.args[1] (:rand, :randn) if ex.head === :call && ex.args[1] (:rand, :randn, :(Plots.fakedata))
pushfirst!(ex.args, ex.args[1]) pushfirst!(ex.args, ex.args[1])
ex.args[2] = :rng ex.args[2] = :rng
end end
end end
function fix_rand!(ex) function fix_rand!(ex)
replace_rand!(ex) replace_rand!(ex)
pushfirst!(ex.args[1].args, :(rng = StableRNG(1234)))
end end
function image_comparison_tests( function image_comparison_tests(
@ -35,13 +34,17 @@ function image_comparison_tests(
fn = "ref$idx.png" fn = "ref$idx.png"
reffn = reference_file(pkg, idx, _current_plots_version) reffn = reference_file(pkg, idx, _current_plots_version)
newfn = joinpath(reference_path(pkg, _current_plots_version), fn) newfn = joinpath(reference_path(pkg, _current_plots_version), fn)
@debug example.exprs
# test function # test function
func = (fn, idx) -> begin func = (fn, idx) -> begin
expr = Expr(:block) eval(:(rng = StableRNG(PLOTS_SEED)))
append!(expr.args, example.exprs) for the_expr in example.exprs
fix_rand!(expr) expr = Expr(:block)
eval(expr) push!(expr.args, the_expr)
fix_rand!(expr)
eval(expr)
end
png(fn) png(fn)
end end
@ -58,7 +61,7 @@ function image_comparison_facts(
sigma = [1, 1], # number of pixels to "blur" sigma = [1, 1], # number of pixels to "blur"
tol = 1e-2, tol = 1e-2,
) # acceptable error (percent) ) # acceptable error (percent)
for i = 1:length(Plots._examples) for i in 1:length(Plots._examples)
i in skip && continue i in skip && continue
if only === nothing || i in only if only === nothing || i in only
@test image_comparison_tests(pkg, i, debug = debug, sigma = sigma, tol = tol) |> @test image_comparison_tests(pkg, i, debug = debug, sigma = sigma, tol = tol) |>

View File

@ -1,13 +1,13 @@
using Plots, Test, Dates using Plots, Test, Dates
@testset "Limits" begin @testset "Limits" begin
y=[1.0*i*i for i in 1:10] y = [1.0 * i * i for i in 1:10]
x=[Date(2019,11,i) for i in 1:10] x = [Date(2019, 11, i) for i in 1:10]
rx=[x[3],x[5]] rx = [x[3], x[5]]
p = plot(x,y, widen = false) p = plot(x, y, widen = false)
vspan!(p, rx, label="", alpha=0.2) vspan!(p, rx, label = "", alpha = 0.2)
ref_ylims = (y[1], y[end]) ref_ylims = (y[1], y[end])
ref_xlims = (x[1].instant.periods.value, x[end].instant.periods.value) ref_xlims = (x[1].instant.periods.value, x[end].instant.periods.value)
@ -23,13 +23,13 @@ using Plots, Test, Dates
end # testset end # testset
@testset "Date xlims" begin @testset "Date xlims" begin
y=[1.0*i*i for i in 1:10] y = [1.0 * i * i for i in 1:10]
x=[Date(2019,11,i) for i in 1:10] x = [Date(2019, 11, i) for i in 1:10]
span = (Date(2019,10,31), Date(2019,11,11)) span = (Date(2019, 10, 31), Date(2019, 11, 11))
ref_xlims = map(date->date.instant.periods.value, span) ref_xlims = map(date -> date.instant.periods.value, span)
p = plot(x,y, xlims=span, widen = false) p = plot(x, y, xlims = span, widen = false)
@test Plots.xlims(p) == ref_xlims @test Plots.xlims(p) == ref_xlims
#@static if (haskey(ENV, "APPVEYOR") || haskey(ENV, "CI")) #@static if (haskey(ENV, "APPVEYOR") || haskey(ENV, "CI"))
@ -42,13 +42,13 @@ end # testset
end # testset end # testset
@testset "DateTime xlims" begin @testset "DateTime xlims" begin
y=[1.0*i*i for i in 1:10] y = [1.0 * i * i for i in 1:10]
x=[DateTime(2019,11,i,11) for i in 1:10] x = [DateTime(2019, 11, i, 11) for i in 1:10]
span = (DateTime(2019,10,31,11,59,59), DateTime(2019,11,11,12,01,15)) span = (DateTime(2019, 10, 31, 11, 59, 59), DateTime(2019, 11, 11, 12, 01, 15))
ref_xlims = map(date->date.instant.periods.value, span) ref_xlims = map(date -> date.instant.periods.value, span)
p = plot(x,y, xlims=span, widen = false) p = plot(x, y, xlims = span, widen = false)
@test Plots.xlims(p) == ref_xlims @test Plots.xlims(p) == ref_xlims
#@static if (haskey(ENV, "APPVEYOR") || haskey(ENV, "CI")) #@static if (haskey(ENV, "APPVEYOR") || haskey(ENV, "CI"))
@static if haskey(ENV, "APPVEYOR") @static if haskey(ENV, "APPVEYOR")

View File

@ -1,50 +1,341 @@
import ImageMagick using Plots: guidefont, series_annotations, PLOTS_SEED
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 VisualRegressionTests
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(
String(read(joinpath(dirname(pathof(Plots)), "..", ".zenodo.json"))),
)
end
@testset "Plotly standalone" begin @testset "Plotly standalone" begin
@test_nowarn Plots._init_ijulia_plotting() @test_nowarn Plots._init_ijulia_plotting()
@test Plots.plotly_local_file_path[] === nothing @test Plots.plotly_local_file_path[] === nothing
temp = Plots.use_local_dependencies[] temp = Plots.use_local_dependencies[]
withenv("PLOTS_HOST_DEPENDENCY_LOCAL" => true) do withenv("PLOTS_HOST_DEPENDENCY_LOCAL" => true) do
Plots.__init__() Plots.__init__()
@test Plots.plotly_local_file_path[] isa String @test Plots.plotly_local_file_path[] isa String
@test isfile(Plots.plotly_local_file_path[]) @test isfile(Plots.plotly_local_file_path[])
@test Plots.use_local_dependencies[] = true @test Plots.use_local_dependencies[] = true
@test_nowarn Plots._init_ijulia_plotting() @test_nowarn Plots._init_ijulia_plotting()
end end
Plots.plotly_local_file_path[] = nothing Plots.plotly_local_file_path[] = nothing
Plots.use_local_dependencies[] = temp Plots.use_local_dependencies[] = temp
end # testset end
include("test_defaults.jl") @testset "Utils" begin
include("test_axes.jl") zipped = (
include("test_axis_letter.jl") [(1, 2)],
include("test_components.jl") [("a", "b")],
include("test_shorthands.jl") [(1, "a"), (2, "b")],
include("integration_dates.jl") [(1, 2), (3, 4)],
include("test_recipes.jl") [(1, 2, 3), (3, 4, 5)],
include("test_hdf5plots.jl") [(1, 2, 3, 4), (3, 4, 5, 6)],
include("test_pgfplotsx.jl") [(1, 2.0), (missing, missing)],
[(1, missing), (missing, "a")],
[(missing, missing)],
[(missing, missing, missing), ("a", "b", "c")],
)
for z in zipped
@test isequal(collect(zip(Plots.RecipesPipeline.unzip(z)...)), z)
@test isequal(
collect(zip(Plots.RecipesPipeline.unzip(GeometryBasics.Point.(z))...)),
z,
)
end
op1 = Plots.process_clims((1.0, 2.0))
op2 = Plots.process_clims((1, 2.0))
data = randn(100, 100)
@test op1(data) == op2(data)
@test Plots.process_clims(nothing) ==
Plots.process_clims(missing) ==
Plots.process_clims(:auto)
reference_dir(args...) = joinpath(homedir(), ".julia", "dev", "PlotReferenceImages", args...) @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)²",
)
@test Plots.isvector([1, 2])
@test !Plots.isvector(nothing)
@test Plots.ismatrix([1 2; 3 4])
@test !Plots.ismatrix(nothing)
@test Plots.isscalar(1.0)
@test !Plots.isscalar(nothing)
@test Plots.tovec([]) isa AbstractVector
@test Plots.tovec(nothing) isa AbstractVector
@test Plots.anynan(1, 3, (1, NaN, 3))
@test Plots.allnan(1, 2, (NaN, NaN, 1))
@test Plots.makevec([]) isa AbstractVector
@test Plots.makevec(1) isa AbstractVector
@test Plots.maketuple(1) == (1, 1)
@test Plots.maketuple((1, 1)) == (1, 1)
@test Plots.ok(1, 2)
@test !Plots.ok(1, 2, NaN)
@test Plots.ok((1, 2, 3))
@test !Plots.ok((1, 2, NaN))
@test Plots.nansplit([1, 2, NaN, 3, 4]) == [[1.0, 2.0], [3.0, 4.0]]
@test Plots.nanvcat([1, NaN]) |> length == 4
@test Plots.nop() === nothing
@test_throws ErrorException Plots.notimpl()
@test Plots.inch2px(1) isa AbstractFloat
@test Plots.px2inch(1) isa AbstractFloat
@test Plots.inch2mm(1) isa AbstractFloat
@test Plots.mm2inch(1) isa AbstractFloat
@test Plots.px2mm(1) isa AbstractFloat
@test Plots.mm2px(1) isa AbstractFloat
p = plot()
@test xlims() isa Tuple
@test ylims() isa Tuple
@test zlims() isa Tuple
Plots.makekw(foo = 1, bar = 2) isa Dict
@test_throws ErrorException Plots.inline()
@test_throws ErrorException Plots._do_plot_show(plot(), :inline)
@test_throws ErrorException Plots.dumpcallstack()
Plots.debugplots(true)
Plots.debugplots(false)
Plots.debugshow(devnull, nothing)
Plots.debugshow(devnull, [1])
p = plot(1)
push!(p, 1.5)
push!(p, 1, 1.5)
# append!(p, [1., 2.])
append!(p, 1, 2.5, 2.5)
push!(p, (1.5, 2.5))
push!(p, 1, (1.5, 2.5))
append!(p, (1.5, 2.5))
append!(p, 1, (1.5, 2.5))
p = plot([1, 2, 3], [4, 5, 6])
@test Plots.xmin(p) == 1
@test Plots.xmax(p) == 3
@test Plots.ignorenan_extrema(p) == (1, 3)
@test Plots.get_attr_symbol(:x, "lims") == :xlims
@test Plots.get_attr_symbol(:x, :lims) == :xlims
@testset "NaN-separated Segments" begin
segments(args...) = collect(iter_segments(args...))
nan10 = fill(NaN, 10)
@test segments(11:20) == [1:10]
@test segments([NaN]) == []
@test segments(nan10) == []
@test segments([nan10; 1:5]) == [11:15]
@test segments([1:5; nan10]) == [1:5]
@test segments([nan10; 1:5; nan10; 1:5; nan10]) == [11:15, 26:30]
@test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10]
@test segments([nan10; 1:15], [1:15; nan10]) == [11:15]
end
end
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@test typeof(axis) == Plots.Axis
@test Plots.discrete_value!(axis, "HI") == (0.5, 1)
@test Plots.discrete_value!(axis, :yo) == (1.5, 2)
@test Plots.ignorenan_extrema(axis) == (0.5, 1.5)
@test axis[:discrete_map] == Dict{Any,Any}(:yo => 2, "HI" => 1)
Plots.discrete_value!(axis, ["x$i" for i in 1:5])
Plots.discrete_value!(axis, ["x$i" for i in 0:2])
@test Plots.ignorenan_extrema(axis) == (0.5, 7.5)
end
@testset "NoFail" begin
# ensure backend with tested display
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
dsp = TextDisplay(IOContext(IOBuffer(), :color => true))
@testset "plot" begin
for plt in [
histogram([1, 0, 0, 0, 0, 0]),
plot([missing]),
plot([missing, missing]),
plot(fill(missing, 10)),
plot([missing; 1:4]),
plot([fill(missing, 10); 1:4]),
plot([1 1; 1 missing]),
plot(["a" "b"; missing "d"], [1 2; 3 4]),
]
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 p isa Plots.Plot
@test display(dsp, p) isa Nothing
end
@testset "gui" begin
open(tempname(), "w") do io
redirect_stdout(io) do
gui(plot())
end
end
end
end
@testset "Coverage" begin
@testset "themes" begin
p = showtheme(:dark)
@test p isa Plots.Plot
end
@testset "plotattr" begin
tmp = tempname()
open(tmp, "w") do io
redirect_stdout(io) do
plotattr("seriestype")
plotattr(:Plot)
plotattr()
end
end
str = join(readlines(tmp), "")
@test occursin("seriestype", str)
@test occursin("Plot attributes", str)
end
@testset "legend" begin
@test isa(
Plots.legend_pos_from_angle(20, 0.0, 0.5, 1.0, 0.0, 0.5, 1.0),
NTuple{2,<:AbstractFloat},
)
@test Plots.legend_anchor_index(-1) == 1
@test Plots.legend_anchor_index(+0) == 2
@test Plots.legend_anchor_index(+1) == 3
@test Plots.legend_angle(:foo_bar) == (45, :inner)
@test Plots.legend_angle(20.0) ==
Plots.legend_angle((20.0, :inner)) ==
(20.0, :inner)
@test Plots.legend_angle((20.0, 10.0)) == (20.0, 10.0)
end
end
@testset "Output" begin
@test Plots.defaultOutputFormat(plot()) == "png"
@test Plots.addExtension("foo", "bar") == "foo.bar"
fn = tempname()
gr()
let p = plot()
Plots.png(p, fn)
Plots.png(fn)
savefig(p, "$fn.png")
savefig("$fn.png")
Plots.pdf(p, fn)
Plots.pdf(fn)
savefig(p, "$fn.pdf")
savefig("$fn.pdf")
Plots.ps(p, fn)
Plots.ps(fn)
savefig(p, "$fn.ps")
savefig("$fn.ps")
Plots.svg(p, fn)
Plots.svg(fn)
savefig(p, "$fn.svg")
savefig("$fn.svg")
end
if Sys.islinux()
pgfplotsx()
let p = plot()
Plots.tex(p, fn)
Plots.tex(fn)
savefig(p, "$fn.tex")
savefig("$fn.tex")
end
end
unicodeplots()
let p = plot()
Plots.txt(p, fn)
Plots.txt(fn)
savefig(p, "$fn.txt")
savefig("$fn.txt")
end
plotlyjs()
let p = plot()
Plots.html(p, fn)
Plots.html(fn)
savefig(p, "$fn.html")
savefig("$fn.html")
if Sys.islinux()
Plots.eps(p, fn)
Plots.eps(fn)
savefig(p, "$fn.eps")
savefig("$fn.eps")
end
end
@test_throws ErrorException savefig("$fn.foo")
end
gr() # reset to default backend
for fn in (
"test_args.jl",
"test_defaults.jl",
"test_pipeline.jl",
"test_axes.jl",
"test_layouts.jl",
"test_contours.jl",
"test_axis_letter.jl",
"test_components.jl",
"test_shorthands.jl",
"integration_dates.jl",
"test_recipes.jl",
"test_hdf5plots.jl",
"test_pgfplotsx.jl",
"test_plotly.jl",
"test_animations.jl",
)
@testset "$fn" begin
include(fn)
end
end
reference_dir(args...) =
joinpath(homedir(), ".julia", "dev", "PlotReferenceImages", args...)
function reference_file(backend, i, version) function reference_file(backend, i, version)
refdir = reference_dir("Plots", string(backend)) refdir = reference_dir("Plots", string(backend))
fn = "ref$i.png" fn = "ref$i.png"
versions = sort(VersionNumber.(readdir(refdir)), rev=true) versions = sort(VersionNumber.(readdir(refdir)), rev = true)
reffn = joinpath(refdir, string(version), fn) reffn = joinpath(refdir, string(version), fn)
for v in versions for v in versions
tmpfn = joinpath(refdir, string(v), fn) tmpfn = joinpath(refdir, string(v), fn)
@ -53,7 +344,6 @@ function reference_file(backend, i, version)
break break
end end
end end
return reffn return reffn
end end
@ -61,42 +351,109 @@ reference_path(backend, version) = reference_dir("Plots", string(backend), strin
if !isdir(reference_dir()) if !isdir(reference_dir())
mkpath(reference_dir()) mkpath(reference_dir())
LibGit2.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git", reference_dir()) LibGit2.clone(
"https://github.com/JuliaPlots/PlotReferenceImages.jl.git",
reference_dir(),
)
end end
include("imgcomp.jl") include("imgcomp.jl")
# don't actually show the plots Random.seed!(PLOTS_SEED)
Random.seed!(1234)
default(show=false, reuse=true) default(show = false, reuse = true) # don't actually show the plots
is_ci() = get(ENV, "CI", "false") == "true" is_ci() = get(ENV, "CI", "false") == "true"
const IMG_TOL = VERSION < v"1.4" && Sys.iswindows() ? 1e-1 : is_ci() ? 1e-2 : 1e-3 const PLOTS_IMG_TOL = parse(
Float64,
get(ENV, "PLOTS_IMG_TOL", is_ci() ? Sys.iswindows() ? "2e-4" : "1e-4" : "1e-5"),
)
## Uncomment the following lines to update reference images for different backends ## Uncomment the following lines to update reference images for different backends
# @testset "GR" begin # @testset "GR" begin
# image_comparison_facts(:gr, tol=IMG_TOL, skip = Plots._backend_skips[:gr]) # image_comparison_facts(:gr, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:gr])
# end # end
# #
# plotly() # plotly()
# @testset "Plotly" begin # @testset "Plotly" begin
# image_comparison_facts(:plotly, tol=IMG_TOL, skip = Plots._backend_skips[:plotlyjs]) # image_comparison_facts(:plotly, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:plotlyjs])
# end # end
# #
# pyplot() # pyplot()
# @testset "PyPlot" begin # @testset "PyPlot" begin
# image_comparison_facts(:pyplot, tol=IMG_TOL, skip = Plots._backend_skips[:pyplot]) # image_comparison_facts(:pyplot, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:pyplot])
# end # end
# #
# pgfplotsx() # pgfplotsx()
# @testset "PGFPlotsX" begin # @testset "PGFPlotsX" begin
# image_comparison_facts(:pgfplotsx, tol=IMG_TOL, skip = Plots._backend_skips[:pgfplotsx]) # image_comparison_facts(:pgfplotsx, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:pgfplotsx])
# end # end
# 10 Histogram2D
## ##
@testset "Examples" begin
if Sys.islinux()
backends = (
:unicodeplots,
:pgfplotsx,
:inspectdr,
:plotlyjs,
:gaston,
# :pyplot, # FIXME: fails with system matplotlib
)
only = setdiff(
1:length(Plots._examples),
(Plots._backend_skips[be] for be in backends)...,
)
for be in backends
@info be
for (i, p) in Plots.test_examples(be, only = only, disp = false)
fn = tempname() * ".png"
png(p, fn)
@test filesize(fn) > 1_000
end
end
end
end
@testset "Backends" begin @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
p = plot((plot(i) for i in 1:4)..., layout = (2, 2))
@test p isa Plots.Plot
@test show(io, p) isa Nothing
end
@testset "GR" begin @testset "GR" begin
ENV["PLOTS_TEST"] = "true" ENV["PLOTS_TEST"] = "true"
@ -107,122 +464,20 @@ const IMG_TOL = VERSION < v"1.4" && Sys.iswindows() ? 1e-1 : is_ci() ? 1e-2 : 1e
@static if haskey(ENV, "APPVEYOR") @static if haskey(ENV, "APPVEYOR")
@info "Skipping GR image comparison tests on AppVeyor" @info "Skipping GR image comparison tests on AppVeyor"
else else
image_comparison_facts(:gr, tol=IMG_TOL, skip=Plots._backend_skips[:gr]) image_comparison_facts(
:gr,
tol = PLOTS_IMG_TOL,
skip = Plots._backend_skips[:gr],
)
end end
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 @testset "PlotlyJS" begin
@test plotlyjs() == Plots.PlotlyJSBackend() @test plotlyjs() == Plots.PlotlyJSBackend()
@test backend() == Plots.PlotlyJSBackend() @test backend() == Plots.PlotlyJSBackend()
p = plot(rand(10)) p = plot(rand(10))
@test isa(p, Plots.Plot) == true @test p isa Plots.Plot
@test_broken isa(display(p), Nothing) == true @test_broken display(p) isa Nothing
end
end
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@test typeof(axis) == Plots.Axis
@test Plots.discrete_value!(axis, "HI") == (0.5, 1)
@test Plots.discrete_value!(axis, :yo) == (1.5, 2)
@test Plots.ignorenan_extrema(axis) == (0.5, 1.5)
@test axis[:discrete_map] == Dict{Any,Any}(:yo => 2, "HI" => 1)
Plots.discrete_value!(axis, ["x$i" for i = 1:5])
Plots.discrete_value!(axis, ["x$i" for i = 0:2])
@test Plots.ignorenan_extrema(axis) == (0.5, 7.5)
end
@testset "NoFail" begin
#ensure backend with tested display
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
@testset "Plot" begin
plots = [histogram([1, 0, 0, 0, 0, 0]),
plot([missing]),
plot([missing; 1:4]),
plot([fill(missing, 10); 1:4]),
plot([1 1; 1 missing]),
plot(["a" "b"; missing "d"], [1 2; 3 4])]
for plt in plots
display(plt)
end
@test_nowarn plot(x -> x^2, 0, 2)
end
@testset "Bar" begin
p = bar([3,2,1], [1,2,3]);
@test isa(p, Plots.Plot)
@test isa(display(p), Nothing) == true
end end
end end
@testset "EmptyAnim" begin
anim = @animate for i in []
end
@test_throws ArgumentError gif(anim)
end
@testset "NaN-separated Segments" begin
segments(args...) = collect(iter_segments(args...))
nan10 = fill(NaN, 10)
@test segments(11:20) == [1:10]
@test segments([NaN]) == []
@test segments(nan10) == []
@test segments([nan10; 1:5]) == [11:15]
@test segments([1:5;nan10]) == [1:5]
@test segments([nan10; 1:5; nan10; 1:5; nan10]) == [11:15, 26:30]
@test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10]
@test segments([nan10; 1:15], [1:15; nan10]) == [11:15]
end
@testset "Utils" begin
zipped = ([(1, 2)], [("a", "b")], [(1, "a"),(2, "b")],
[(1, 2),(3, 4)], [(1, 2, 3),(3, 4, 5)], [(1, 2, 3, 4),(3, 4, 5, 6)],
[(1, 2.0),(missing, missing)], [(1, missing),(missing, "a")],
[(missing, missing)], [(missing, missing, missing),("a", "b", "c")])
for z in zipped
@test isequal(collect(zip(Plots.unzip(z)...)), z)
@test isequal(collect(zip(Plots.unzip(GeometryBasics.Point.(z))...)), z)
end
op1 = Plots.process_clims((1.0, 2.0))
op2 = Plots.process_clims((1, 2.0))
data = randn(100, 100)
@test op1(data) == op2(data)
@test Plots.process_clims(nothing) == Plots.process_clims(missing) == Plots.process_clims(:auto)
end

61
test/test_animations.jl Normal file
View File

@ -0,0 +1,61 @@
@testset "Empty anim" begin
anim = @animate for i in []
end
@test_throws ArgumentError gif(anim)
end
@userplot CirclePlot
@recipe function f(cp::CirclePlot)
x, y, i = cp.args
n = length(x)
inds = circshift(1:n, 1 - i)
linewidth --> range(0, 10, length = n)
seriesalpha --> range(0, 1, length = n)
aspect_ratio --> 1
label --> false
x[inds], y[inds]
end
@testset "Circle plot" begin
n = 10
t = range(0, 2π, length = n)
x = sin.(t)
y = cos.(t)
anim = @animate for i in 1:n
circleplot(x, y, i)
end
@test filesize(gif(anim).filename) > 10_000
@test filesize(mov(anim).filename) > 10_000
@test filesize(mp4(anim).filename) > 10_000
@test filesize(webm(anim).filename) > 10_000
@gif for i in 1:n
circleplot(x, y, i, line_z = 1:n, cbar = false, framestyle = :zerolines)
end every 5
end
@testset "html" begin
p = plot([sin, cos], zeros(0), leg = false, xlims = (0, 2π), ylims = (-1, 1))
anim = Animation()
for x in range(0, stop = 2π, length = 10)
push!(p, x, Float64[sin(x), cos(x)])
frame(anim)
end
agif = gif(anim)
html = tempname() * ".html"
open(html, "w") do io
show(io, MIME("text/html"), agif)
end
@test filesize(html) > 10_000
@test showable(MIME("image/gif"), agif)
agif = mp4(anim)
html = tempname() * ".html"
open(html, "w") do io
show(io, MIME("text/html"), agif)
end
@test filesize(html) > 10_000
end

27
test/test_args.jl Normal file
View File

@ -0,0 +1,27 @@
using Plots, Test
@testset "Series Attributes" begin
pl = plot([[1, 2, 3], [2, 3, 4]], lw = 5)
@test hline!(deepcopy(pl), [1.75])[1].series_list[3][:label] ==
hline!(deepcopy(pl), [1.75], z_order = :front)[1].series_list[3][:label] ==
"y3"
@test hline!(deepcopy(pl), [1.75], z_order = :back)[1].series_list[1][:label] == "y3"
@test hline!(deepcopy(pl), [1.75], z_order = 2)[1].series_list[2][:label] == "y3"
end
@testset "Axis Attributes" begin
pl = @test_nowarn plot(; tickfont = font(10, "Times"))
for axis in (:xaxis, :yaxis, :zaxis)
@test pl[1][axis][:tickfontsize] == 10
@test pl[1][axis][:tickfontfamily] == "Times"
end
end
@testset "Permute recipes" begin
pl = bar(["a", "b", "c"], [1, 2, 3])
ppl = bar(["a", "b", "c"], [1, 2, 3], permute = (:x, :y))
@test xticks(ppl) == yticks(pl)
@test yticks(ppl) == xticks(pl)
@test filter(isfinite, pl[1][1][:x]) == filter(isfinite, ppl[1][1][:y])
@test filter(isfinite, pl[1][1][:y]) == filter(isfinite, ppl[1][1][:x])
end

View File

@ -9,8 +9,8 @@ using Plots, Test
end end
@testset "Magic axis" begin @testset "Magic axis" begin
@test plot(1, axis=nothing)[1][:xaxis][:ticks] == [] @test plot(1, axis = nothing)[1][:xaxis][:ticks] == []
@test plot(1, axis=nothing)[1][:yaxis][:ticks] == [] @test plot(1, axis = nothing)[1][:yaxis][:ticks] == []
end # testset end # testset
@testset "Categorical ticks" begin @testset "Categorical ticks" begin
@ -21,3 +21,102 @@ end # testset
@test Plots.get_ticks(p2[1], p2[1][:xaxis])[2] == string.('C':3:'Z') @test Plots.get_ticks(p2[1], p2[1][:xaxis])[2] == string.('C':3:'Z')
@test Plots.get_ticks(p3[1], p3[1][:xaxis])[2] == string.('A':'Z') @test Plots.get_ticks(p3[1], p3[1][:xaxis])[2] == string.('A':'Z')
end end
@testset "Ticks getter functions" begin
ticks1 = ([1, 2, 3], ("a", "b", "c"))
ticks2 = ([4, 5], ("e", "f"))
p1 = plot(1:5, 1:5, 1:5, xticks = ticks1, yticks = ticks1, zticks = ticks1)
p2 = plot(1:5, 1:5, 1:5, xticks = ticks2, yticks = ticks2, zticks = ticks2)
p = plot(p1, p2)
@test xticks(p) == yticks(p) == zticks(p) == [ticks1, ticks2]
@test xticks(p[1]) == yticks(p[1]) == zticks(p[1]) == ticks1
end
@testset "Axis limits" begin
pl = plot(1:5, xlims = :symmetric, widen = false)
@test Plots.xlims(pl) == (-5, 5)
pl = plot(1:3)
@test Plots.xlims(pl) == Plots.widen(1, 3)
pl = plot([1.05, 2.0, 2.95], ylims = :round)
@test Plots.ylims(pl) == (1, 3)
pl = plot(1:3, xlims = (1, 5))
@test Plots.xlims(pl) == (1, 5)
pl = plot(1:3, xlims = (1, 5), widen = true)
@test Plots.xlims(pl) == Plots.widen(1, 5)
end
@testset "3D Axis" begin
ql = quiver([1, 2], [2, 1], [3, 4], quiver = ([1, -1], [0, 0], [1, -0.5]), arrow = true)
@test ql[1][:projection] == "3d"
end
@testset "twinx" begin
pl = plot(1:10, margin = 2Plots.cm)
twpl = twinx(pl)
pl! = plot!(twinx(), -(1:10))
@test twpl[:right_margin] == 2Plots.cm
@test twpl[:left_margin] == 2Plots.cm
@test twpl[:top_margin] == 2Plots.cm
@test twpl[:bottom_margin] == 2Plots.cm
end
@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))
@test xlims(p) === (0, 3)
p = plot(1:2, xtick = [1.25, 1.5, 1.75])
@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α = 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.0, 0.0, 1.0)
p = plot(1:2, xminorgridcolor = :red)
@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

View File

@ -9,12 +9,15 @@ using Plots, Test
value(m::MyType) = m.val value(m::MyType) = m.val
data = MyType.(sort(randn(20))) data = MyType.(sort(randn(20)))
# A recipe that puts the axis letter in the title # A recipe that puts the axis letter in the title
@recipe function f(::Type{T}, m::T) where T <: AbstractArray{<:MyType} @recipe function f(::Type{T}, m::T) where {T<:AbstractArray{<:MyType}}
title --> string(plotattributes[:letter]) title --> string(plotattributes[:letter])
value.(m) value.(m)
end end
@testset "$f (orientation = $o)" for f in [histogram, barhist, stephist, scatterhist], o in [:vertical, :horizontal] @testset "$f (orientation = $o)" for f in [histogram, barhist, stephist, scatterhist],
@test f(data, orientation=o).subplots[1].attr[:title] == (o == :vertical ? "x" : "y") o in [:vertical, :horizontal]
@test f(data, orientation = o).subplots[1].attr[:title] ==
(o == :vertical ? "x" : "y")
end end
@testset "$f" for f in [hline, hspan] @testset "$f" for f in [hline, hspan]
@test f(data).subplots[1].attr[:title] == "y" @test f(data).subplots[1].attr[:title] == "y"

View File

@ -1,52 +1,90 @@
using Plots, Test using Plots, Test
@testset "Shapes" begin @testset "Shapes" begin
@testset "Type" begin
square = Shape([(0, 0.0), (1, 0.0), (1, 1.0), (0, 1.0)])
@test Plots.get_xs(square) == [0, 1, 1, 0]
@test Plots.get_ys(square) == [0, 0, 1, 1]
@test Plots.vertices(square) == [(0, 0), (1, 0), (1, 1), (0, 1)]
@test isa(square, Shape{Int64,Float64})
@test coords(square) isa Tuple{Vector{S},Vector{T}} where {T,S}
end
@testset "Copy" begin @testset "Copy" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)]) square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
square2 = Shape(square) square2 = Shape(square)
@test square2.x == square.x @test square2.x == square.x
@test square2.y == square.y @test square2.y == square.y
end end
@testset "Center" begin @testset "Center" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)]) square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
@test Plots.center(square) == (0.5,0.5) @test Plots.center(square) == (0.5, 0.5)
end end
@testset "Translate" begin @testset "Translate" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)]) square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
squareUp = Shape([(0,1),(1,1),(1,2),(0,2)]) squareUp = Shape([(0, 1), (1, 1), (1, 2), (0, 2)])
squareUpRight = Shape([(1,1),(2,1),(2,2),(1,2)]) squareUpRight = Shape([(1, 1), (2, 1), (2, 2), (1, 2)])
@test Plots.translate(square,0,1).x == squareUp.x @test Plots.translate(square, 0, 1).x == squareUp.x
@test Plots.translate(square,0,1).y == squareUp.y @test Plots.translate(square, 0, 1).y == squareUp.y
@test Plots.center(translate!(square,1)) == (1.5,1.5) @test Plots.center(translate!(square, 1)) == (1.5, 1.5)
end end
@testset "Rotate" begin @testset "Rotate" begin
# 2 radians rotation matrix # 2 radians rotation matrix
R2 = [cos(2) sin(2); -sin(2) cos(2)] R2 = [cos(2) sin(2); -sin(2) cos(2)]
coords = [0 0; 1 0; 1 1; 0 1]' coords = [0 0; 1 0; 1 1; 0 1]'
coordsRotated2 = R2*(coords.-0.5).+0.5 coordsRotated2 = R2 * (coords .- 0.5) .+ 0.5
square = Shape([(0,0),(1,0),(1,1),(0,1)]) square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
# make a new, rotated square # make a new, rotated square
square2 = Plots.rotate(square, -2) square2 = Plots.rotate(square, -2)
@test square2.x coordsRotated2[1,:] @test square2.x coordsRotated2[1, :]
@test square2.y coordsRotated2[2,:] @test square2.y coordsRotated2[2, :]
# unrotate the new square in place # unrotate the new square in place
rotate!(square2, 2) rotate!(square2, 2)
@test square2.x coords[1,:] @test square2.x coords[1, :]
@test square2.y coords[2,:] @test square2.y coords[2, :]
end
@testset "Plot" begin
ang = range(0, 2π, length = 60)
ellipse(x, y, w, h) = Shape(w * sin.(ang) .+ x, h * cos.(ang) .+ y)
myshapes = [ellipse(x, rand(), rand(), rand()) for x in 1:4]
@test coords(myshapes) isa Tuple{Vector{Vector{S}},Vector{Vector{T}}} where {T,S}
local p
@test_nowarn p = plot(myshapes)
@test p[1][1][:seriestype] == :shape
end
@testset "Misc" begin
@test Plots.weave([1, 3], [2, 4]) == collect(1:4)
@test Plots.makeshape(3) isa Plots.Shape
@test Plots.makestar(3) isa Plots.Shape
@test Plots.makecross() isa Plots.Shape
@test Plots.makearrowhead(10.0) isa Plots.Shape
@test Plots.rotate(1.0, 2.0, 5.0, (0, 0)) isa Tuple
star = Plots.makestar(3)
star_scaled = Plots.scale(star, 0.5)
Plots.scale!(star, 0.5)
@test Plots.get_xs(star) == Plots.get_xs(star_scaled)
@test Plots.get_ys(star) == Plots.get_ys(star_scaled)
@test Plots.extrema_plus_buffer([1, 2], 0.1) == (0.9, 2.1)
end end
end end
@testset "Brush" begin @testset "Brush" begin
@testset "Colors" begin @testset "Colors" begin
baseline = brush(1, RGB(0,0,0)) baseline = brush(1, RGB(0, 0, 0))
@test brush(:black) == baseline @test brush(:black) == baseline
@test brush("black") == baseline @test brush("black") == baseline
end end
@ -60,52 +98,124 @@ end
end end
@testset "Bad Argument" begin @testset "Bad Argument" begin
# using test_logs because test_warn seems to not work anymore # using test_logs because test_warn seems to not work anymore
@test_logs (:warn,"Unused brush arg: nothing (Nothing)") begin @test_logs (:warn, "Unused brush arg: nothing (Nothing)") begin
brush(nothing) brush(nothing)
end end
end end
end end
@testset "Text" begin
t = Plots.PlotText("foo")
f = Plots.font()
@test Plots.PlotText(nothing).str == "nothing"
@test length(t) == 3
@test text(t).str == "foo"
@test text(t, f).str == "foo"
@test text("bar", f).str == "bar"
@test text(true).str == "true"
end
@testset "Annotations" begin
ann = Plots.series_annotations(missing)
@test Plots.series_annotations(["1" "2"; "3" "4"]) isa AbstractMatrix
@test Plots.series_annotations(10).strs[1].str == "10"
@test Plots.series_annotations(nothing) === nothing
@test Plots.series_annotations(ann) == ann
@test Plots.annotations(["1" "2"; "3" "4"]) isa AbstractMatrix
@test Plots.annotations(ann) == ann
@test Plots.annotations([ann]) == [ann]
@test Plots.annotations(nothing) == []
t = Plots.text("foo")
sp = plot(1)[1]
@test Plots.locate_annotation(sp, 1, 2, t) == (1, 2, t)
@test Plots.locate_annotation(sp, 1, 2, 3, t) == (1, 2, 3, t)
@test Plots.locate_annotation(sp, (0.1, 0.2), t) isa Tuple
@test Plots.locate_annotation(sp, (0.1, 0.2, 0.3), t) isa Tuple
end
@testset "Fonts" begin @testset "Fonts" begin
@testset "Scaling" begin @testset "Scaling" begin
sizesToCheck = [:titlefontsize, :legendfontsize, :legendtitlefontsize, sizesToCheck = [
:xtickfontsize, :ytickfontsize, :ztickfontsize, :titlefontsize,
:xguidefontsize, :yguidefontsize, :zguidefontsize,] :legendfontsize,
:legendtitlefontsize,
:xtickfontsize,
:ytickfontsize,
:ztickfontsize,
:xguidefontsize,
:yguidefontsize,
:zguidefontsize,
]
# get inital font sizes # get inital font sizes
initialSizes = [Plots.default(s) for s in sizesToCheck ] initialSizes = [Plots.default(s) for s in sizesToCheck]
#scale up font sizes #scale up font sizes
scalefontsizes(2) scalefontsizes(2)
# get inital font sizes # get inital font sizes
doubledSizes = [Plots.default(s) for s in sizesToCheck ] doubledSizes = [Plots.default(s) for s in sizesToCheck]
@test doubledSizes == initialSizes*2 @test doubledSizes == initialSizes * 2
# reset font sizes # reset font sizes
resetfontsizes() resetfontsizes()
finalSizes = [Plots.default(s) for s in sizesToCheck ] finalSizes = [Plots.default(s) for s in sizesToCheck]
@test finalSizes == initialSizes @test finalSizes == initialSizes
end end
end end
@testset "Series Annotations" begin @testset "Series Annotations" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)]) square = Shape([(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)])
@test_logs (:warn,"Unused SeriesAnnotations arg: triangle (Symbol)") begin @test_logs (:warn, "Unused SeriesAnnotations arg: triangle (Symbol)") begin
p = plot([1,2,3], p = plot(
series_annotations=(["a"], [1, 2, 3],
2, # pass a scale factor series_annotations = (
(1,4), # pass two scale factors (overwrites first one) ["a"],
square, # pass a shape 2, # pass a scale factor
font(:courier), # pass an annotation font (1, 4), # pass two scale factors (overwrites first one)
:triangle # pass an incorrect argument square, # pass a shape
)) font(:courier), # pass an annotation font
:triangle, # pass an incorrect argument
),
)
sa = p.series_list[1].plotattributes[:series_annotations] sa = p.series_list[1].plotattributes[:series_annotations]
@test sa.strs == ["a"] @test only(sa.strs).str == "a"
@test sa.font.family == "courier" @test sa.font.family == "courier"
@test sa.baseshape == square @test sa.baseshape == square
@test sa.scalefactor == (1,4) @test sa.scalefactor == (1, 4)
end end
spl = scatter(
4.53 .* [1 / 1 1 / 2 1 / 3 1 / 4 1 / 5],
[0 0 0 0 0],
layout = (5, 1),
ylims = (-1.1, 1.1),
xlims = (0, 5),
series_annotations = permutedims([["1/1"], ["1/2"], ["1/3"], ["1/4"], ["1/5"]]),
)
for i in 1:5
@test only(spl.series_list[i].plotattributes[:series_annotations].strs).str ==
"1/$i"
end
p = plot([1, 2], annotations = (1.5, 2, text("foo", :left)))
x, y, txt = only(p.subplots[end][:annotations])
@test (x, y) == (1.5, 2)
@test txt.str == "foo"
p = plot([1, 2], annotations = ((0.1, 0.5), :auto))
pos, txt = only(p.subplots[end][:annotations])
@test pos == (0.1, 0.5)
@test txt.str == "(a)"
end
@testset "Bezier" begin
curve = Plots.BezierCurve([Plots.P2(0.0, 0.0), Plots.P2(0.5, 1.0), Plots.P2(1.0, 0.0)])
@test curve(0.75) == Plots.P2(0.75, 0.375)
@test length(coords(curve, 10)) == 10
end end

68
test/test_contours.jl Normal file
View File

@ -0,0 +1,68 @@
using Plots, Test
import RecipesPipeline
@testset "Contours" begin
@testset "check_contour_levels" begin
@test Plots.check_contour_levels(2) === nothing
@test Plots.check_contour_levels(-1.0:0.2:10.0) === nothing
@test Plots.check_contour_levels([-100, -2, -1, 0, 1, 2, 100]) === nothing
@test_throws ArgumentError Plots.check_contour_levels(1.0)
@test_throws ArgumentError Plots.check_contour_levels((1, 2, 3))
@test_throws ArgumentError Plots.check_contour_levels(-3)
end
@testset "RecipesPipeline.preprocess_attributes!" begin
function equal_after_pipeline(kw)
kw = deepcopy(kw)
RecipesPipeline.preprocess_attributes!(kw)
kw == kw
end
@test equal_after_pipeline(KW(:levels => 1))
@test equal_after_pipeline(KW(:levels => 1:10))
@test equal_after_pipeline(KW(:levels => [1.0, 3.0, 5.0]))
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(
KW(:levels => 1.0),
)
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(
KW(:levels => (1, 2, 3)),
)
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(KW(:levels => -3))
end
@testset "contour[f]" begin
x = (-2π):0.1:(2π)
y = (-π):0.1:π
z = cos.(y) .* sin.(x')
@testset "Incorrect input" begin
@test_throws ArgumentError contour(x, y, z, levels = 1.0)
@test_throws ArgumentError contour(x, y, z, levels = (1, 2, 3))
@test_throws ArgumentError contour(x, y, z, levels = -3)
end
@testset "Default number" begin
@test contour(x, y, z)[1][1].plotattributes[:levels] ==
Plots._series_defaults[:levels]
end
@testset "Number" begin
@testset "$n contours" for n in (2, 5, 100)
p = contour(x, y, z, levels = n)
attr = p[1][1].plotattributes
@test attr[:seriestype] == :contour
@test attr[:levels] == n
end
end
@testset "Range" begin
levels = -1:0.5:1
@test contour(x, y, z, levels = levels)[1][1].plotattributes[:levels] == levels
end
@testset "Set of levels" begin
levels = [-1, 0.25, 0, 0.25, 1]
@test contour(x, y, z, levels = levels)[1][1].plotattributes[:levels] == levels
end
end
end

View File

@ -1,11 +1,101 @@
using Plots, Test using Plots, Test, Plots.Colors
const PLOTS_DEFAULTS = Dict(:theme => :wong2) const PLOTS_DEFAULTS = Dict(:theme => :wong2, :fontfamily => :palantino)
Plots.__init__() Plots.__init__()
@testset "Loading theme" begin @testset "Loading theme" begin
@test plot(1:5)[1][1][:seriescolor] == RGBA(colorant"black") pl = plot(1:5)
@test pl[1][1][:seriescolor] == RGBA(colorant"black")
@test Plots.guidefont(pl[1][:xaxis]).family == "palantino"
end end
empty!(PLOTS_DEFAULTS) empty!(PLOTS_DEFAULTS)
Plots.__init__() Plots.__init__()
@testset "default" begin
default(fillrange = 0)
@test Plots._series_defaults[:fillrange] == 0
pl = plot(1:5)
@test pl[1][1][:fillrange] == 0
default()
end
@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)
#remember settings
plot(legend_font_pointsize = 20)
sp = plot!(label = "R")[1]
@test Plots.legendfont(sp).pointsize == 20
#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]
# magic invocation
@test_nowarn sp = plot(; legendfont = 12)[1]
@test sp[:legend_font_pointsize] == 12
@test Plots.legendfont(sp).pointsize == 12
end # testset

View File

@ -1,21 +1,20 @@
using Plots, HDF5 using Plots, HDF5
@testset "HDF5_Plots" begin @testset "HDF5_Plots" begin
fname = "tmpplotsave.hdf5" fname = "tmpplotsave.hdf5"
hdf5() hdf5()
x = 1:10 x = 1:10
psrc=plot(x, x.*x); #Create some plot psrc = plot(x, x .* x) #Create some plot
Plots.hdf5plot_write(psrc, fname) Plots.hdf5plot_write(psrc, fname)
#Read back file: #Read back file:
gr() #Choose some fast backend likely to work in test environment. gr() #Choose some fast backend likely to work in test environment.
pread = Plots.hdf5plot_read(fname) pread = Plots.hdf5plot_read(fname)
#Make sure data made it through: #Make sure data made it through:
@test psrc.subplots[1].series_list[1][:x] == pread.subplots[1].series_list[1][:x] @test psrc.subplots[1].series_list[1][:x] == pread.subplots[1].series_list[1][:x]
@test psrc.subplots[1].series_list[1][:y] == pread.subplots[1].series_list[1][:y] @test psrc.subplots[1].series_list[1][:y] == pread.subplots[1].series_list[1][:y]
#display(pread) #Don't display. Regression env might not support #display(pread) #Don't display. Regression env might not support
end #testset end #testset

98
test/test_layouts.jl Normal file
View File

@ -0,0 +1,98 @@
using Plots, Test
@testset "Subplot sclicing" begin
pl = @test_nowarn plot(
rand(4, 8),
layout = 4,
yscale = [:identity :identity :log10 :log10],
)
@test pl[1][:yaxis][:scale] == :identity
@test pl[2][:yaxis][:scale] == :identity
@test pl[3][:yaxis][:scale] == :log10
@test pl[4][:yaxis][:scale] == :log10
end
@testset "Plot title" begin
pl = plot(rand(4, 8), layout = 4, plot_title = "My title")
@test pl[:plot_title] == "My title"
@test pl[:plot_titleindex] == 5
plot!(pl)
@test pl[:plot_title] == "My title"
@test pl[:plot_titleindex] == 5
plot!(pl, plot_title = "My new title")
@test pl[:plot_title] == "My new title"
@test pl[:plot_titleindex] == 5
end
@testset "Plots.jl/issues/4083" begin
p = plot(plot(1:2), plot(1:2); border = :grid, plot_title = "abc")
@test p[1][:framestyle] === :grid
@test p[2][:framestyle] === :grid
@test p[3][:framestyle] === :none
end
@testset "Coverage" begin
p = plot((plot(i) for i in 1:4)..., layout = (2, 2))
sp = p[end]
@test sp isa Plots.Subplot
@test size(sp) == (1, 1)
@test length(sp) == 1
@test sp[1, 1] == sp
@test Plots.get_subplot(p, UInt32(4)) == sp
@test Plots.series_list(sp) |> first |> Plots.get_subplot isa Plots.Subplot
@test Plots.get_subplot(p, keys(p.spmap) |> first) isa Plots.Subplot
gl = p[2, 2]
@test gl isa Plots.GridLayout
@test length(gl) == 1
@test size(gl) == (1, 1)
@test Plots.layout_args(gl) == (gl, 1)
@test size(p, 1) == 2
@test size(p, 2) == 2
@test size(p) === (2, 2)
@test ndims(p) == 2
@test p[1][end] isa Plots.Series
show(devnull, p[1])
@test Plots.getplot(p) == p
@test Plots.getattr(p) == p.attr
@test Plots.backend_object(p) == p.o
@test occursin("Plot", string(p))
print(devnull, p)
@test Plots.to_pixels(1Plots.mm) isa AbstractFloat
@test Plots.ispositive(1Plots.mm)
@test size(Plots.defaultbox) == (0Plots.mm, 0Plots.mm)
show(devnull, Plots.defaultbox)
show(devnull, p.layout)
@test Plots.make_measure_hor(1Plots.mm) == 1Plots.mm
@test Plots.make_measure_vert(1Plots.mm) == 1Plots.mm
@test Plots.parent(p.layout) isa Plots.RootLayout
show(devnull, Plots.parent_bbox(p.layout))
rl = Plots.RootLayout()
show(devnull, rl)
@test parent(rl) === nothing
@test Plots.parent_bbox(rl) == Plots.defaultbox
@test Plots.bbox(rl) == Plots.defaultbox
el = Plots.EmptyLayout()
@test Plots.update_position!(el) === nothing
@test size(el) == (0, 0)
@test length(el) == 0
@test el[1, 1] === nothing
@test Plots.left(el) == 0Plots.mm
@test Plots.top(el) == 0Plots.mm
@test Plots.right(el) == 0Plots.mm
@test Plots.bottom(el) == 0Plots.mm
@test_throws ErrorException Plots.layout_args(nothing)
end

View File

@ -2,410 +2,410 @@ using Plots, Test
pgfplotsx() pgfplotsx()
function create_plot(args...; kwargs...) function create_plot(args...; kwargs...)
pgfx_plot = plot(args...; kwargs...) pgfx_plot = plot(args...; kwargs...)
return pgfx_plot, repr("application/x-tex", pgfx_plot) return pgfx_plot, repr("application/x-tex", pgfx_plot)
end end
function create_plot!(args...; kwargs...) function create_plot!(args...; kwargs...)
pgfx_plot = plot!(args...; kwargs...) pgfx_plot = plot!(args...; kwargs...)
return pgfx_plot, repr("application/x-tex", pgfx_plot) return pgfx_plot, repr("application/x-tex", pgfx_plot)
end end
@testset "PGFPlotsX" begin @testset "PGFPlotsX" begin
pgfx_plot = plot(1:5) pgfx_plot = plot(1:5)
Plots._update_plot_object(pgfx_plot) Plots._update_plot_object(pgfx_plot)
@test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument @test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument
@test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing @test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing
axis = Plots.pgfx_axes(pgfx_plot.o)[1] axis = Plots.pgfx_axes(pgfx_plot.o)[1]
@test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 1 @test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 1
@test !haskey(axis.contents[1].options.dict, "fill") @test !haskey(axis.contents[1].options.dict, "fill")
@testset "Legends" begin @testset "Legends" begin
legends_plot = plot(rand(5, 2), lab = ["1" ""]) legends_plot = plot(rand(5, 2), lab = ["1" ""], arrow = true)
scatter!(legends_plot, rand(5)) scatter!(legends_plot, rand(5))
Plots._update_plot_object(legends_plot) Plots._update_plot_object(legends_plot)
axis_contents = Plots.pgfx_axes(legends_plot.o)[1].contents axis_contents = Plots.pgfx_axes(legends_plot.o)[1].contents
leg_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis_contents) leg_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis_contents)
series = filter(x -> x isa PGFPlotsX.Plot, axis_contents) series = filter(x -> x isa PGFPlotsX.Plot, axis_contents)
@test length(leg_entries) == 2 @test length(leg_entries) == 2
@test !haskey(series[1].options.dict, "forget plot") @test length(series) == 5
@test haskey(series[2].options.dict, "forget plot") @test !haskey(series[1].options.dict, "forget plot")
@test !haskey(series[3].options.dict, "forget plot") @test haskey(series[2].options.dict, "forget plot")
end # testset @test haskey(series[3].options.dict, "forget plot")
@test haskey(series[4].options.dict, "forget plot")
@test !haskey(series[5].options.dict, "forget plot")
end # testset
@testset "3D docs example" begin @testset "3D docs example" begin
n = 100 n = 100
ts = range(0, stop = 8π, length = n) ts = range(0, stop = 8π, length = n)
x = ts .* map(cos, ts) x = ts .* map(cos, ts)
y = (0.1ts) .* map(sin, ts) y = (0.1ts) .* map(sin, ts)
z = 1:n z = 1:n
pl = plot( pl = plot(
x, x,
y, y,
z, z,
zcolor = reverse(z), zcolor = reverse(z),
m = (10, 0.8, :blues, Plots.stroke(0)), m = (10, 0.8, :blues, Plots.stroke(0)),
leg = false, leg = false,
cbar = true, cbar = true,
w = 5, w = 5,
) )
pgfx_plot = plot!(pl, zeros(n), zeros(n), 1:n, w = 10) pgfx_plot = plot!(pl, zeros(n), zeros(n), 1:n, w = 10)
Plots._update_plot_object(pgfx_plot) Plots._update_plot_object(pgfx_plot)
if @test_nowarn( if @test_nowarn(
haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true
) )
@test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing
end end
end # testset end # testset
@testset "Color docs example" begin @testset "Color docs example" begin
y = rand(100) y = rand(100)
plot( plot(
0:10:100, 0:10:100,
rand(11, 4), rand(11, 4),
lab = "lines", lab = "lines",
w = 3, w = 3,
palette = :grays, palette = :grays,
fill = 0, fill = 0,
α = 0.6, α = 0.6,
) )
pl = scatter!( pl = scatter!(
y, y,
zcolor = abs.(y .- 0.5), zcolor = abs.(y .- 0.5),
m = (:hot, 0.8, Plots.stroke(1, :green)), m = (:hot, 0.8, Plots.stroke(1, :green)),
ms = 10 * abs.(y .- 0.5) .+ 4, ms = 10 * abs.(y .- 0.5) .+ 4,
lab = ["grad", "", "ient"], lab = ["grad", "", "ient"],
) )
Plots._update_plot_object(pl) Plots._update_plot_object(pl)
axis = Plots.pgfx_axes(pl.o)[1] axis = Plots.pgfx_axes(pl.o)[1]
@test count(x -> x isa PGFPlotsX.LegendEntry, axis.contents) == 6 @test count(x -> x isa PGFPlotsX.LegendEntry, axis.contents) == 6
@test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 108 # each marker is its own plot, fillranges create 2 plot-objects @test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 108 # each marker is its own plot, fillranges create 2 plot-objects
marker = axis.contents[15] marker = axis.contents[15]
@test marker isa PGFPlotsX.Plot @test marker isa PGFPlotsX.Plot
@test marker.options["mark"] == "*" @test marker.options["mark"] == "*"
@test marker.options["mark options"]["color"] == @test marker.options["mark options"]["color"] == RGBA{Float64}(colorant"green", 0.8)
RGBA{Float64}(colorant"green", 0.8) @test marker.options["mark options"]["line width"] == 0.75 # 1px is 0.75pt
@test marker.options["mark options"]["line width"] == 0.75 # 1px is 0.75pt end # testset
end # testset @testset "Plot in pieces" begin
@testset "Plot in pieces" begin pic = plot(rand(100) / 3, reg = true, fill = (0, :green))
pic = plot(rand(100) / 3, reg = true, fill = (0, :green)) scatter!(pic, rand(100), markersize = 6, c = :orange)
scatter!(pic, rand(100), markersize = 6, c = :orange) Plots._update_plot_object(pic)
Plots._update_plot_object(pic) axis_contents = Plots.pgfx_axes(pic.o)[1].contents
axis_contents = Plots.pgfx_axes(pic.o)[1].contents leg_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis_contents)
leg_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis_contents) series = filter(x -> x isa PGFPlotsX.Plot, axis_contents)
series = filter(x -> x isa PGFPlotsX.Plot, axis_contents) @test length(leg_entries) == 2
@test length(leg_entries) == 2 @test length(series) == 4
@test length(series) == 4 @test haskey(series[1].options.dict, "forget plot")
@test haskey(series[1].options.dict, "forget plot") @test !haskey(series[2].options.dict, "forget plot")
@test !haskey(series[2].options.dict, "forget plot") @test haskey(series[3].options.dict, "forget plot")
@test haskey(series[3].options.dict, "forget plot") @test !haskey(series[4].options.dict, "forget plot")
@test !haskey(series[4].options.dict, "forget plot") end # testset
end # testset @testset "Marker types" begin
@testset "Marker types" begin markers = filter((m -> begin
markers = filter((m -> begin m in Plots.supported_markers()
m in Plots.supported_markers() end), Plots._shape_keys)
end), Plots._shape_keys) markers = reshape(markers, 1, length(markers))
markers = reshape(markers, 1, length(markers)) n = length(markers)
n = length(markers) x = (range(0, stop = 10, length = n + 2))[2:(end - 1)]
x = (range(0, stop = 10, length = n + 2))[2:(end-1)] y = repeat(reshape(reverse(x), 1, :), n, 1)
y = repeat(reshape(reverse(x), 1, :), n, 1) scatter(
scatter( x,
x, y,
y, m = (8, :auto),
m = (8, :auto), lab = map(string, markers),
lab = map(string, markers), bg = :linen,
bg = :linen, xlim = (0, 10),
xlim = (0, 10), ylim = (0, 10),
ylim = (0, 10), )
) end # testset
end # testset @testset "Layout" begin
@testset "Layout" begin plot(
plot( Plots.fakedata(100, 10),
Plots.fakedata(100, 10), layout = 4,
layout = 4, palette = [:grays :blues :hot :rainbow],
palette = [:grays :blues :hot :rainbow], bg_inside = [:orange :pink :darkblue :black],
bg_inside = [:orange :pink :darkblue :black], )
) end # testset
end # testset @testset "Polar plots" begin
@testset "Polar plots" begin Θ = range(0, stop = 1.5π, length = 100)
Θ = range(0, stop = 1.5π, length = 100) r = abs.(0.1 * randn(100) + sin.(3Θ))
r = abs.(0.1 * randn(100) + sin.(3Θ)) plot(Θ, r, proj = :polar, m = 2)
plot(Θ, r, proj = :polar, m = 2) end # testset
end # testset @testset "Drawing shapes" begin
@testset "Drawing shapes" begin verts = [
verts = [ (-1.0, 1.0),
(-1.0, 1.0), (-1.28, 0.6),
(-1.28, 0.6), (-0.2, -1.4),
(-0.2, -1.4), (0.2, -1.4),
(0.2, -1.4), (1.28, 0.6),
(1.28, 0.6), (1.0, 1.0),
(1.0, 1.0), (-1.0, 1.0),
(-1.0, 1.0), (-0.2, -0.6),
(-0.2, -0.6), (0.0, -0.2),
(0.0, -0.2), (-0.4, 0.6),
(-0.4, 0.6), (1.28, 0.6),
(1.28, 0.6), (0.2, -1.4),
(0.2, -1.4), (-0.2, -1.4),
(-0.2, -1.4), (0.6, 0.2),
(0.6, 0.2), (-0.2, 0.2),
(-0.2, 0.2), (0.0, -0.2),
(0.0, -0.2), (0.2, 0.2),
(0.2, 0.2), (-0.2, -0.6),
(-0.2, -0.6), ]
] x = 0.1:0.2:0.9
x = 0.1:0.2:0.9 y = 0.7 * rand(5) .+ 0.15
y = 0.7 * rand(5) .+ 0.15 plot(
plot( x,
x, y,
y, line = (3, :dash, :lightblue),
line = (3, :dash, :lightblue), marker = (Shape(verts), 30, RGBA(0, 0, 0, 0.2)),
marker = (Shape(verts), 30, RGBA(0, 0, 0, 0.2)), bg = :pink,
bg = :pink, fg = :darkblue,
fg = :darkblue, xlim = (0, 1),
xlim = (0, 1), ylim = (0, 1),
ylim = (0, 1), leg = false,
leg = false, )
) end # testset
end # testset @testset "Histogram 2D" begin
@testset "Histogram 2D" begin histogram2d(randn(10000), randn(10000), nbins = 20)
histogram2d(randn(10000), randn(10000), nbins = 20) end # testset
end # testset @testset "Heatmap-like" begin
@testset "Heatmap-like" begin xs = [string("x", i) for i in 1:10]
xs = [string("x", i) for i = 1:10] ys = [string("y", i) for i in 1:4]
ys = [string("y", i) for i = 1:4] z = float((1:4) * reshape(1:10, 1, :))
z = float((1:4) * reshape(1:10, 1, :)) pgfx_plot = heatmap(xs, ys, z, aspect_ratio = 1)
pgfx_plot = heatmap(xs, ys, z, aspect_ratio = 1) Plots._update_plot_object(pgfx_plot)
Plots._update_plot_object(pgfx_plot) if @test_nowarn(
if @test_nowarn( haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true
haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true )
) @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing
@test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing @test Plots.pgfx_axes(pgfx_plot.o)[1]["colormap name"] == "plots1"
@test Plots.pgfx_axes(pgfx_plot.o)[1]["colormap name"] == "plots1" end
end
pgfx_plot = wireframe(xs, ys, z, aspect_ratio = 1) pgfx_plot = wireframe(xs, ys, z, aspect_ratio = 1)
# TODO: clims are wrong # TODO: clims are wrong
end # testset end # testset
@testset "Contours" begin @testset "Contours" begin
x = 1:0.5:20 x = 1:0.5:20
y = 1:0.5:10 y = 1:0.5:10
f(x, y) = begin f(x, y) = begin
(3x + y^2) * abs(sin(x) + cos(y)) (3x + y^2) * abs(sin(x) + cos(y))
end end
X = repeat(reshape(x, 1, :), length(y), 1) X = repeat(reshape(x, 1, :), length(y), 1)
Y = repeat(y, 1, length(x)) Y = repeat(y, 1, length(x))
Z = map(f, X, Y) Z = map(f, X, Y)
p2 = contour(x, y, Z) p2 = contour(x, y, Z)
p1 = contour(x, y, f, fill = true) p1 = contour(x, y, f, fill = true)
plot(p1, p2) plot(p1, p2)
# TODO: colorbar for filled contours # TODO: colorbar for filled contours
end # testset end # testset
@testset "Varying colors" begin @testset "Varying colors" begin
t = range(0, stop = 1, length = 100) t = range(0, stop = 1, length = 100)
θ = (6π) .* t θ = (6π) .* t
x = t .* cos.(θ) x = t .* cos.(θ)
y = t .* sin.(θ) y = t .* sin.(θ)
p1 = plot(x, y, line_z = t, linewidth = 3, legend = false) p1 = plot(x, y, line_z = t, linewidth = 3, legend = false)
p2 = scatter( p2 = scatter(x, y, marker_z = ((x, y) -> begin
x,
y,
marker_z = ((x, y) -> begin
x + y x + y
end), end), color = :bwr, legend = false)
color = :bwr, plot(p1, p2)
legend = false, end # testset
) @testset "Framestyles" begin
plot(p1, p2) scatter(
end # testset fill(randn(10), 6),
@testset "Framestyles" begin fill(randn(10), 6),
scatter( framestyle = [:box :semi :origin :zerolines :grid :none],
fill(randn(10), 6), title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"],
fill(randn(10), 6), color = permutedims(1:6),
framestyle = [:box :semi :origin :zerolines :grid :none], layout = 6,
title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], label = "",
color = permutedims(1:6), markerstrokewidth = 0,
layout = 6, ticks = -2:2,
label = "", )
markerstrokewidth = 0, # TODO: support :semi
ticks = -2:2, end # testset
) @testset "Quiver" begin
# TODO: support :semi x = (-2pi):0.2:(2 * pi)
end # testset y = sin.(x)
@testset "Quiver" begin
x = (-2pi):0.2:(2*pi)
y = sin.(x)
u = ones(length(x)) u = ones(length(x))
v = cos.(x) v = cos.(x)
arrow_plot = plot(x, y, quiver = (u, v), arrow = true) arrow_plot = plot(x, y, quiver = (u, v), arrow = true)
# TODO: could adjust limits to fit arrows if too long, but how? # TODO: could adjust limits to fit arrows if too long, but how?
# TODO: get latex available on CI # TODO: get latex available on CI
# mktempdir() do path # mktempdir() do path
# @test_nowarn savefig(arrow_plot, path*"arrow.pdf") # @test_nowarn savefig(arrow_plot, path*"arrow.pdf")
# end # end
end # testset end # testset
@testset "Annotations" begin @testset "Annotations" begin
y = rand(10) y = rand(10)
pgfx_plot = plot( pgfx_plot =
y, plot(y, annotations = (3, y[3], Plots.text("this is \\#3", :left)), leg = false)
annotations = (3, y[3], Plots.text("this is \\#3", :left)), Plots._update_plot_object(pgfx_plot)
leg = false, axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents
) nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content)
Plots._update_plot_object(pgfx_plot) @test length(nodes) == 1
axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents mktempdir() do path
nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content) file_path = joinpath(path, "annotations.tex")
@test length(nodes) == 1 @test_nowarn savefig(pgfx_plot, file_path)
mktempdir() do path open(file_path) do io
file_path = joinpath(path, "annotations.tex") lines = readlines(io)
@test_nowarn savefig(pgfx_plot, file_path) @test count(s -> occursin("node", s), lines) == 1
open(file_path) do io end
lines = readlines(io) end
@test count(s -> occursin("node", s), lines) == 1 annotate!([
end (5, y[5], Plots.text("this is \\#5", 16, :red, :center)),
end (10, y[10], Plots.text("this is \\#10", :right, 20, "courier")),
annotate!([ ])
(5, y[5], Plots.text("this is \\#5", 16, :red, :center)), Plots._update_plot_object(pgfx_plot)
(10, y[10], Plots.text("this is \\#10", :right, 20, "courier")), axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents
]) nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content)
Plots._update_plot_object(pgfx_plot) @test length(nodes) == 3
axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents mktempdir() do path
nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content) file_path = joinpath(path, "annotations.tex")
@test length(nodes) == 3 @test_nowarn savefig(pgfx_plot, file_path)
mktempdir() do path open(file_path) do io
file_path = joinpath(path, "annotations.tex") lines = readlines(io)
@test_nowarn savefig(pgfx_plot, file_path) @test count(s -> occursin("node", s), lines) == 3
open(file_path) do io end
lines = readlines(io) end
@test count(s -> occursin("node", s), lines) == 3 annotation_plot = scatter!(
end range(2, stop = 8, length = 6),
end rand(6),
annotation_plot = scatter!( marker = (50, 0.2, :orange),
range(2, stop = 8, length = 6), series_annotations = [
rand(6), "series",
marker = (50, 0.2, :orange), "annotations",
series_annotations = [ "map",
"series", "to",
"annotations", "series",
"map", Plots.text("data", :green),
"to", ],
"series", )
Plots.text("data", :green), Plots._update_plot_object(annotation_plot)
], axis_content = Plots.pgfx_axes(annotation_plot.o)[1].contents
) nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content)
Plots._update_plot_object(annotation_plot) @test length(nodes) == 9
axis_content = Plots.pgfx_axes(annotation_plot.o)[1].contents mktempdir() do path
nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content) file_path = joinpath(path, "annotations.tex")
@test length(nodes) == 9 @test_nowarn savefig(annotation_plot, file_path)
mktempdir() do path open(file_path) do io
file_path = joinpath(path, "annotations.tex") lines = readlines(io)
@test_nowarn savefig(annotation_plot, file_path) @test count(s -> occursin("node", s), lines) == 9
open(file_path) do io end
lines = readlines(io) # test .tikz extension
@test count(s -> occursin("node", s), lines) == 9 file_path = joinpath(path, "annotations.tikz")
end @test_nowarn savefig(annotation_plot, file_path)
# test .tikz extension @test_nowarn open(file_path) do io
file_path = joinpath(path, "annotations.tikz") end
@test_nowarn savefig(annotation_plot, file_path) end
@test_nowarn open(file_path) do io end # testset
end @testset "Ribbon" begin
end aa = rand(10)
end # testset bb = rand(10)
@testset "Ribbon" begin cc = rand(10)
aa = rand(10) conf = [aa - cc bb - cc]
bb = rand(10) ribbon_plot = plot(collect(1:10), fill(1, 10), ribbon = (conf[:, 1], conf[:, 2]))
cc = rand(10) Plots._update_plot_object(ribbon_plot)
conf = [aa - cc bb - cc] axis = Plots.pgfx_axes(ribbon_plot.o)[1]
ribbon_plot = plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents)
plot(collect(1:10), fill(1, 10), ribbon = (conf[:, 1], conf[:, 2])) @test length(plots) == 3
Plots._update_plot_object(ribbon_plot) @test haskey(plots[1].options.dict, "fill")
axis = Plots.pgfx_axes(ribbon_plot.o)[1] @test haskey(plots[2].options.dict, "fill")
plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents) @test !haskey(plots[3].options.dict, "fill")
@test length(plots) == 3 @test ribbon_plot.o !== nothing
@test haskey(plots[1].options.dict, "fill") @test ribbon_plot.o.the_plot !== nothing
@test haskey(plots[2].options.dict, "fill") end # testset
@test !haskey(plots[3].options.dict, "fill") @testset "Markers and Paths" begin
@test ribbon_plot.o !== nothing pl = plot(
@test ribbon_plot.o.the_plot !== nothing 5 .- ones(9),
end # testset markershape = [:utriangle, :rect],
@testset "Markers and Paths" begin markersize = 8,
pl = plot( color = [:red, :black],
5 .- ones(9), )
markershape = [:utriangle, :rect], Plots._update_plot_object(pl)
markersize = 8, axis = Plots.pgfx_axes(pl.o)[1]
color = [:red, :black], plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents)
) @test length(plots) == 9
Plots._update_plot_object(pl) end # testset
axis = Plots.pgfx_axes(pl.o)[1] @testset "Groups and Subplots" begin
plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents) group = rand(map((i -> begin
@test length(plots) == 9 "group $(i)"
end # testset end), 1:4), 100)
pl = plot(
rand(100),
layout = @layout([a b; c]),
group = group,
linetype = [:bar :scatter :steppre],
linecolor = :match,
)
Plots._update_plot_object(pl)
axis = Plots.pgfx_axes(pl.o)[1]
legend_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis.contents)
@test length(legend_entries) == 2
end
end # testset end # testset
@testset "Extra kwargs" begin @testset "Extra kwargs" begin
pl = plot(1:5, test = "me") pl = plot(1:5, test = "me")
@test pl[1][1].plotattributes[:extra_kwargs][:test] == "me" @test pl[1][1].plotattributes[:extra_kwargs][:test] == "me"
pl = plot(1:5, test = "me", extra_kwargs = :subplot) pl = plot(1:5, test = "me", extra_kwargs = :subplot)
@test pl[1].attr[:extra_kwargs][:test] == "me" @test pl[1].attr[:extra_kwargs][:test] == "me"
pl = plot(1:5, test = "me", extra_kwargs = :plot) pl = plot(1:5, test = "me", extra_kwargs = :plot)
@test pl.attr[:extra_plot_kwargs][:test] == "me" @test pl.attr[:extra_plot_kwargs][:test] == "me"
pl = plot( pl = plot(
1:5, 1:5,
extra_kwargs = Dict( extra_kwargs = Dict(
:plot => Dict(:test => "me"), :plot => Dict(:test => "me"),
:series => Dict(:and => "me too"), :series => Dict(:and => "me too"),
), ),
) )
@test pl.attr[:extra_plot_kwargs][:test] == "me" @test pl.attr[:extra_plot_kwargs][:test] == "me"
@test pl[1][1].plotattributes[:extra_kwargs][:and] == "me too" @test pl[1][1].plotattributes[:extra_kwargs][:and] == "me too"
pl = plot( pl = plot(
plot(1:5, title = "Line"), plot(1:5, title = "Line"),
scatter( scatter(
1:5, 1:5,
title = "Scatter", title = "Scatter",
extra_kwargs = Dict(:subplot => Dict("axis line shift" => "10pt")), extra_kwargs = Dict(:subplot => Dict("axis line shift" => "10pt")),
), ),
) )
Plots._update_plot_object(pl) Plots._update_plot_object(pl)
axes = Plots.pgfx_axes(pl.o) axes = Plots.pgfx_axes(pl.o)
@test !haskey(axes[1].options.dict, "axis line shift") @test !haskey(axes[1].options.dict, "axis line shift")
@test haskey(axes[2].options.dict, "axis line shift") @test haskey(axes[2].options.dict, "axis line shift")
pl = plot( pl =
x -> x, plot(x -> x, -1:1; add = raw"\node at (0,0.5) {\huge hi};", extra_kwargs = :subplot)
-1:1; @test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};")
add = raw"\node at (0,0.5) {\huge hi};", Plots._update_plot_object(pl)
extra_kwargs = :subplot, axes = Plots.pgfx_axes(pl.o)
) @test filter(x -> x isa String, axes[1].contents)[1] ==
@test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};") raw"\node at (0,0.5) {\huge hi};"
Plots._update_plot_object(pl) plot!(pl)
axes = Plots.pgfx_axes(pl.o) @test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};")
@test filter(x -> x isa String, axes[1].contents)[1] == Plots._update_plot_object(pl)
raw"\node at (0,0.5) {\huge hi};" axes = Plots.pgfx_axes(pl.o)
plot!(pl) @test filter(x -> x isa String, axes[1].contents)[1] ==
@test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};") raw"\node at (0,0.5) {\huge hi};"
Plots._update_plot_object(pl)
axes = Plots.pgfx_axes(pl.o)
@test filter(x -> x isa String, axes[1].contents)[1] ==
raw"\node at (0,0.5) {\huge hi};"
end # testset end # testset
@testset "Titlefonts" begin @testset "Titlefonts" begin
pl = plot(1:5, title = "Test me", titlefont = (2, :left)) pl = plot(1:5, title = "Test me", titlefont = (2, :left))
@test pl[1][:title] == "Test me" @test pl[1][:title] == "Test me"
@test pl[1][:titlefontsize] == 2 @test pl[1][:titlefontsize] == 2
@test pl[1][:titlefonthalign] == :left @test pl[1][:titlefonthalign] == :left
Plots._update_plot_object(pl) Plots._update_plot_object(pl)
ax_opt = Plots.pgfx_axes(pl.o)[1].options ax_opt = Plots.pgfx_axes(pl.o)[1].options
@test ax_opt["title"] == "Test me" @test ax_opt["title"] == "Test me"
@test(haskey(ax_opt.dict, "title style")) isa Test.Pass @test(haskey(ax_opt.dict, "title style")) isa Test.Pass
pl = plot(1:5, plot_title = "Test me", plot_titlefont = (2, :left)) pl = plot(1:5, plot_title = "Test me", plot_titlefont = (2, :left))
@test pl[:plot_title] == "Test me" @test pl[:plot_title] == "Test me"
@test pl[:plot_titlefontsize] == 2 @test pl[:plot_titlefontsize] == 2
@test pl[:plot_titlefonthalign] == :left @test pl[:plot_titlefonthalign] == :left
pl = heatmap( pl = heatmap(rand(3, 3), colorbar_title = "Test me", colorbar_titlefont = (12, :right))
rand(3, 3), @test pl[1][:colorbar_title] == "Test me"
colorbar_title = "Test me", @test pl[1][:colorbar_titlefontsize] == 12
colorbar_titlefont = (12, :right), @test pl[1][:colorbar_titlefonthalign] == :right
)
@test pl[1][:colorbar_title] == "Test me"
@test pl[1][:colorbar_titlefontsize] == 12
@test pl[1][:colorbar_titlefonthalign] == :right
end # testset end # testset

38
test/test_pipeline.jl Normal file
View File

@ -0,0 +1,38 @@
using Plots, Test
using RecipesPipeline
@testset "plot" begin
pl = plot(1:5)
pl2 = plot(pl, tex_output_standalone = true)
@test pl[:tex_output_standalone] == false
@test pl2[:tex_output_standalone] == true
plot!(pl, tex_output_standalone = true)
@test pl[:tex_output_standalone] == true
end
@testset "get_axis_limits" begin
x = [0.1, 5]
p1 = plot(x, [5, 0.1], yscale = :log10)
p2 = plot!(identity)
@test all(RecipesPipeline.get_axis_limits(p1, :x) .== x)
@test all(RecipesPipeline.get_axis_limits(p2, :x) .== x)
end
@testset "Slicing" begin
@test plot(1:5, fillrange = 0)[1][1][:fillrange] == 0
data4 = rand(4, 4)
mat = reshape(1:8, 2, 4)
for i in axes(data4, 1)
for attribute in (:fillrange, :ribbon)
@test plot(data4; NamedTuple{tuple(attribute)}(0)...)[1][i][attribute] == 0
@test plot(data4; NamedTuple{tuple(attribute)}(Ref([1, 2]))...)[1][i][attribute] ==
[1.0, 2.0]
@test plot(data4; NamedTuple{tuple(attribute)}(Ref([1 2]))...)[1][i][attribute] ==
(iseven(i) ? 2 : 1)
@test plot(data4; NamedTuple{tuple(attribute)}(Ref(mat))...)[1][i][attribute] ==
[2(i - 1) + 1, 2i]
end
@test plot(data4, ribbon = (mat, mat))[1][i][:ribbon] ==
([2(i - 1) + 1, 2i], [2(i - 1) + 1, 2i])
end
end

64
test/test_plotly.jl Normal file
View File

@ -0,0 +1,64 @@
using Plots, Test
@testset "Plotly" begin
@testset "Basic" begin
@test plotly() == Plots.PlotlyBackend()
@test backend() == Plots.PlotlyBackend()
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test_nowarn Plots.plotly_series(plot())
end
@testset "Contours" begin
x = (-2π):0.1:(2π)
y = (-π):0.1:π
z = cos.(y) .* sin.(x')
@testset "Contour numbers" begin
@testset "Default" begin
@test Plots.plotly_series(contour(x, y, z))[1][:ncontours] ==
Plots._series_defaults[:levels] + 2
end
@testset "Specified number" begin
@test Plots.plotly_series(contour(x, y, z, levels = 10))[1][:ncontours] ==
12
end
end
@testset "Contour values" begin
@testset "Range" begin
levels = -1:0.5:1
p = contour(x, y, z, levels = levels)
@test p[1][1].plotattributes[:levels] == levels
@test Plots.plotly_series(p)[1][:contours][:start] == first(levels)
@test Plots.plotly_series(p)[1][:contours][:end] == last(levels)
@test Plots.plotly_series(p)[1][:contours][:size] == step(levels)
end
@testset "Set of contours" begin
levels = [-1, -0.25, 0, 0.25, 1]
levels_range =
range(first(levels), stop = last(levels), length = length(levels))
p = contour(x, y, z, levels = levels)
@test p[1][1].plotattributes[:levels] == levels
series_dict = @test_logs (
:warn,
"setting arbitrary contour levels with Plotly backend " *
"is not supported; use a range to set equally-spaced contours or an " *
"integer to set the approximate number of contours with the keyword " *
"`levels`. Setting levels to -1.0:0.5:1.0",
) Plots.plotly_series(p)
@test series_dict[1][:contours][:start] == first(levels_range)
@test series_dict[1][:contours][:end] == last(levels_range)
@test series_dict[1][:contours][:size] == step(levels_range)
end
end
end
@testset "Extra kwargs" begin
pl = plot(1:5, test = "me")
@test Plots.plotly_series(pl)[1][:test] == "me"
pl = plot(1:5, test = "me", extra_kwargs = :plot)
@test Plots.plotly_layout(pl)[:test] == "me"
end
end

View File

@ -1,29 +1,41 @@
using Plots, Test using Plots, Test
using OffsetArrays 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 @testset "lens!" begin
pl = plot(1:5) pl = plot(1:5)
lens!(pl, [1,2], [1,2], inset = (1, bbox(0.0,0.0,0.2,0.2)), colorbar = false) lens!(pl, [1, 2], [1, 2], inset = (1, bbox(0.0, 0.0, 0.2, 0.2)), colorbar = false)
@test length(pl.series_list) == 4 @test length(pl.series_list) == 4
@test pl[2][:colorbar] == :none @test pl[2][:colorbar] == :none
end # testset end # testset
@testset "vline, vspan" begin @testset "vline, vspan" begin
vl = vline([1], widen = false) vl = vline([1], widen = false)
@test Plots.xlims(vl) == (1,2) @test Plots.xlims(vl) == (1, 2)
@test Plots.ylims(vl) == (1,2) @test Plots.ylims(vl) == (1, 2)
vl = vline([1], xlims=(0,2), widen = false) vl = vline([1], xlims = (0, 2), widen = false)
@test Plots.xlims(vl) == (0,2) @test Plots.xlims(vl) == (0, 2)
vl = vline([1], ylims=(-3,5), widen = false) vl = vline([1], ylims = (-3, 5), widen = false)
@test Plots.ylims(vl) == (-3,5) @test Plots.ylims(vl) == (-3, 5)
vsp = vspan([1,3], widen = false) vsp = vspan([1, 3], widen = false)
@test Plots.xlims(vsp) == (1,3) @test Plots.xlims(vsp) == (1, 3)
@test Plots.ylims(vsp) == (0,1) # TODO: might be problematic on log-scales @test Plots.ylims(vsp) == (0, 1) # TODO: might be problematic on log-scales
vsp = vspan([1,3], xlims=(-2,5), widen = false) vsp = vspan([1, 3], xlims = (-2, 5), widen = false)
@test Plots.xlims(vsp) == (-2,5) @test Plots.xlims(vsp) == (-2, 5)
vsp = vspan([1,3], ylims=(-2,5), widen = false) vsp = vspan([1, 3], ylims = (-2, 5), widen = false)
@test Plots.ylims(vsp) == (-2,5) @test Plots.ylims(vsp) == (-2, 5)
end # testset end # testset
@testset "offset axes" begin @testset "offset axes" begin
@ -46,4 +58,4 @@ end
prevha = ha prevha = ha
end end
end end
end end

View File

@ -4,45 +4,135 @@ using Plots, Test
@testset "Set Lims" begin @testset "Set Lims" begin
p = plot(rand(10)) p = plot(rand(10))
xlims!((1,20)) xlims!((1, 20))
@test xlims(p) == (1,20) @test xlims(p) == (1, 20)
ylims!((-1,1)) xlims!(p, (1, 21))
@test ylims(p) == (-1,1) @test xlims(p) == (1, 21)
zlims!((-1,1)) ylims!((-1, 1))
@test zlims(p) == (-1,1) @test ylims(p) == (-1, 1)
xlims!(-1,11) ylims!(p, (-2, 2))
@test xlims(p) == (-1,11) @test ylims(p) == (-2, 2)
ylims!((-10,10)) zlims!((-1, 1))
@test ylims(p) == (-10,10) @test zlims(p) == (-1, 1)
zlims!((-10,10)) zlims!(p, (-2, 2))
@test zlims(p) == (-10,10) @test zlims(p) == (-2, 2)
xlims!(-1, 11)
@test xlims(p) == (-1, 11)
xlims!(p, -2, 12)
@test xlims(p) == (-2, 12)
ylims!((-10, 10))
@test ylims(p) == (-10, 10)
ylims!(p, (-11, 9))
@test ylims(p) == (-11, 9)
zlims!((-10, 10))
@test zlims(p) == (-10, 10)
zlims!(p, (-9, 8))
@test zlims(p) == (-9, 8)
end
@testset "Set Title / Labels" begin
p = plot()
title!(p, "Foo")
sp = p[1]
@test sp[:title] == "Foo"
xlabel!(p, "xlabel")
@test sp[:xaxis][:guide] == "xlabel"
ylabel!(p, "ylabel")
@test sp[:yaxis][:guide] == "ylabel"
end
@testset "Misc" begin
p = plot()
sp = p[1]
xflip!(p)
@test sp[:xaxis][:flip]
yflip!(p)
@test sp[:yaxis][:flip]
xgrid!(p, true)
@test sp[:xaxis][:grid]
xgrid!(p, false)
@test !sp[:xaxis][:grid]
ygrid!(p, true)
@test sp[:yaxis][:grid]
ygrid!(p, false)
@test !sp[:yaxis][:grid]
ann = [(7, 3, "(7,3)"), (3, 7, text("hey", 14, :left, :top, :green))]
annotate!(p, ann)
annotate!(p, ann...)
xaxis!(p, true)
@test sp[:xaxis][:showaxis]
xaxis!(p, false)
@test !sp[:xaxis][:showaxis]
yaxis!(p, true)
@test sp[:yaxis][:showaxis]
yaxis!(p, false)
@test !sp[:yaxis][:showaxis]
p = plot3d([1, 2], [1, 2], [1, 2])
plot3d!(p, [3, 4], [3, 4], [3, 4])
@test Plots.series_list(p[1])[1][:seriestype] == :path3d
end end
@testset "Set Ticks" begin @testset "Set Ticks" begin
p = plot([0,2,3,4,5,6,7,8,9,10]) p = plot([0, 2, 3, 4, 5, 6, 7, 8, 9, 10])
sp = p[1]
xticks = 2:6 xticks = 2:6
xticks!(xticks) xticks!(xticks)
@test Plots.get_subplot(current(),1).attr[:xaxis][:ticks] == xticks @test sp.attr[:xaxis][:ticks] == xticks
xticks = 1:5
xticks!(p, xticks)
@test sp.attr[:xaxis][:ticks] == xticks
yticks = 0.2:0.1:0.7 yticks = 0.2:0.1:0.7
yticks!(yticks) yticks!(yticks)
@test Plots.get_subplot(current(),1).attr[:yaxis][:ticks] == yticks @test sp.attr[:yaxis][:ticks] == yticks
xticks = [5,6,7.5] yticks = 0.1:0.5
xlabels = ["a","b","c"] yticks!(p, yticks)
@test sp.attr[:yaxis][:ticks] == yticks
xticks = [5, 6, 7.5]
xlabels = ["a", "b", "c"]
xticks!(xticks, xlabels) xticks!(xticks, xlabels)
@test Plots.get_subplot(current(),1).attr[:xaxis][:ticks] == (xticks, xlabels) @test sp.attr[:xaxis][:ticks] == (xticks, xlabels)
yticks = [.5,.6,.75] xticks = [5, 2]
ylabels = ["z","y","x"] xlabels = ["b", "a"]
xticks!(p, xticks, xlabels)
@test sp.attr[:xaxis][:ticks] == (xticks, xlabels)
yticks = [0.5, 0.6, 0.75]
ylabels = ["z", "y", "x"]
yticks!(yticks, ylabels) yticks!(yticks, ylabels)
@test Plots.get_subplot(current(),1).attr[:yaxis][:ticks] == (yticks, ylabels) @test sp.attr[:yaxis][:ticks] == (yticks, ylabels)
yticks = [0.5, 0.1]
ylabels = ["z", "y"]
yticks!(p, yticks, ylabels)
@test sp.attr[:yaxis][:ticks] == (yticks, ylabels)
end end
end end