Compare commits

..

No commits in common. "master" and "v1.18.0" have entirely different histories.

74 changed files with 5113 additions and 9846 deletions

View File

@ -1,12 +0,0 @@
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,11 +20,10 @@ Backend | yes | no | untested
-------------|-----|-----|--------- -------------|-----|-----|---------
gr (default) | | | gr (default) | | |
pyplot | | | pyplot | | |
plotly | | |
plotlyjs | | | plotlyjs | | |
pgfplotsx | | | pgfplotsx | | |
unicodeplots | | |
inspectdr | | | inspectdr | | |
gaston | | |
### Versions ### Versions

View File

@ -1,11 +1,9 @@
# 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:
@ -16,19 +14,14 @@ 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: "nul" GKSwstype: "100"
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.6' # ⎤ - '1'
- '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:
@ -40,20 +33,11 @@ jobs:
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: |
cat /proc/cpuinfo julia --project -e 'using Pkg; Pkg.instantiate();'
cat /proc/meminfo julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); Pkg.develop(PackageSpec(; path=pwd())); using CompileBot; CompileBot.addtestdep();'
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
@ -85,21 +69,18 @@ jobs:
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
- name: CompileBot postprocess - name: CompileBot postprocess
run: | run: julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();'
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 [skip ci] commit-message: Update precompile_*.jl file
title: "[AUTO] Update precompiles [skip ci]" title: "[AUTO] Update precompiles"
labels: | labels: SnoopCompile
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,4 +12,3 @@ 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: benchmarks name: Run benchmarks
on: on:
pull_request: pull_request:
@ -6,14 +6,17 @@ 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.7' version: 1
# 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,8 +2,6 @@ name: ci
on: on:
push: push:
branches:
- master
pull_request: pull_request:
defaults: defaults:
@ -15,7 +13,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: "nul" GKSwstype: "100"
name: Julia ${{ matrix.version }} - ${{ matrix.os }} name: Julia ${{ matrix.version }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -24,8 +22,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
version: version:
- '1.6' # LTS - '1'
- '1.7' # latest stable - 'nightly'
os: os:
- ubuntu-latest - ubuntu-latest
- windows-latest - windows-latest
@ -33,11 +31,9 @@ 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
@ -55,16 +51,19 @@ 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: | run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV
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
@ -73,17 +72,14 @@ jobs:
# Run tests # Run tests
- name: Run Graphical test - name: Run Graphical test
run: | run: |
$TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true)' $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("StatsPlots"); Pkg.test("StatsPlots");'
$TESTCMD -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("GraphRecipes"); Pkg.test("GraphRecipes")' $TESTCMD -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("GraphRecipes"); Pkg.test("GraphRecipes");'
# Codecov - name: Codecov
- uses: julia-actions/julia-processcoverage@v1 uses: julia-actions/julia-uploadcodecov@latest
if: startsWith(matrix.os,'ubuntu') env:
- uses: codecov/codecov-action@v2 CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
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]')"

View File

@ -1,7 +1,6 @@
name: docs name: docs
on: on:
workflow_dispatch:
push: push:
branches: branches:
- master - master
@ -9,7 +8,7 @@ on:
jobs: jobs:
Build_docs: Build_docs:
runs-on: ubuntu-latest runs-on: ubuntu-18.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
@ -26,9 +25,26 @@ jobs:
${{ runner.os }}-test-${{ env.cache-name }}- ${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test- ${{ runner.os }}-test-
${{ runner.os }}- ${{ runner.os }}-
- name: Build documentation - name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y qt5-default \
ttf-mscorefonts-installer \
poppler-utils \
pdf2svg \
texlive-latex-base \
texlive-binaries \
texlive-pictures \
texlive-latex-extra \
texlive-luatex \
ghostscript-x \
libgconf2-4
sudo fc-cache -vr
- name: build documentation
env: env:
PYTHON: "" PYTHON: ""
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} run: |
run: bash docs/ci_build.sh xvfb-run julia --color=yes --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.add(PackageSpec(name="Plots", rev=split(ENV["GITHUB_REF"], "/", limit=3)[3])); Pkg.instantiate()'
xvfb-run julia --color=yes --project=docs/ -e 'withenv("GITHUB_REPOSITORY" => "JuliaPlots/PlotDocs.jl") do; include("docs/make.jl"); end'

View File

@ -1,54 +0,0 @@
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

View File

@ -1,35 +0,0 @@
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 }}"

View File

@ -3,7 +3,7 @@
"license": "MIT", "license": "MIT",
"creators": [ "creators": [
{ {
"affiliation": "Headlands Technologies", "affiliation": "Elemental Cognition",
"name": "Tom Breloff" "name": "Tom Breloff"
} }
], ],
@ -15,9 +15,8 @@
"type": "ProjectLeader" "type": "ProjectLeader"
}, },
{ {
"affiliation": "GLOBE Institute, University of Copenhagen", "affiliation": "GLOBE Institute",
"name": "Michael Krabbe Borregaard", "name": "Michael Krabbe Borregaard",
"orcid": "0000-0002-8146-8435",
"type": "ProjectLeader" "type": "ProjectLeader"
}, },
{ {
@ -142,8 +141,6 @@
}, },
{ {
"name": "Anshul Singhvi", "name": "Anshul Singhvi",
"affiliation": "Columbia University",
"orcid": "0000-0001-6055-1291",
"type": "Other" "type": "Other"
}, },
{ {
@ -403,7 +400,7 @@
"type": "Other" "type": "Other"
}, },
{ {
"name": "Mosè Giodano", "name": "Moesè Giodano",
"type": "Other" "type": "Other"
}, },
{ {
@ -690,32 +687,10 @@
{ {
"name": "@t-bltg", "name": "@t-bltg",
"type": "Other" "type": "Other"
}, }
{ {
"name": "Fred Callaway", "name": "Fred Callaway",
"type": "Other" "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" "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
## NOTE: this file is deprecated, see the [TagBot](https://github.com/marketplace/actions/julia-tagbot) auto-generated changelogs instead ## (current master)
## 0.28.3 ## 0.28.3
- support generalized array interface - support generalized array interface

View File

@ -1,13 +1,12 @@
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.29.0" version = "1.18.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"
@ -17,7 +16,6 @@ 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"
@ -33,53 +31,39 @@ 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.4" FFMPEG = "0.2, 0.3, 0.4"
FixedPointNumbers = "0.6 - 0.8" FixedPointNumbers = "0.6, 0.7, 0.8"
GR = "0.64" GR = "0.53, 0.54, 0.55, 0.57"
GeometryBasics = "0.2, 0.3.1, 0.4" GeometryBasics = "0.2, 0.3.1"
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, 1" NaNMath = "0.3"
PGFPlotsX = "1" PlotThemes = "2"
PlotThemes = "2, 3"
PlotUtils = "1" PlotUtils = "1"
PlotlyBase = "0.7" RecipesBase = "1"
PlotlyJS = "0.18" RecipesPipeline = "0.3"
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"
UnicodeFun = "0.4" julia = "1.5"
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"
@ -90,4 +74,4 @@ UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"
[targets] [targets]
test = ["Colors", "Distributions", "FileIO", "Gaston", "Gtk", "ImageMagick", "Images", "InspectDR", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PyPlot", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"] test = ["Distributions", "FileIO", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "HDF5", "RDatasets", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "VisualRegressionTests"]

View File

@ -10,18 +10,18 @@
[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]: https://docs.juliaplots.org/stable/ [docs-url]: http://docs.juliaplots.org/latest/
[![][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) [![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. 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)
#### Maintained by the [JuliaPlots members](https://github.com/orgs/JuliaPlots/people) #### Maintained by the [JuliaPlots members](https://github.com/orgs/JuliaPlots/people)

View File

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

View File

@ -1,487 +0,0 @@
# 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

@ -1,282 +0,0 @@
# 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

@ -66,29 +66,22 @@ 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{(:parent,), Tuple{Subplot{GRBackend}}},Type{Subplot},GRBackend}) Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:label, :blank), Tuple{Symbol, Bool}},Type{EmptyLayout}})
Base.precompile(Tuple{Core.kwftype(typeof(Type)),NamedTuple{(:label, :width, :height), Tuple{Symbol, Symbol, Length{:pct, Float64}}},Type{EmptyLayout}})
Base.precompile(Tuple{Core.kwftype(typeof(_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(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, :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, :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, :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,), 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{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{(: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{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, :halign, :valign, :rotation, :color), Tuple{String, Int64, Symbol, Symbol, Float64, RGBA{Float64}}},typeof(font)})
@ -98,18 +91,12 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),UnitRange{Int64},UnitRange{Int64}}) Base.precompile(Tuple{Core.kwftype(typeof(gr_polyline)),NamedTuple{(:arrowside, :arrowstyle), Tuple{Symbol, Symbol}},typeof(gr_polyline),UnitRange{Int64},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(gr_set_font)),NamedTuple{(:halign, :valign, :rotation), Tuple{Symbol, Symbol, Int64}},typeof(gr_set_font),Font,Subplot{GRBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(hline!)),Any,typeof(hline!),Any})
Base.precompile(Tuple{Core.kwftype(typeof(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, Tuple{String, Any, Any, Any}}}}},typeof(plot!)}) 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{(:c, :lw, :label), Tuple{Symbol, Int64, String}},typeof(plot!),Plot{GRBackend},Vector{Int64},Vector{Int64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:layout, :margin), Tuple{GridLayout, AbsoluteLength}},typeof(plot!),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(: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{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{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{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
@ -122,49 +109,39 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),Plot{GRBackend},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),Plot{GRBackend},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),Plot{PlotlyBackend},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:marker, :series_annotations, :seriestype), Tuple{Tuple{Int64, Float64, Symbol}, Vector{Any}, Symbol}},typeof(plot!),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!),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{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!),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{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!)}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:title,), Tuple{String}},typeof(plot!)})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:w,), Tuple{Int64}},typeof(plot!),Plot{GRBackend},Vector{Float64},Vector{Float64},Vararg{Any, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:xgrid,), Tuple{Tuple{Symbol, Symbol, Int64, Symbol, Float64}}},typeof(plot!),Plot{GRBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:xgrid,), Tuple{Tuple{Symbol, Symbol, Int64, Symbol, Float64}}},typeof(plot!),Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:yaxis, :minorgrid), Tuple{Tuple{String, Symbol}, Bool}},typeof(plot!),Plot{PlotlyBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(plot!)),NamedTuple{(:yaxis,), Tuple{Tuple{String, Symbol}}},typeof(plot!)})
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{(: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},Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:bar_width, :alpha, :color, :fillto, :label, :seriestype), Tuple{Float64, Float64, Vector{Symbol}, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, String, Symbol}},typeof(plot),Vector{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:bins, :weights, :seriestype), Tuple{Symbol, Vector{Int64}, Symbol}},typeof(plot),Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(: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, :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{(:connections, :seriestype), Tuple{Tuple{Vector{Int64}, Vector{Int64}, Vector{Int64}}, Symbol}},typeof(plot),Vector{Int64},Vector{Int64},Vector{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:fill, :seriestype), Tuple{Bool, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Function}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:fill, :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, :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, :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{Matrix{Any}, Vector{String}, Matrix{Symbol}, Symbol}},typeof(plot),Vector{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, :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{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, :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, :margin), Tuple{GridLayout, AbsoluteLength}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :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{Matrix{Any}, Matrix{Symbol}, Bool, Nothing, Symbol}},typeof(plot),Matrix{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :t, :leg, :ticks, :border), Tuple{GridLayout, Matrix{Symbol}, Bool, Nothing, Symbol}},typeof(plot),Matrix{Float64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :title, :titlelocation, :left_margin, :bottom_margin, :xrotation), Tuple{Matrix{Any}, 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{GridLayout, 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{Matrix{Any}, Tuple{Int64, Float64}}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout, :xlims), Tuple{GridLayout, Tuple{Int64, Float64}}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:layout,), 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{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{(:layout,), Tuple{Tuple{Int64, Int64}}},typeof(plot),Plot{PlotlyBackend},Plot{PlotlyBackend},Plot{PlotlyBackend}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:legend,), Tuple{Bool}},typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N}) 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})
@ -188,11 +165,8 @@ function _precompile_()
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:projection, :seriestype), Tuple{Symbol, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},UnitRange{Int64},Matrix{Int64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:projection, :seriestype), Tuple{Symbol, Symbol}},typeof(plot),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},UnitRange{Int64},Matrix{Int64}})
Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(:quiver, :seriestype), Tuple{Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}, Symbol}},typeof(plot),Vector{Float64},Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{Core.kwftype(typeof(plot)),NamedTuple{(: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{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),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),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{DateTime},UnitRange{Int64},Matrix{Float64}})
@ -211,23 +185,19 @@ function _precompile_()
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, :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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{OHLC}}) 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},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{: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{: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{: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})
@ -235,26 +205,19 @@ 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.unzip),Vector{GeometryBasics.Point2{Float64}}}) Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{GRBackend},DefaultsDict,Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{GRBackend},Dict{Symbol, Any},Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{PlotlyBackend},DefaultsDict,Symbol,Any})
Base.precompile(Tuple{typeof(RecipesPipeline.warn_on_recipe_aliases!),Plot{PlotlyBackend},Dict{Symbol, Any},Symbol,Any})
Base.precompile(Tuple{typeof(_bin_centers),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) Base.precompile(Tuple{typeof(_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),UnitRange{Int64},Vector{Int64}})
Base.precompile(Tuple{typeof(_cycle),Vector{Float64},StepRange{Int64, 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{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(_plot!),Plot,Any,Any})
Base.precompile(Tuple{typeof(_preprocess_barlike),DefaultsDict,Base.OneTo{Int64},Vector{Float64}}) 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}},Vector{Float64}}) Base.precompile(Tuple{typeof(_preprocess_binlike),DefaultsDict,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64}})
@ -268,67 +231,58 @@ function _precompile_()
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(bottompad),EmptyLayout})
Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}}) Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}})
Base.precompile(Tuple{typeof(convert_to_polar),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Int64, Float64}}) Base.precompile(Tuple{typeof(convert_to_polar),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Int64, Float64}})
Base.precompile(Tuple{typeof(default),Symbol,Bool}) Base.precompile(Tuple{typeof(create_grid),Expr})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64},Vararg{Vector{Float64}, N} where N})
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{typeof(error_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(fakedata),Int64,Int64})
Base.precompile(Tuple{typeof(fakedata),MersenneTwister,Int64,Vararg{Int64, N} where N})
Base.precompile(Tuple{typeof(get_minor_ticks),Subplot{GRBackend},Axis,Tuple{Vector{Float64}, Vector{String}}}) Base.precompile(Tuple{typeof(get_minor_ticks),Subplot{GRBackend},Axis,Tuple{Vector{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{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, Int64, Int64, 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,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,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,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_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,UnitRange{Int64},Vector{Float64},Tuple{Float64, Float64},Int64,Int64})
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_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_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, Int64, Int64, 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_minimum),Vector{Int64}}) Base.precompile(Tuple{typeof(ignorenan_minimum),Vector{Int64}})
Base.precompile(Tuple{typeof(layout_args),NamedTuple{(:label, :blank), Tuple{Symbol, Bool}}}) Base.precompile(Tuple{typeof(layout_args),Int64})
Base.precompile(Tuple{typeof(layout_args),NamedTuple{(:label, :width, :height), Tuple{Symbol, Symbol, Float64}}}) Base.precompile(Tuple{typeof(make_fillrange_side),UnitRange{Int64},StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{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})
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, Float64},Symbol,Symbol})
@ -336,12 +290,10 @@ function _precompile_()
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(partialcircle),Int64,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, N} where N})
Base.precompile(Tuple{typeof(plot),Any,Any}) Base.precompile(Tuple{typeof(plot),Any,Any})
Base.precompile(Tuple{typeof(plot),Any})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N}) Base.precompile(Tuple{typeof(plot),Plot{GRBackend},Plot{GRBackend},Plot{GRBackend},Vararg{Plot{GRBackend}, N} where N})
Base.precompile(Tuple{typeof(plot),Plot{GRBackend},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}, N} where N}) 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(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})
@ -352,52 +304,25 @@ function _precompile_()
Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Shape{Float64, Float64}}) Base.precompile(Tuple{typeof(processMarkerArg),Dict{Symbol, Any},Shape{Float64, Float64}})
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},String,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(push!),Segments{Tuple{Float64, Float64, Float64}},Tuple{Int64, Int64, Float64},Tuple{Int64, Int64, Float64}})
Base.precompile(Tuple{typeof(resetfontsizes)}) 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{RGBA{Float64}},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(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}})
isdefined(Plots, Symbol("#166#167")) && Base.precompile(Tuple{getfield(Plots, Symbol("#166#167")),Any}) Base.precompile(Tuple{typeof(yaxis!),Any,Any})
isdefined(Plots, Symbol("#2#6")) && Base.precompile(Tuple{getfield(Plots, Symbol("#2#6")),UnitRange{Int64}}) isdefined(Plots, Symbol("#add_major_or_minor_segments#126")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#126")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#295#331")) && Base.precompile(Tuple{getfield(Plots, Symbol("#295#331"))}) isdefined(Plots, Symbol("#add_major_or_minor_segments#127")) && Base.precompile(Tuple{getfield(Plots, Symbol("#add_major_or_minor_segments#127")),Vector{Float64},Bool,Segments{Tuple{Float64, Float64, Float64}},Float64,Bool})
isdefined(Plots, Symbol("#316#352")) && Base.precompile(Tuple{getfield(Plots, Symbol("#316#352"))})
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})
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(font, (Font,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody)
precompile(fbody, (Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},typeof(font),Font,Vararg{Any, N} where N,))
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 let fbody = try __lookup_kwbody__(which(plot!, (Any,))) catch missing end
if !ismissing(fbody) if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Any,)) precompile(fbody, (Any,typeof(plot!),Any,))
@ -407,26 +332,6 @@ end
if !ismissing(fbody) if !ismissing(fbody)
precompile(fbody, (Any,typeof(plot!),Any,Vararg{Any, N} where N,)) precompile(fbody, (Any,typeof(plot!),Any,Vararg{Any, N} where N,))
end 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 end
let fbody = try __lookup_kwbody__(which(plot, (Any,))) catch missing end let fbody = try __lookup_kwbody__(which(plot, (Any,))) catch missing end
if !ismissing(fbody) if !ismissing(fbody)
@ -438,9 +343,14 @@ end
precompile(fbody, (Any,typeof(plot),Any,Vararg{Any, N} where N,)) precompile(fbody, (Any,typeof(plot),Any,Vararg{Any, N} where N,))
end end
end end
let fbody = try __lookup_kwbody__(which(scatter, (Any,Vararg{Any, N} where N,))) catch missing end let fbody = try __lookup_kwbody__(which(text, (String,Int64,Vararg{Any, N} where N,))) catch missing end
if !ismissing(fbody) if !ismissing(fbody)
precompile(fbody, (Any,typeof(scatter),Any,Vararg{Any, N} where N,)) 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
end end
let fbody = try __lookup_kwbody__(which(title!, (AbstractString,))) catch missing end let fbody = try __lookup_kwbody__(which(title!, (AbstractString,))) catch missing end

View File

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

View File

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

View File

@ -1,7 +0,0 @@
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,61 +1,35 @@
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 _plots_project = Pkg.Types.read_project(normpath(@__DIR__, "..", "Project.toml")) const _current_plots_version = VersionNumber(split(first(filter(line -> occursin("version", line), readlines(normpath(@__DIR__, "..", "Project.toml")))), "\"")[2])
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, Unzip using Dates, Printf, Statistics, Base64, LinearAlgebra, Random
using SparseArrays using SparseArrays
using FFMPEG using FFMPEG
@reexport using RecipesBase @reexport using RecipesBase
import RecipesBase: plot, plot!, animate, is_explicit, grid import RecipesBase: plot, plot!, animate, is_explicit
using Base.Meta using Base.Meta
@reexport using PlotUtils @reexport using PlotUtils
@reexport using PlotThemes @reexport using PlotThemes
import UnicodeFun
import StatsBase
import Downloads
import Showoff import Showoff
import StatsBase
import JSON import JSON
using Requires using Requires
#! format: off
export export
grid, grid,
bbox, bbox,
plotarea, plotarea,
@layout,
KW, KW,
wrap, wrap,
@ -143,7 +117,8 @@ 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
@ -162,6 +137,7 @@ 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
@ -172,16 +148,13 @@ ignorenan_extrema(x) = Base.extrema(x)
import Measures import Measures
module PlotMeasures module PlotMeasures
import Measures import Measures
import Measures: import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
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)
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value) Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
@ -195,8 +168,7 @@ import .PlotMeasures: Length, AbsoluteLength, Measure, width, height
# --------------------------------------------------------- # ---------------------------------------------------------
import RecipesPipeline import RecipesPipeline
import RecipesPipeline: import RecipesPipeline: SliceIt,
SliceIt,
DefaultsDict, DefaultsDict,
Formatted, Formatted,
AbstractSurface, AbstractSurface,
@ -210,13 +182,14 @@ import RecipesPipeline:
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-2.6.3.min.js" const _plotly_min_js_filename = "plotly-1.57.1.min.js"
include("types.jl") include("types.jl")
include("utils.jl") include("utils.jl")
@ -224,7 +197,6 @@ 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")
@ -260,8 +232,10 @@ let PlotOrSubplot = Union{Plot,Subplot}
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, ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks, labels), kw...) global xticks!(plt::PlotOrSubplot,
global yticks!(plt::PlotOrSubplot, ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (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 xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...) global xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
global ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...) global ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
global annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...) global annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
@ -272,10 +246,10 @@ let PlotOrSubplot = Union{Plot,Subplot}
global yaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; yaxis = 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,7 +14,7 @@ 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))
@ -69,16 +69,12 @@ 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( function buildanimation(anim::Animation, fn::AbstractString,
anim::Animation,
fn::AbstractString,
is_animated_gif::Bool=true; is_animated_gif::Bool=true;
fps::Real = 20, fps::Real = 20, loop::Integer = 0,
loop::Integer = 0,
variable_palette::Bool=false, variable_palette::Bool=false,
verbose=false, verbose=false,
show_msg::Bool = true, 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
@ -86,47 +82,39 @@ function buildanimation(
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 ? 32 : 16) # "error" verbose_level = (verbose isa Int ? verbose :
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( ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -lavfi "$palette" -loop $loop -y $fn`)
`-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( ffmpeg_exe(`-v $verbose_level -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
`-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( ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -loop $loop -y $fn`)
`-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( ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -vf format=yuv420p -loop $loop -y $fn`)
`-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 = html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />"
"<img src=\"data:image/gif;base64," *
base64encode(read(agif.filename)) *
"\" />"
elseif ext in ("mov", "mp4","webm") elseif ext in ("mov", "mp4","webm")
mimetype = ext == "mov" ? "video/quicktime" : "video/$ext" mimetype = ext == "mov" ? "video/quicktime" : "video/$ext"
html = html = "<video controls><source src=\"data:$mimetype;base64," *
"<video controls><source src=\"data:$mimetype;base64," *
base64encode(read(agif.filename)) * base64encode(read(agif.filename)) *
"\" type = \"$mimetype\"></video>" "\" type = \"$mimetype\"></video>"
else else
@ -137,6 +125,7 @@ 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"
@ -144,6 +133,7 @@ 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)
@ -179,12 +169,8 @@ function _animate(forloop::Expr, args...; callgif = false)
error("Unsupported animate filter: $args") error("Unsupported animate filter: $args")
end end
push!(block.args, :( push!(block.args, :(if $filterexpr; Plots.frame($animsym); end))
if $filterexpr push!(block.args, :(global $countersym += 1))
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
@ -193,9 +179,8 @@ function _animate(forloop::Expr, args...; callgif = false)
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
let $countersym = 1 # init iteration counter global $countersym = 1 # init iteration counter
$forloop # for loop, saving a frame after each iteration $forloop # for loop, saving a frame after each iteration
end
$retval # return the animation object, or the gif $retval # return the animation object, or the gif
end) end)
end end

View File

@ -14,26 +14,24 @@ const _arg_desc = KW(
: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).",
:fillstyle => "Symbol. Style of the fill area. `nothing` (the default) means solid fill. Choose from :/, :\\, :|, :-, :+, :x",
:markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.", :markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.",
: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.", :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.",
:markersize => "Number or AbstractVector. Size (radius pixels) of the markers", :markersize => "Number or AbstractVector. Size (radius pixels) of the markers.",
:markerstrokestyle => "Symbol. Style of the marker stroke (border). Choose from $(_allStyles)", :markerstrokestyle => "Symbol. Style of the marker stroke (border). Choose from $(_allStyles)",
:markerstrokewidth => "Number. Width of the marker stroke (border) in pixels", :markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)",
:markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.",
: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.", :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.",
: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)`", :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)`",
:smooth => "Bool. Add a regression line?", :smooth => "Bool. Add a regression line?",
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
:x => "Various. Input data. First Dimension", :x => "Various. Input data. First Dimension",
:y => "Various. Input data. Second Dimension", :y => "Various. Input data. Second Dimension",
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.", :z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
: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.", :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.",
: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).", :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).",
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.", :fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
:levels => "Integer (number of contours) or AbstractVector (contour values). Determines contour levels for a contour type.", :levels => "Integer, NTuple{2,Integer}, or AbstractVector. Levels or number of levels (or x-levels/y-levels) for a contour type.",
:permute => "Tuple{Symbol,Symbol}. Permutes data and axis properties of the axes given in the tuple. E.g. (:x, :y).", :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).",
: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_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)", :bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).", :bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).",
:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?", :bar_edges => "Bool. Align bars to edges (true), or centers (the default)?",
@ -44,7 +42,7 @@ const _arg_desc = KW(
: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.", :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.",
: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).", :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).",
:weights => "AbstractVector. Used in histogram types for weighted counts.", :weights => "AbstractVector. Used in histogram types for weighted counts.",
:show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default)", :show_empty_bins => "Bool. Whether empty bins in a 2D histogram are colored as 0 (true), or transparent (the default).",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:contour_labels => "Bool. Show labels at the contour lines?", :contour_labels => "Bool. Show labels at the contour lines?",
: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`.", :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`.",
@ -53,11 +51,9 @@ const _arg_desc = KW(
: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.", :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.", :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.", :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)", :plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)",
:plot_titlevspan => "Number in [0,1]. Vertical span of the whole plot title (fraction of the plot height)",
:background_color => "Color Type. Base color for all backgrounds.", :background_color => "Color Type. Base color for all backgrounds.",
:background_color_outside => "Color Type or `:match` (matches `:background_color`). Color outside the plot area(s)", :background_color_outside => "Color Type or `:match` (matches `:background_color`). Color outside the plot area(s)",
:foreground_color => "Color Type. Base color for all foregrounds.", :foreground_color => "Color Type. Base color for all foregrounds.",
@ -88,28 +84,26 @@ const _arg_desc = KW(
: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.",
:legend_background_color => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.", :background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).", :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.",
:legend_foreground_color => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.", :foreground_color_legend => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.",
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.", :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_position => "Bool (show the legend?) or (x,y) tuple or Symbol (legend position) or angle or (angle,inout) tuple. Bottom left corner of legend is placed at (x,y). Symbol values: `:none`; `:best`; `:inline`; `:inside`; `:legend`; any valid combination of `:(outer ?)(top/bottom ?)(right/left ?)`, i.e.: `:top`, `:topright`, `:outerleft`, `:outerbottomright` ... (note: only some may be supported in each backend)", :legend => "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_column => "Integer. Number of columns in the legend. `-1` stands for maximum number of colums (horizontal legend).", :legendfontfamily => "String or Symbol. Font family of legend entries.",
:legend_title_font => "Font. Font of the legend title.", :legendfontsize => "Integer. Font pointsize of legend entries.",
:legend_font_family => "String or Symbol. Font family of legend entries.", :legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
:legend_font_pointsize => "Integer. Font pointsize of legend entries.", :legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legend_font_halign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center", :legendfontrotation => "Real. Font rotation of legend entries",
:legend_font_valign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center", :legendfontcolor => "Color Type. Font color of legend entries",
:legend_font_rotation => "Real. Font rotation of legend entries", :legendtitle => "String. Legend title.",
:legend_font_color => "Color Type. Font color of legend entries", :legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
:legend_title => "String. Legend title.", :legendtitlefontsize => "Integer. Font pointsize the legend title.",
:legend_title_font_family => "String or Symbol. Font family of the legend title.", :legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legend_title_font_pointsize => "Integer. Font pointsize the legend title.", :legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
:legend_title_font_halign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center", :legendtitlefontrotation => "Real. Font rotation of the legend title",
:legend_title_font_valign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center", :legendtitlefontcolor => "Color Type. Font color of the legend title",
:legend_title_font_rotation => "Real. Font rotation of the legend title",
:legend_title_font_color => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)", :colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.", :clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.",
:colorbar_fontfamily => "String or Symbol. Font family of colobar entries.", :colorbar_fontfamily => "String or Symbol. Font family of colobar entries.",
@ -119,9 +113,9 @@ const _arg_desc = KW(
:colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries", :colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries",
:colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`", :colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`",
:colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", :colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
:legend_font => "Font. Font of legend items.", :legendfont => "Font. Font of legend items.",
:legend_titlefont => "Font. Font of the legend title.", :legendtitlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String, PlotText (created with `text(args...)`), or a tuple of arguments to `text` (e.g., `(\"Label\", 8, :red, :top)`). Add one-off text annotations at the x,y coordinates.", :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.",
:annotationfontfamily => "String or Symbol. Font family of annotations.", :annotationfontfamily => "String or Symbol. Font family of annotations.",
:annotationfontsize => "Integer. Font pointsize of annotations.", :annotationfontsize => "Integer. Font pointsize of annotations.",
:annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.", :annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.",

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
# 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...)
@ -23,7 +24,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 = get_attr_symbol(letter, :axis) axissym = Symbol(letter, :axis)
if haskey(sp.attr, axissym) if haskey(sp.attr, axissym)
sp.attr[axissym] sp.attr[axissym]
else else
@ -35,45 +36,42 @@ 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[get_attr_symbol(letter, :tickfont)] = arg plotattributes[Symbol(letter,:tickfont)] = arg
plotattributes[get_attr_symbol(letter, :guidefont)] = arg plotattributes[Symbol(letter,:guidefont)] = arg
elseif arg in _allScales elseif arg in _allScales
plotattributes[get_attr_symbol(letter, :scale)] = arg plotattributes[Symbol(letter,:scale)] = arg
elseif arg in (:flip, :invert, :inverted) elseif arg in (:flip, :invert, :inverted)
plotattributes[get_attr_symbol(letter, :flip)] = true plotattributes[Symbol(letter,:flip)] = true
elseif T <: AbstractString elseif T <: AbstractString
plotattributes[get_attr_symbol(letter, :guide)] = arg plotattributes[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[get_attr_symbol(letter, sym)] = arg plotattributes[Symbol(letter,sym)] = arg
# xticks/yticks # xticks/yticks
elseif T <: AVec elseif T <: AVec
plotattributes[get_attr_symbol(letter, :ticks)] = arg plotattributes[Symbol(letter,:ticks)] = arg
elseif arg === nothing elseif arg === nothing
plotattributes[get_attr_symbol(letter, :ticks)] = [] plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs elseif T <: Bool || arg in _allShowaxisArgs
plotattributes[get_attr_symbol(letter, :showaxis)] = showaxis(arg, letter) plotattributes[Symbol(letter,:showaxis)] = showaxis(arg, letter)
elseif typeof(arg) <: Number elseif typeof(arg) <: Number
plotattributes[get_attr_symbol(letter, :rotation)] = arg plotattributes[Symbol(letter,:rotation)] = arg
elseif typeof(arg) <: Function elseif typeof(arg) <: Function
plotattributes[get_attr_symbol(letter, :formatter)] = arg plotattributes[Symbol(letter,:formatter)] = arg
elseif !handleColors!( elseif !handleColors!(plotattributes, arg, Symbol(letter, :foreground_color_axis))
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
@ -124,8 +122,11 @@ 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 = const _label_func = Dict{Symbol,Function}(
Dict{Symbol,Function}(:log10 => x -> "10^$x", :log2 => x -> "2^$x", :ln => x -> "e^$x") :log10 => x -> "10^$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}(
@ -135,6 +136,7 @@ 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
@ -156,8 +158,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 = ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax;
optimize_datetime_ticks(864e5 * amin, 864e5 * amax; k_min = 2, k_max = 4) 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
@ -170,9 +172,8 @@ 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 = scale _logScales ? 2 : 4, # minimum number of ticks k_min = 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(
@ -184,7 +185,6 @@ 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,10 +196,7 @@ 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( map(x -> string("\$", replace(convert_sci_unicode(x), '×' => "\\times"), "\$"), Showoff.showoff(unscaled_ticks, :auto))
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)
@ -224,15 +221,9 @@ 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] = axis.plotattributes[:optimized_ticks] = if ticks isa Symbol && ticks !== :none &&
if ( ispolar(sp) && axis[:letter] === :x && !isempty(dvals)
ticks isa Symbol && collect(0:pi/4:7pi/4), string.(0:45:315)
ticks !== :none &&
ispolar(sp) &&
axis[:letter] === :x &&
!isempty(dvals)
)
collect(0:(pi / 4):(7pi / 4)), string.(0:45:315)
else else
cvals = axis[:continuous_values] cvals = axis[:continuous_values]
alims = axis_limits(sp, axis[:letter]) alims = axis_limits(sp, axis[:letter])
@ -301,10 +292,10 @@ for l in (:x, :y, :z)
end end
end end
# get_ticks from axis symbol :x, :y, or :z # 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(sp::Subplot, s::Symbol) = get_ticks(sp, sp[Symbol(s, :axis)])
get_ticks(p::Plot, s::Symbol) = [get_ticks(sp, s) for sp in p.subplots] 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} 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)
@ -330,64 +321,40 @@ function get_ticks(ticks::Int, dvals, cvals, 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] (:none, nothing, false) && !axis[:minorgrid] && return nothing axis[:minorticks] in (: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])
scale = axis[:scale] #Add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits
log_scaled = scale _logScales if length(ticks) > 2
base = get(_logScaleBases, scale, nothing) ratio = (ticks[3] - ticks[2])/(ticks[2] - ticks[1])
elseif axis[:scale] in (:none, :identity)
# add one phantom tick either side of the ticks to ensure minor ticks extend to the axis limits ratio = 1
if log_scaled
sub = round(Int, log(base, ticks[2] / ticks[1]))
ticks = [ticks[1] / base; ticks; ticks[end] * base]
else else
sub = 1 # unused return nothing
ratio = length(ticks) > 2 ? (ticks[3] - ticks[2]) / (ticks[2] - ticks[1]) : 1 end
first_step = ticks[2] - ticks[1] first_step = ticks[2] - ticks[1]
last_step = ticks[end] - ticks[end-1] last_step = ticks[end] - ticks[end-1]
ticks = [ticks[1] - first_step/ratio; ticks; ticks[end] + last_step*ratio] 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
if log_scaled append!(minorticks,collect(lo + (hi-lo)/n :(hi-lo)/n: hi - (hi-lo)/2n))
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]
@ -395,15 +362,17 @@ end
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
function reset_extrema!(sp::Subplot) function reset_extrema!(sp::Subplot)
for asym in (:x,:y,:z) for asym in (:x,:y,:z)
sp[get_attr_symbol(asym, :axis)][:extrema] = Extrema() sp[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
@ -418,13 +387,14 @@ 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)
@ -432,6 +402,7 @@ 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)
@ -442,22 +413,16 @@ 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 ( if letter != :z && plotattributes[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2]
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[get_attr_symbol(letter, :axis)] axis = sp[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 || elseif eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf))
(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))
@ -467,9 +432,7 @@ 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[letter], plotattributes[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data)
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
@ -503,11 +466,9 @@ function expand_extrema!(sp::Subplot, plotattributes::AKW)
bw = plotattributes[:bar_width] bw = plotattributes[:bar_width]
if bw === nothing if bw === nothing
bw = bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
plotattributes[:bar_width] =
_bar_width * ignorenan_minimum(filter(x -> x > 0, diff(sort(data))))
end end
axis = sp.attr[get_attr_symbol(dsym, :axis)] axis = sp.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
@ -516,8 +477,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[get_attr_symbol(letter, :axis)] axis = sp[Symbol(letter, "axis")]
scale = get(plotattributes, get_attr_symbol(letter, :scale), :identity) scale = get(plotattributes, Symbol(letter, "scale"), :identity)
expand_extrema!(axis, heatmap_edges(data, scale)) expand_extrema!(axis, heatmap_edges(data, scale))
end end
end end
@ -540,28 +501,7 @@ function widen(lmin, lmax, scale = :identity)
end end
# figure out if widening is a good idea. # figure out if widening is a good idea.
const _widen_seriestypes = ( const _widen_seriestypes = (:line, :path, :steppre, :stepmid, :steppost, :sticks, :scatter, :barbins, :barhist, :histogram, :scatterbins, :scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :bar, :shape, :path3d, :scatter3d)
: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)
if axis[:widen] isa Bool if axis[:widen] isa Bool
@ -579,22 +519,16 @@ function default_should_widen(axis::Axis)
false false
end end
function round_limits(amin, amax, scale) function round_limits(amin,amax)
base = get(_logScaleBases, scale, 10.0) scale = 10^(1-round(log10(amax - amin)))
factor = base^(1 - round(log(base, amax - amin))) amin = floor(amin*scale)/scale
amin = floor(amin * factor) / factor amax = ceil(amax*scale)/scale
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( function axis_limits(sp, letter, should_widen = default_should_widen(sp[Symbol(letter, :axis)]), consider_aspect = true)
sp, axis = sp[Symbol(letter, :axis)]
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]
@ -633,17 +567,12 @@ function axis_limits(
elseif should_widen elseif should_widen
widen(amin, amax, axis[:scale]) widen(amin, amax, axis[:scale])
elseif lims == :round elseif lims == :round
round_limits(amin, amax, axis[:scale]) round_limits(amin,amax)
else else
amin, amax amin, amax
end end
if ( if !has_user_lims && consider_aspect && letter in (:x, :y) && !(sp[:aspect_ratio] in (:none, :auto) || RecipesPipeline.is3d(:sp))
!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
@ -675,17 +604,9 @@ 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)
@ -737,10 +658,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 = get_attr_symbol(letter, :axis) asym = Symbol(letter, :axis)
isy = letter === :y isy = letter === :y
oletter = isy ? :x : :y oletter = isy ? :x : :y
oasym = get_attr_symbol(oletter, :axis) oasym = 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]
@ -766,11 +687,7 @@ 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 ( if sp[:framestyle] == :origin && !(ticks in (:none, nothing, false)) && length(ticks) > 1
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)
@ -791,7 +708,6 @@ function axis_drawing_info(sp, letter)
invf = RecipesPipeline.inverse_scale_func(oax[:scale]) invf = RecipesPipeline.inverse_scale_func(oax[:scale])
add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin
ticks === nothing && return
if cond if cond
tick_start, tick_stop = if sp[:framestyle] == :origin tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + factor * (f(oamax) - f(oamin))) t = invf(f(0) + factor * (f(oamax) - f(oamin)))
@ -821,26 +737,12 @@ function axis_drawing_info(sp, letter)
end end
end end
ax_length = letter === :x ? height(sp.plotarea).value : width(sp.plotarea).value
# add major grid segments # add major grid segments
add_major_or_minor_segments( add_major_or_minor_segments(ticks[1], ax[:grid], grid_segments, 0.012, ax[:tick_direction] !== :none)
ticks[1],
ax[:grid],
grid_segments,
1.2 / ax_length,
ax[:tick_direction] !== :none,
)
# add minor grid segments # add minor grid segments
if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid] if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid]
add_major_or_minor_segments( add_major_or_minor_segments(minor_ticks, ax[:minorgrid], minorgrid_segments, 0.006, true)
minor_ticks,
ax[:minorgrid],
minorgrid_segments,
0.6 / ax_length,
true,
)
end end
end end
end end
@ -851,7 +753,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
@ -869,9 +771,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[get_attr_symbol(letter, :axis)] ax = sp[Symbol(letter, :axis)]
nax = sp[get_attr_symbol(near_letter, :axis)] nax = sp[Symbol(near_letter, :axis)]
fax = sp[get_attr_symbol(far_letter, :axis)] fax = sp[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)
@ -887,6 +789,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
@ -907,11 +810,7 @@ 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 ( if sp[:framestyle] == :origin && !(ticks in (:none, nothing, false)) && length(ticks) > 1
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)
@ -931,11 +830,9 @@ function axis_drawing_info_3d(sp, letter)
if ax[:ticks] (: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])
ga0, ga1 = ga0, ga1 = sp[:framestyle] in (:origin, :zerolines) ? (namin, namax) : (na0, na1)
sp[:framestyle] in (:origin, :zerolines) ? (namin, namax) : (na0, na1)
add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin add_major_or_minor_segments(ticks, grid, segments, factor, cond) = begin
ticks === nothing && return
if cond if cond
tick_start, tick_stop = if sp[:framestyle] == :origin tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + factor * (f(namax) - f(namin))) t = invf(f(0) + factor * (f(namax) - f(namin)))
@ -973,23 +870,11 @@ function axis_drawing_info_3d(sp, letter)
end end
# add major grid segments # add major grid segments
add_major_or_minor_segments( add_major_or_minor_segments(ticks[1], ax[:grid], grid_segments, 0.012, ax[:tick_direction] !== :none)
ticks[1],
ax[:grid],
grid_segments,
0.012,
ax[:tick_direction] !== :none,
)
# add minor grid segments # add minor grid segments
if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid] if ax[:minorticks] (:none, nothing, false) || ax[:minorgrid]
add_major_or_minor_segments( add_major_or_minor_segments(minor_ticks, ax[:minorgrid], minorgrid_segments, 0.006, true)
minor_ticks,
ax[:minorgrid],
minorgrid_segments,
0.006,
true,
)
end end
end end
end end
@ -1000,7 +885,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,6 +38,7 @@ 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",
@ -49,7 +50,11 @@ 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(:center => "", :left => "right", :right => "left") const _pgf_annotation_halign = KW(
: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)
@ -58,9 +63,7 @@ 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( @warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.")
"Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead."
)
default_style default_style
end end
end end
@ -123,15 +126,8 @@ 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( cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(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)))
)
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",
@ -142,7 +138,7 @@ 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
@ -150,20 +146,14 @@ 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!( push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text
o, x, y,
PGFPlots.Plots.Node(
val.str, # Annotation Text
x,
y,
style=""" style="""
$(get(_pgf_annotation_halign,val.font.halign,"")), $(get(_pgf_annotation_halign,val.font.halign,"")),
color=$cstr, draw opacity=$(convert(Float16,a)), color=$cstr, draw opacity=$(convert(Float16,a)),
rotate=$(val.font.rotation), rotate=$(val.font.rotation),
font=$(pgf_font(val.font.pointsize, thickness_scaling)) font=$(pgf_font(val.font.pointsize, thickness_scaling))
""", """))
),
)
end end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
@ -227,7 +217,7 @@ function pgf_series(sp::Subplot, series::Series)
end end
# add to legend? # add to legend?
if i == 1 && sp[:legend_position] != :none && should_add_to_legend(series) if i == 1 && sp[:legend] != :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))
@ -251,15 +241,7 @@ function pgf_series(sp::Subplot, series::Series)
# add fillrange # add fillrange
if series[:fillrange] !== nothing && st != :shape if series[:fillrange] !== nothing && st != :shape
push!( push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
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
@ -331,7 +313,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function pgf_axis(sp::Subplot, letter) function pgf_axis(sp::Subplot, letter)
axis = sp[get_attr_symbol(letter, :axis)] axis = sp[Symbol(letter,:axis)]
style = [] style = []
kw = KW() kw = KW()
@ -342,7 +324,7 @@ function pgf_axis(sp::Subplot, letter)
framestyle = pgf_framestyle(sp[:framestyle]) framestyle = pgf_framestyle(sp[:framestyle])
# axis guide # axis guide
kw[get_attr_symbol(letter, :label)] = axis[:guide] kw[Symbol(letter,:label)] = axis[:guide]
# axis label position # axis label position
labelpos = "" labelpos = ""
@ -354,23 +336,7 @@ 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!( push!(style, string(letter, "label style = {", labelpos ,"font = ", pgf_font(axis[:guidefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:guidefontrotation], "}"))
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")
@ -378,7 +344,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[get_attr_symbol(letter, :mode)] = "log" kw[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
@ -397,19 +363,15 @@ function pgf_axis(sp::Subplot, letter)
# limits # limits
# TODO: support zlims # TODO: support zlims
if letter != :z if letter != :z
lims = lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : axis_limits(sp, letter)
ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) : kw[Symbol(letter,:min)] = lims[1]
axis_limits(sp, letter) kw[Symbol(letter,:max)] = lims[2]
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 = tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1]
ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] :
ticks[1]
push!(style, string(letter, "tick = {", join(tick_values,","), "}")) 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 }
@ -419,13 +381,9 @@ 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!( push!(style, string(letter, "ticklabels = {\$", join(tick_labels,"\$,\$"), "\$}"))
style,
string(letter, "ticklabels = {\$", join(tick_labels, "\$,\$"), "\$}"),
)
elseif axis[:showaxis] elseif axis[:showaxis]
tick_labels = tick_labels = ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
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"))
@ -434,44 +392,10 @@ function pgf_axis(sp::Subplot, letter)
else else
push!(style, string(letter, "ticklabels = {}")) push!(style, string(letter, "ticklabels = {}"))
end end
push!( push!(style, string(letter, "tick align = ", (axis[:tick_direction] == :out ? "outside" : "inside")))
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!( push!(style, string(letter, "ticklabel style = {font = ", pgf_font(axis[:tickfontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:tickfontrotation], "}"))
style, push!(style, string(letter, " grid style = {", pgf_linestyle(pgf_thickness_scaling(sp) * axis[:gridlinewidth], axis[:foreground_color_grid], axis[:gridalpha], axis[:gridstyle]), "}"))
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
@ -488,20 +412,7 @@ 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!( push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}}"))
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]
@ -510,19 +421,7 @@ 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!( push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}"))
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
@ -531,6 +430,7 @@ 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
@ -556,66 +456,40 @@ 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!( push!(style, """
style,
"""
xshift = $(left(bb).value)mm, xshift = $(left(bb).value)mm,
yshift = $(round((total_height - (bottom(bb))).value, digits=2))mm, yshift = $(round((total_height - (bottom(bb))).value, digits=2))mm,
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])} 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!( push!(style, string("title style = {font = ", pgf_font(sp[:titlefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", sp[:titlefontrotation], "}"))
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_position] legpos = sp[:legend]
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[:legend_background_color])) cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend]))
fg_alpha = alpha(plot_color(sp[:legend_foreground_color])) fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
push!( push!(style, string(
style,
string(
"legend style = {", "legend style = {",
pgf_linestyle( pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], fg_alpha, "solid", ), ",",
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[:legend_font_color]))),", "text opacity = $(alpha(plot_color(sp[:legendfontcolor]))),",
"font = ", "font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)),
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}"
@ -646,10 +520,7 @@ 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!( push!(style,"colormap={plots}{$(pgf_colormap(series.plotattributes[col]))}")
style,
"colormap={plots}{$(pgf_colormap(series.plotattributes[col]))}",
)
if sp[:colorbar] == :none if sp[:colorbar] == :none
kw[:colorbar] = "false" kw[:colorbar] = "false"
@ -673,25 +544,16 @@ 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!( pgf_add_annotation!(o, xi, yi, PlotText(str, fnt), pgf_thickness_scaling(series))
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!( pgf_add_annotation!(o, locate_annotation(sp, ann...)..., pgf_thickness_scaling(sp))
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
@ -718,11 +580,7 @@ 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( PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone])
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
@ -740,5 +598,3 @@ function _display(plt::Plot{PGFPlotsBackend})
# cleanup # cleanup
PGFPlots.cleanup(plt.o) PGFPlots.cleanup(plt.o)
end end
# COV_EXCL_STOP

View File

@ -1,593 +1,315 @@
# https://github.com/mbaz/Gaston. # https://github.com/mbaz/Gaston.
const G = Gaston
const GastonSubplot = G.Plot
const GASTON_MARKER_SCALING = 1.3 / 5.0
const GNUPLOT_DPI = 72 # Compensate for DPI with increased resolution
should_warn_on_unsupported(::GastonBackend) = false #
# --------------------------------------------
# These functions are called by Plots
# --------------------------------------------
#
# Create the window/figure for this backend. # Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{GastonBackend}) function _create_backend_figure(plt::Plot{GastonBackend})
state_handle = Gaston.nexthandle() # for now all the figures will be kept xsize = plt.attr[:size][1]
plt.o = Gaston.newfigure(state_handle) ysize = plt.attr[:size][2]
G.set(termopts="""size $xsize,$ysize""")
state_handle = G.nexthandle() # for now all the figures will be kept
plt.o = G.newfigure(state_handle)
end end
function _before_layout_calcs(plt::Plot{GastonBackend}) function _before_layout_calcs(plt::Plot{GastonBackend})
# Initialize all the subplots first # Initialize all the subplots first
plt.o.subplots = Gaston.SubPlot[] plt.o.subplots = G.SubPlot[]
grid = size(plt.layout)
plt.o.layout = grid
n1 = n2 = 0
if length(plt.inset_subplots) > 0 for sp in plt.subplots
n1, sps = gaston_get_subplots(0, plt.inset_subplots, plt.layout) gaston_init_subplot(plt, sp)
gaston_init_subplots(plt, sps)
end 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) # Then add the series (curves in gaston)
for series in plt.series_list for series in plt.series_list
gaston_add_series(plt, series) gaston_add_series(plt, series)
end 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 end
function _update_min_padding!(sp::Subplot{GastonBackend}) function _update_min_padding!(sp::Subplot{GastonBackend})
sp.minpad = 0mm, 0mm, 0mm, 0mm sp.minpad = (20mm, 5mm, 2mm, 10mm)
nothing
end end
function _update_plot_object(plt::Plot{GastonBackend}) 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 end
for (mime, term) in ( for (mime, term) in (
"application/eps" => "epscairo", "application/eps" => "epscairo", # NEED fixing TODO
"image/eps" => "epslatex", "image/eps" => "epslatex", # NEED fixing TODO
"application/pdf" => "pdfcairo", "application/pdf" => "pdfcairo", # NEED fixing TODO
"application/postscript" => "postscript", "application/postscript" => "postscript", # NEED fixing TODO
"image/png" => "png",
"image/svg+xml" => "svg", "image/svg+xml" => "svg",
"text/latex" => "tikz", "text/latex" => "tikz", # NEED fixing TODO
"application/x-tex" => "epslatex", "application/x-tex" => "epslatex", # NEED fixing TODO
"text/plain" => "dumb", "text/plain" => "dumb", # NEED fixing TODO
) )
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GastonBackend}) @eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GastonBackend})
term = String($term) xsize = plt.attr[:size][1]
tmpfile = "$(Gaston.tempname()).$term" ysize = plt.attr[:size][2]
termopts="""size $xsize,$ysize"""
Gaston.save( tmpfile = G.tempname() * "." * $term
term = term,
G.save(
term = $term,
output = tmpfile, output = tmpfile,
handle = plt.o.handle, handle = plt.o.handle,
saveopts = gaston_saveopts(plt), saveopts = termopts
) )
while !isfile(tmpfile) while !isfile(tmpfile) end # avoid race condition with read in next line
end # avoid race condition with read in next line write(io, read(tmpfile))
rm(tmpfile, force=true)
nothing
end
end
function _show(io::IO, mime::MIME{Symbol("image/png")},
plt::Plot{GastonBackend},)
scaling = plt.attr[:dpi] / GNUPLOT_DPI
xsize = plt.attr[:size][1] * scaling
ysize = plt.attr[:size][2] * scaling
# Scale all plot elements to match Plots.jl DPI standard
termopts="""size $xsize,$ysize fontscale $scaling lw $scaling dl $scaling ps $scaling"""
tmpfile = G.tempname()
G.save(
term = "pngcairo",
output = tmpfile,
handle = plt.o.handle,
saveopts = termopts
)
while !isfile(tmpfile) end # avoid race condition with read in next line
write(io, read(tmpfile)) write(io, read(tmpfile))
rm(tmpfile, force=true) rm(tmpfile, force=true)
nothing nothing
end end
function _display(plt::Plot{GastonBackend})
display(plt.o)
end end
#
_display(plt::Plot{GastonBackend}) = display(plt.o)
# -------------------------------------------- # --------------------------------------------
# These functions are gaston specific # These functions are gaston specific
# -------------------------------------------- # --------------------------------------------
#
function gaston_init_subplot(plt::Plot{GastonBackend}, sp::Subplot{GastonBackend})
dims = RecipesPipeline.is3d(sp) ? 3 : 2
function gaston_saveopts(plt::Plot{GastonBackend}) axesconf = gaston_parse_axes_args(plt, sp) # Gnuplot string
saveopts = String["size $(join(plt.attr[:size], ","))"] sp.o = GastonSubplot(dims=dims, axesconf = axesconf, curves = [])
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) 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 end
function gaston_add_series(plt::Plot{GastonBackend}, series::Series) function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
# Gaston.Curve = Plots.Series
sp = series[:subplot] sp = series[:subplot]
gsp = sp.o g_sp = sp.o # Gaston subplot object
x, y, z = series[:x], series[:y], series[:z]
seriesconf = gaston_parse_series_args(series) # Gnuplot string
c = G.Curve(series[:x], series[:y], nothing, nothing, seriesconf )
isfirst = length(g_sp.curves) == 0 ? true : false
push!(g_sp.curves, c)
G.write_data(c, g_sp.dims, g_sp.datafile, append = isfirst ? false : true)
end
function gaston_parse_series_args(series::Series)
curveconf = String[]
st = series[:seriestype] st = series[:seriestype]
curves = []
if gsp.dims == 2 && z === nothing if st == :scatter
for (n, seg) in enumerate(series_segments(series, st; check = true)) pt = gaston_marker(series[:markershape])
i, rng = seg.attr_index, seg.range ps = series[:markersize] * GASTON_MARKER_SCALING
fr = _cycle(series[:fillrange], 1:length(x[rng])) lc = gaston_color(series[:markercolor])
for sc in gaston_seriesconf!(sp, series, i, n == 1) # alpha = series[:markeralpha] # TODO merge alpha with rgb color
push!(curves, Gaston.Curve(x[rng], y[rng], nothing, fr, sc)) push!(curveconf, """with points pt $pt ps $ps lc $lc""")
end elseif st == :path
end lc = gaston_color(series[:linecolor])
dt = gaston_linestyle(series[:linestyle])
lw = series[:linewidth]
# alpha = series[:linealpha] # TODO merge alpha with rgb color
if series[:markershape] == :none # simplepath
push!(curveconf, """with lines lc $lc dt $dt lw $lw""")
else else
if z isa Surface pt = gaston_marker(series[:markershape])
z = z.surf ps = series[:markersize] * GASTON_MARKER_SCALING
if st == :image push!(curveconf, """with lp lc $lc dt $dt lw $lw pt $pt ps $ps""")
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 end
elseif st == :shape elseif st == :shape
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i)) fc = gaston_color(series[:fillcolor])
lc, _ = gaston_lc_ls_lw(series, clims, i) fs = "solid"
push!(curveconf, "w filledcurves fc $fc fs solid border lc $lc") lc = gaston_color(series[:linecolor])
elseif st (:steppre, :stepmid, :steppost) push!(curveconf, """with filledcurves fc $fc fs $fs border lc $lc""")
step = if st == :steppre elseif st == :steppre
"fsteps" push!(curveconf, """with steps""")
elseif st == :stepmid
"histeps"
elseif st == :steppost elseif st == :steppost
"steps" push!(curveconf, """with fsteps""") # Not sure if not the other way
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 end
return [join(curveconf, " "), extra...] # label
push!(curveconf, """title "$(series[:label])" """)
return join(curveconf, " ")
end end
function gaston_parse_axes_args( function gaston_parse_axes_args(plt::Plot{GastonBackend}, sp::Subplot{GastonBackend})
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[] axesconf = String[]
# Standard 2d axis
polar = ispolar(sp) && dims == 2 # cannot splot in polar coordinates if !ispolar(sp) && !RecipesPipeline.is3d(sp)
# TODO
# configure grid, axis spines, thickness
end
for letter in (:x, :y, :z) for letter in (:x, :y, :z)
(letter == :z && dims == 2) && continue axis_attr = sp.attr[Symbol(letter, :axis)]
axis = sp.attr[get_attr_symbol(letter, :axis)]
# label names # label names
push!( push!(axesconf, """set $(letter)label "$(axis_attr[:guide])" """)
axesconf, push!(axesconf, """set $(letter)label font "$(axis_attr[:guidefontfamily]), $(axis_attr[:guidefontsize])" """)
"set $(letter)label '$(axis[:guide])' $(gaston_font(guidefont(axis)))",
)
mirror = axis[:mirror] ? "mirror" : "nomirror"
if axis[:scale] == :identity # Handle ticks
logscale, base = "nologscale", "" # ticksyle
elseif axis[:scale] == :log10 push!(axesconf, """set $(letter)tics font "$(axis_attr[:tickfontfamily]), $(axis_attr[:tickfontsize])" """)
logscale, base = "logscale", "10" push!(axesconf, """set $(letter)tics textcolor rgb "#$(hex(axis_attr[:tickfontcolor], :rrggbb))" """)
elseif axis[:scale] == :log2 push!(axesconf, """set $(letter)tics $(axis_attr[:tick_direction])""")
logscale, base = "logscale", "2"
elseif axis[:scale] == :ln
logscale, base = "logscale", "e"
end
push!(axesconf, "set $logscale $letter $base")
# handle ticks mirror = axis_attr[:mirror] ? "mirror" : "nomirror"
if polar push!(axesconf, """set $(letter)tics $(mirror) """)
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 logscale = if axis_attr[:scale] == :identity
if axis[:ticks] != :native "nologscale"
if axis[:flip] elseif axis_attr[:scale] == :log10
hi, lo = axis_limits(sp, letter) "logscale"
else
lo, hi = axis_limits(sp, letter)
end end
push!(axesconf, "set $(letter)range [$lo:$hi]") push!(axesconf, """set $logscale $(letter)""")
ticks = get_ticks(sp, axis) # tick locations
gaston_set_ticks!(axesconf, ticks, letter, "", "") if axis_attr[:ticks] != :native
# axis limits
from, to = axis_limits(sp, letter)
push!(axesconf, """set $(letter)range [$from:$to]""")
if axis[:minorticks] != :native ticks = get_ticks(sp, axis_attr)
minor_ticks = get_minor_ticks(sp, axis, ticks) gaston_set_ticks!(axesconf, ticks, letter)
gaston_set_ticks!(axesconf, minor_ticks, letter, "m", "add")
end
end end
# set title {"<title-text>"} {offset <offset>} {font "<font>{,<size>}"}{{textcolor | tc} {<colorspec> | default}} {{no}enhanced}1
end end
gaston_set_legend!(axesconf, sp) # Set legend params
if axis[:grid] if sp[:title] != nothing
push!(axesconf, "set grid " * (polar ? "polar" : "$(letter)tics")) push!(axesconf, """set title '$(sp[:title])' """)
axis[:minorgrid] && push!(axesconf, """set title font '$(sp[:titlefontfamily]), $(sp[:titlefontsize])' """)
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 end
return join(axesconf, "\n") return join(axesconf, "\n")
end end
function gaston_set_ticks!(axesconf, ticks, letter, maj_min, add) function gaston_set_ticks!(axesconf, ticks, letter)
ticks == :auto && return ticks == :auto && return
if ticks (:none, nothing, false) if ticks == :none || ticks === nothing || ticks == false
push!(axesconf, "unset $(maj_min)$(letter)tics") push!(axesconf, """unset $(letter)tics """)
return return
end end
gaston_ticks = String[] ttype = ticksType(ticks)
if (ttype = ticksType(ticks)) == :ticks if ttype == :ticks
tick_locs = @view ticks[:] tick_locations = @view ticks[:]
for i in eachindex(tick_locs) gaston_tick_string = []
tick = if maj_min == "m" for i in eachindex(tick_locations)
"'' $(tick_locs[i]) 1" # see gnuplot manual 'Mxtics' lac = tick_locations[i]
else push!(gaston_tick_string, "$loc")
"$(tick_locs[i])"
end 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!( push!(
axesconf, axesconf,
"set key " * (occursin("outer", string(leg)) ? "outside" : "inside"), "set $(letter)tics (" * join(gaston_tick_string, ", ") * ")"
) )
for position in ("top", "bottom", "left", "right")
occursin(position, string(leg)) && push!(axesconf, "set key $position") elseif ttype == :ticks_and_labels
tick_locations = @view ticks[1][:]
tick_labels = @view ticks[2][:]
gaston_tick_string = []
for i in eachindex(tick_locations)
loc = tick_locations[i]
lab = gaston_enclose_tick_string(tick_labels[i])
push!(gaston_tick_string, "'$lab' $loc")
end end
push!(axesconf, "set key $(gaston_font(legendfont(sp), rot=false, align=false))") push!(
if sp[:legend_title] !== nothing axesconf,
# NOTE: cannot use legendtitlefont(sp) as it will override legendfont "set $(letter)tics (" * join(gaston_tick_string, ", ") * ")"
push!(axesconf, "set key title '$(sp[:legend_title])'") )
else
error("Invalid input for $(letter)ticks: $ticks")
end end
push!(axesconf, "set key box lw 1 opaque") end
function gaston_set_legend!(axesconf, sp)
leg = sp[:legend]
if !(sp[:legend] in(:none, :inline))
if leg == :best
leg = :topright
end
if occursin("outer", string(leg))
push!(axesconf, "set key outside")
else
push!(axesconf, "set key inside")
end
positions = ["top", "bottom", "left", "right"]
for position in positions
if occursin(position, string(leg))
push!(axesconf, "set key $position")
end
end
if sp[:legendtitle] != nothing
push!(axesconf, "set key title '$(sp[:legendtitle])'")
end
push!(axesconf, "set key box linewidth 1")
push!(axesconf, "set key opaque")
push!(axesconf, "set border back") push!(axesconf, "set border back")
push!(axesconf, """set key font "$(sp[:legendfontfamily]), $(sp[:legendfontsize])" """)
else else
push!(axesconf, "set key off") push!(axesconf, "set key off")
end
nothing
end 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 end
function gaston_palette(gradient) function gaston_marker(marker)
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 == :none && return -1
marker == :pixel && return 0 marker == :circle && return 7
marker (:+, :cross) && return 1 marker == :rect && return 5
marker (:x, :xcross) && return 2 marker == :diamond && return 28
marker == :utriangle && return 9
marker == :dtriangle && return 11
marker == :+ && return 1
marker == :x && return 2
marker == :star5 && return 3 marker == :star5 && return 3
marker == :rect && return filled ? 5 : 4 marker == :pentagon && return 15
marker == :circle && return filled ? 7 : 6 marker == :pixel && return 0
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" @warn("Unsupported marker $marker")
return 1 return 1
end end
function gaston_color(col, alpha = 0) gaston_color(color) = """rgb "#$(hex(color, :rrggbb))" """
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) function gaston_linestyle(style)
style == :solid && return "1" style == :solid && return "1"
@ -598,7 +320,12 @@ function gaston_linestyle(style)
end end
function gaston_enclose_tick_string(tick_string) function gaston_enclose_tick_string(tick_string)
findfirst("^", tick_string) === nothing && return tick_string if findfirst("^", tick_string) == nothing
base, power = split(tick_string, "^") return tick_string
return "$base^{$power}" end
base, power = split(tick_string, "^")
power = string("{", power, "}")
return string(base, "^", power)
end end

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ Read from .hdf5 file using:
display(pread) display(pread)
==# ==#
#==TODO #==TODO
=============================================================================== ===============================================================================
1. Support more features. 1. Support more features.
@ -55,8 +56,7 @@ 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, import ..PlotUtils.ColorPalette, ..PlotUtils.CategoricalColorGradient, ..PlotUtils.ContinuousColorGradient
..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
@ -70,9 +70,10 @@ 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
#== #==
===============================================================================# ===============================================================================#
@ -86,7 +87,8 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1
"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, "CTUPLE" => CplxTuple, #Tuple of complex structures
"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)
@ -113,12 +115,10 @@ 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!( merge!(HDF5PLOT_MAP_TELEM2STR, Dict{Type, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM))
HDF5PLOT_MAP_TELEM2STR,
Dict{Type,String}(v => k for (k, v) in HDF5PLOT_MAP_STR2TELEM),
)
end end
#==Helper functions #==Helper functions
===============================================================================# ===============================================================================#
@ -151,14 +151,15 @@ 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
@ -172,7 +173,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"])
@ -185,8 +186,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) = _read_size_attr(::Type{Array}, grp::Group) = tuple(HDF5.read(HDF5.attributes(grp)["SIZE"])...)
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.)
===============================================================================# ===============================================================================#
@ -229,7 +230,7 @@ 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
@ -237,6 +238,8 @@ 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
===============================================================================# ===============================================================================#
@ -267,7 +270,7 @@ 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)
@ -275,11 +278,12 @@ function _writestructgeneric(grp::Group, obj::T) where {T}
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
@ -295,12 +299,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
@ -343,6 +347,7 @@ 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)
===============================================================================# ===============================================================================#
@ -373,11 +378,7 @@ function _write(grp::Group, plt::Plot{HDF5Backend})
return return
end end
function hdf5plot_write( function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString; name::String="_unnamed")
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))
@ -385,6 +386,7 @@ function hdf5plot_write(
end end
end end
#== _read(): Read data, but not type information. #== _read(): Read data, but not type information.
===============================================================================# ===============================================================================#
@ -415,6 +417,7 @@ 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
===============================================================================# ===============================================================================#
@ -426,7 +429,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))
@ -451,6 +454,7 @@ function _read(::Type{KW}, grp::Group)
return d return d
end end
#== _read(): More complex structures. #== _read(): More complex structures.
===============================================================================# ===============================================================================#
@ -459,9 +463,7 @@ _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 if tuple(0) == sz; return []; end
return []
end
result = Array{Any}(undef, sz) result = Array{Any}(undef, sz)
lidx = LinearIndices(sz) lidx = LinearIndices(sz)
@ -496,9 +498,7 @@ 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( @warn("Cannot yet read DefaultsDict using _read_typed():\n $path\nCannot fully reconstruct plot.")
"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,6 +510,7 @@ 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
===============================================================================# ===============================================================================#
@ -558,8 +559,10 @@ function hdf5plot_read(path::AbstractString; name::String = "_unnamed")
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
===============================================================================# ===============================================================================#
@ -637,8 +640,7 @@ end
#==Interface actually required to use HDF5Backend #==Interface actually required to use HDF5Backend
===============================================================================# ===============================================================================#
hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) = hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) = _hdf5_implementation.hdf5plot_write(plt, path)
_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
@ -64,18 +64,11 @@ 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( fnt = InspectDR.Font(val.font.family, val.font.pointsize,
val.font.family, color =_inspectdr_mapcolor(val.font.color)
val.font.pointsize,
color = _inspectdr_mapcolor(val.font.color),
) )
ann = InspectDR.atext( ann = InspectDR.atext(val.str, x=x, y=y,
texmath2unicode(val.str), font=fnt, angle=val.font.rotation, align=align
x = x,
y = y,
font = fnt,
angle = val.font.rotation,
align = align,
) )
InspectDR.add(plot, ann) InspectDR.add(plot, ann)
return return
@ -91,9 +84,7 @@ 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] pos = ticks[1]; labels = ticks[2]; nticks = length(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
@ -154,8 +145,9 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
#Glyph used when plotting "Shape"s: #Glyph used when plotting "Shape"s:
INSPECTDR_GLYPH_SHAPE = INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline(
InspectDR.GlyphPolyline(2 * InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y) 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}
@ -208,9 +200,7 @@ 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 if nothing == plot; return; end
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
@ -229,9 +219,7 @@ 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 if nothing == plot; return; end
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
@ -242,19 +230,16 @@ 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 Θ = x; r = y
r = y x = r.*cos.(Θ); y = r.*sin.(Θ)
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) nx = length(x); ny = length(y)
ny = length(y)
if nx < ny if nx < ny
series[:x] = Float64[x[mod1(i, nx)] for i in 1:ny] series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
elseif ny > nx elseif ny > nx
series[:y] = Float64[y[mod1(i, ny)] for i in 1:nx] series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end end
#= TODO: Eventually support #= TODO: Eventually support
@ -276,12 +261,11 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
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(style = :solid, width = linewidth, color = linecolor) line = InspectDR.line(
style=:solid, width=linewidth, color=linecolor
)
apline = InspectDR.PolylineAnnotation( apline = InspectDR.PolylineAnnotation(
x[rng], x[rng], y[rng], line=line, fillcolor=fillcolor
y[rng],
line = line,
fillcolor = fillcolor,
) )
InspectDR.add(plot, apline) InspectDR.add(plot, apline)
end end
@ -296,14 +280,11 @@ function _series_added(plt::Plot{InspectDRBackend}, series::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, style=:none, width=linewidth, #linewidth affects glyph
width = linewidth, #linewidth affects glyph
) )
wfrm.glyph = InspectDR.glyph( wfrm.glyph = InspectDR.glyph(
shape = INSPECTDR_GLYPH_SHAPE, shape = INSPECTDR_GLYPH_SHAPE, size = 8,
size = 8, color = linecolor, fillcolor = fillcolor
color = linecolor,
fillcolor = fillcolor,
) )
end end
elseif st in (:path, :scatter, :straightline) #, :steppre, :stepmid, :steppost) elseif st in (:path, :scatter, :straightline) #, :steppre, :stepmid, :steppost)
@ -325,12 +306,8 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
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( color = _inspectdr_mapcolor(plot_color(get_markerstrokecolor(series), get_markerstrokealpha(series))),
plot_color(get_markerstrokecolor(series), get_markerstrokealpha(series)), fillcolor = _inspectdr_mapcolor(plot_color(get_markercolor(series, clims), get_markeralpha(series))),
),
fillcolor = _inspectdr_mapcolor(
plot_color(get_markercolor(series, clims), get_markeralpha(series)),
),
) )
end end
@ -356,8 +333,7 @@ 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] xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
yaxis = sp[:yaxis]
xgrid_show = xaxis[:grid] xgrid_show = xaxis[:grid]
ygrid_show = yaxis[:grid] ygrid_show = yaxis[:grid]
@ -384,9 +360,8 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
_inspectdr_setticks(sp, plot, strip, xaxis, yaxis) _inspectdr_setticks(sp, plot, strip, xaxis, yaxis)
a = plot.annotation a = plot.annotation
a.title = texmath2unicode(sp[:title]) a.title = sp[:title]
a.xlabel = texmath2unicode(xaxis[:guide]) a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]]
a.ylabels = [texmath2unicode(yaxis[:guide])]
#Modify base layout of new object: #Modify base layout of new object:
l = plot.layout.defaults = deepcopy(InspectDR.defaults.plotlayout) l = plot.layout.defaults = deepcopy(InspectDR.defaults.plotlayout)
@ -395,30 +370,27 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
l.frame_canvas.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) 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.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis]) l.frame_data.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l.font_title = InspectDR.Font( l.font_title = InspectDR.Font(sp[:titlefontfamily],
sp[:titlefontfamily],
_inspectdr_mapptsize(sp[:titlefontsize]), _inspectdr_mapptsize(sp[:titlefontsize]),
color = _inspectdr_mapcolor(sp[:titlefontcolor]), color = _inspectdr_mapcolor(sp[:titlefontcolor])
) )
#Cannot independently control fonts of axes with InspectDR: #Cannot independently control fonts of axes with InspectDR:
l.font_axislabel = InspectDR.Font( l.font_axislabel = InspectDR.Font(xaxis[:guidefontfamily],
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_position] != :none) l.enable_legend = (sp[:legend] != :none)
#l.halloc_legend = 150 #TODO: compute??? #l.halloc_legend = 150 #TODO: compute???
l.font_legend = InspectDR.Font( l.font_legend = InspectDR.Font(sp[:legendfontfamily],
sp[:legend_font_family], _inspectdr_mapptsize(sp[:legendfontsize]),
_inspectdr_mapptsize(sp[:legend_font_pointsize]), color = _inspectdr_mapcolor(sp[:legendfontcolor])
color = _inspectdr_mapcolor(sp[:legend_font_color]),
) )
l.frame_legend.fillcolor = _inspectdr_mapcolor(sp[:legend_background_color]) l.frame_legend.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
#_round!() ensures values use integer spacings (looks better on screen): #_round!() ensures values use integer spacings (looks better on screen):
InspectDR._round!(InspectDR.autofit2font!(l, legend_width=10.0)) #10 "em"s wide InspectDR._round!(InspectDR.autofit2font!(l, legend_width=10.0)) #10 "em"s wide
return return
@ -428,9 +400,7 @@ end
# 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 if nothing == mplot; return; end
return
end
mplot.title = plt[:plot_title] mplot.title = plt[:plot_title]
if "" == mplot.title if "" == mplot.title
@ -483,9 +453,7 @@ 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) if !isa(plot, InspectDR.Plot2D); return sp.minpad; end
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.
@ -504,9 +472,7 @@ 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 if nothing == mplot; return; end
return
end
mplot.bblist = InspectDR.BoundingBox[] mplot.bblist = InspectDR.BoundingBox[]
for (i, sp) in enumerate(plt.subplots) for (i, sp) in enumerate(plt.subplots)
@ -520,9 +486,7 @@ function _update_plot_object(plt::Plot{InspectDRBackend})
end end
gplot = _inspectdr_getgui(plt.o) gplot = _inspectdr_getgui(plt.o)
if nothing == gplot if nothing == gplot; return; end
return
end
gplot.src = mplot #Ensure still references current plot gplot.src = mplot #Ensure still references current plot
InspectDR.refresh(gplot) InspectDR.refresh(gplot)
@ -558,9 +522,7 @@ 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 if nothing == mplot; return; end
return
end
gplot = _inspectdr_getgui(plt.o) gplot = _inspectdr_getgui(plt.o)
if nothing == gplot if nothing == gplot

View File

@ -8,11 +8,23 @@ Base.@kwdef mutable struct PGFPlotsXPlot
function PGFPlotsXPlot(is_created, was_shown, the_plot) function PGFPlotsXPlot(is_created, was_shown, the_plot)
pgfx_plot = new(is_created, was_shown, the_plot) pgfx_plot = new(is_created, was_shown, the_plot)
# tikz libraries # tikz libraries
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{arrows.meta}") PGFPlotsX.push_preamble!(
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{backgrounds}") pgfx_plot.the_plot,
"\\usetikzlibrary{arrows.meta}",
)
PGFPlotsX.push_preamble!(
pgfx_plot.the_plot,
"\\usetikzlibrary{backgrounds}",
)
# pgfplots libraries # pgfplots libraries
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{patchplots}") PGFPlotsX.push_preamble!(
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{fillbetween}") pgfx_plot.the_plot,
"\\usepgfplotslibrary{patchplots}",
)
PGFPlotsX.push_preamble!(
pgfx_plot.the_plot,
"\\usepgfplotslibrary{fillbetween}",
)
# compatibility fixes # compatibility fixes
# add background layer to standard layers # add background layer to standard layers
PGFPlotsX.push_preamble!( PGFPlotsX.push_preamble!(
@ -89,9 +101,8 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
extra_plot = wraptuple(extra_plot) extra_plot = wraptuple(extra_plot)
push!(the_plot, extra_plot...) push!(the_plot, extra_plot...)
end end
bgc = bgc = plt.attr[:background_color_outside] == :match ?
plt.attr[:background_color_outside] == :match ? plt.attr[:background_color] : plt.attr[:background_color] : plt.attr[:background_color_outside]
plt.attr[:background_color_outside]
if bgc isa Colors.Colorant if bgc isa Colors.Colorant
cstr = plot_color(bgc) cstr = plot_color(bgc)
a = alpha(cstr) a = alpha(cstr)
@ -107,27 +118,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
end end
for sp in plt.subplots for sp in plt.subplots
bb1 = sp.plotarea
bb2 = bbox(sp) bb2 = bbox(sp)
sp_width = width(bb2)
sp_height = height(bb2)
dx, dy = bb2.x0 dx, dy = bb2.x0
sp_width = width(bb2)
sp_height = height(bb2)
if sp[:subplot_index] == plt[:plot_titleindex]
x = dx + sp_width / 2 - 10mm # FIXME: get rid of magic constant
y = dy + sp_height / 2
pgfx_add_annotation!(
the_plot,
x,
y,
PlotText(plt[:plot_title], plottitlefont(plt)),
pgfx_thickness_scaling(plt);
cs = "",
options = PGFPlotsX.Options("anchor" => "center"),
)
continue
end
sp_width = width(bb2)
sp_height = height(bb2)
lpad = leftpad(sp) + sp[:left_margin] lpad = leftpad(sp) + sp[:left_margin]
rpad = rightpad(sp) + sp[:right_margin] rpad = rightpad(sp) + sp[:right_margin]
tpad = toppad(sp) + sp[:top_margin] tpad = toppad(sp) + sp[:top_margin]
@ -136,35 +131,40 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
dy += tpad dy += tpad
axis_height = sp_height - (tpad + bpad) axis_height = sp_height - (tpad + bpad)
axis_width = sp_width - (rpad + lpad) axis_width = sp_width - (rpad + lpad)
title_cstr = plot_color(sp[:titlefontcolor]) title_cstr = plot_color(sp[:titlefontcolor])
title_a = alpha(title_cstr) title_a = alpha(title_cstr)
title_loc = sp[:titlelocation] title_loc = sp[:titlelocation]
bgc_inside = plot_color(sp[:background_color_inside]) bgc_inside = plot_color(sp[:background_color_inside])
bgc_inside_a = alpha(bgc_inside) bgc_inside_a = alpha(bgc_inside)
update_clims(sp)
axis_opt = PGFPlotsX.Options( axis_opt = PGFPlotsX.Options(
"point meta max" => get_clims(sp)[2], "point meta max" => get_clims(sp)[2],
"point meta min" => get_clims(sp)[1], "point meta min" => get_clims(sp)[1],
"legend cell align" => "left",
"legend columns" => pgfx_legend_col(sp[:legend_column]),
"title" => sp[:title], "title" => sp[:title],
"title style" => PGFPlotsX.Options( "title style" => PGFPlotsX.Options(
pgfx_get_title_pos(title_loc)..., pgfx_get_title_pos(title_loc)...,
"font" => pgfx_font(sp[:titlefontsize], pgfx_thickness_scaling(sp)), "font" => pgfx_font(
sp[:titlefontsize],
pgfx_thickness_scaling(sp),
),
"color" => title_cstr, "color" => title_cstr,
"draw opacity" => title_a, "draw opacity" => title_a,
"rotate" => sp[:titlefontrotation], "rotate" => sp[:titlefontrotation],
), ),
"legend style" => pgfx_get_legend_style(sp), "legend style" => pgfx_get_legend_style(sp),
"axis background/.style" => "axis background/.style" => PGFPlotsX.Options(
PGFPlotsX.Options("fill" => bgc_inside, "opacity" => bgc_inside_a), "fill" => bgc_inside,
"opacity" => bgc_inside_a,
),
# These are for layouting # These are for layouting
"anchor" => "north west", "anchor" => "north west",
"xshift" => string(dx), "xshift" => string(dx),
"yshift" => string(-dy), "yshift" => string(-dy),
) )
sp_width > 0 * mm ? push!(axis_opt, "width" => string(axis_width)) : nothing sp_width > 0 * mm ? push!(axis_opt, "width" => string(axis_width)) :
sp_height > 0 * mm ? push!(axis_opt, "height" => string(axis_height)) : nothing nothing
sp_height > 0 * mm ? push!(axis_opt, "height" => string(axis_height)) :
nothing
for letter in (:x, :y, :z) for letter in (:x, :y, :z)
if letter != :z || RecipesPipeline.is3d(sp) if letter != :z || RecipesPipeline.is3d(sp)
pgfx_axis!(axis_opt, sp, letter) pgfx_axis!(axis_opt, sp, letter)
@ -206,10 +206,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
if hascolorbar(sp) if hascolorbar(sp)
cticks = get_colorbar_ticks(sp)[2] cticks = get_colorbar_ticks(sp)[2]
colorbar_style = PGFPlotsX.Options(
"title" => sp[:colorbar_title],
)
if sp[:colorbar] === :top if sp[:colorbar] === :top
colorbar_style = PGFPlotsX.Options("xlabel" => sp[:colorbar_title]) push!(colorbar_style,
push!(
colorbar_style,
"at" => string((0.5, 1.05)), "at" => string((0.5, 1.05)),
"anchor" => "south", "anchor" => "south",
"xtick" => string("{", join(cticks, ","), "}"), "xtick" => string("{", join(cticks, ","), "}"),
@ -217,9 +218,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
"xticklabel style" => pgfx_get_colorbar_ticklabel_style(sp), "xticklabel style" => pgfx_get_colorbar_ticklabel_style(sp),
) )
else else
colorbar_style = PGFPlotsX.Options("ylabel" => sp[:colorbar_title]) push!(colorbar_style,
push!(
colorbar_style,
"ytick" => string("{", join(cticks, ","), "}"), "ytick" => string("{", join(cticks, ","), "}"),
"yticklabel style" => pgfx_get_colorbar_ticklabel_style(sp), "yticklabel style" => pgfx_get_colorbar_ticklabel_style(sp),
) )
@ -249,18 +248,12 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
extra_sp = wraptuple(extra_sp) extra_sp = wraptuple(extra_sp)
push!(axis, extra_sp...) push!(axis, extra_sp...)
end end
if sp[:legend_title] !== nothing if sp[:legendtitle] !== nothing
legtfont = legendtitlefont(sp)
push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing)) push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing))
push!( push!(
axis, axis,
PGFPlotsX.LegendEntry( PGFPlotsX.LegendEntry(
PGFPlotsX.Options( string("\\hspace{-.6cm}{\\textbf{", sp[:legendtitle], "}}"),
"font" =>
pgfx_font(legtfont.pointsize, pgfx_thickness_scaling(sp)),
"text" => legtfont.color,
),
string("\\hspace{-.6cm}{\\textbf{", sp[:legend_title], "}}"),
false, false,
), ),
) )
@ -276,19 +269,15 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
"color" => single_color(opt[:linecolor]), "color" => single_color(opt[:linecolor]),
"name path" => string(series_id), "name path" => string(series_id),
) )
extra_series, extra_series_opt = extra_series, extra_series_opt = pgfx_split_extra_opts(series[:extra_kwargs])
pgfx_split_extra_opts(series[:extra_kwargs])
series_opt = merge(series_opt, PGFPlotsX.Options(extra_series_opt...)) series_opt = merge(series_opt, PGFPlotsX.Options(extra_series_opt...))
if ( if RecipesPipeline.is3d(series) || st in (:heatmap, :contour) || (st == :quiver && opt[:z] !== nothing)
RecipesPipeline.is3d(series) ||
st in (:heatmap, :contour) ||
(st == :quiver && opt[:z] !== nothing)
)
series_func = PGFPlotsX.Plot3 series_func = PGFPlotsX.Plot3
else else
series_func = PGFPlotsX.Plot series_func = PGFPlotsX.Plot
end end
if sf !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing if sf !== nothing &&
!isfilledcontour(series) && series[:ribbon] === nothing
push!(series_opt, "area legend" => nothing) push!(series_opt, "area legend" => nothing)
end end
pgfx_add_series!(Val(st), axis, series_opt, series, series_func, opt) pgfx_add_series!(Val(st), axis, series_opt, series, series_func, opt)
@ -352,7 +341,10 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
scale_factor = 0.00125 scale_factor = 0.00125
mark_size = opt[:markersize] * scale_factor mark_size = opt[:markersize] * scale_factor
path = join( path = join(
["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], [
"($(x[i] * mark_size), $(y[i] * mark_size))"
for i in eachindex(x)
],
" -- ", " -- ",
) )
c = get_markercolor(series, i) c = get_markercolor(series, i)
@ -370,9 +362,17 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
segment_opt = merge(segment_opt, pgfx_marker(opt, i)) segment_opt = merge(segment_opt, pgfx_marker(opt, i))
end end
# add fillrange # add fillrange
if sf !== nothing && !isfilledcontour(series) if sf !== nothing &&
!isfilledcontour(series)
if sf isa Number || sf isa AVec if sf isa Number || sf isa AVec
pgfx_fillrange_series!(axis, series, series_func, i, _cycle(sf, rng), rng) pgfx_fillrange_series!(
axis,
series,
series_func,
i,
_cycle(sf, rng),
rng,
)
elseif sf isa Tuple && series[:ribbon] !== nothing elseif sf isa Tuple && series[:ribbon] !== nothing
for sfi in sf for sfi in sf
pgfx_fillrange_series!( pgfx_fillrange_series!(
@ -385,9 +385,8 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
) )
end end
end end
if i == 1 && if k == 1 &&
series[:subplot][:legend_position] != :none && series[:subplot][:legend] != :none && pgfx_should_add_to_legend(series)
pgfx_should_add_to_legend(series)
pgfx_filllegend!(series_opt, opt) pgfx_filllegend!(series_opt, opt)
end end
end end
@ -396,22 +395,18 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
if arrow isa Arrow if arrow isa Arrow
arrow_opt = merge( arrow_opt = merge(
segment_opt, segment_opt,
PGFPlotsX.Options( PGFPlotsX.Options("quiver" => PGFPlotsX.Options(
"quiver" => PGFPlotsX.Options(
"u" => "\\thisrow{u}", "u" => "\\thisrow{u}",
"v" => "\\thisrow{v}", "v" => "\\thisrow{v}",
pgfx_arrow(arrow, :head) => nothing, pgfx_arrow(arrow, :head) => nothing,
),
),
) )
if opt[:label] == "" )
push!(arrow_opt, "forget plot" => nothing) )
end
if arrow.side == :head if arrow.side == :head
x_arrow = opt[:x][rng][(end - 1):end] x_arrow = opt[:x][rng][end-1:end]
y_arrow = opt[:y][rng][(end - 1):end] y_arrow = opt[:y][rng][end-1:end]
x_path = opt[:x][rng][1:(end - 1)] x_path = opt[:x][rng][1:end-1]
y_path = opt[:y][rng][1:(end - 1)] y_path = opt[:y][rng][1:end-1]
elseif arrow.side == :tail elseif arrow.side == :tail
x_arrow = opt[:x][rng][2:-1:1] x_arrow = opt[:x][rng][2:-1:1]
y_arrow = opt[:y][rng][2:-1:1] y_arrow = opt[:y][rng][2:-1:1]
@ -420,24 +415,26 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
elseif arrow.side == :both elseif arrow.side == :both
x_arrow = opt[:x][rng][[2,1,end-1,end]] x_arrow = opt[:x][rng][[2,1,end-1,end]]
y_arrow = opt[:y][rng][[2,1,end-1,end]] y_arrow = opt[:y][rng][[2,1,end-1,end]]
x_path = opt[:x][rng][2:(end - 1)] x_path = opt[:x][rng][2:end-1]
y_path = opt[:y][rng][2:(end - 1)] y_path = opt[:y][rng][2:end-1]
end end
coordinates = PGFPlotsX.Table([ coordinates = PGFPlotsX.Table([
:x => x_arrow[1:2:(end - 1)], :x => x_arrow[1:2:end-1],
:y => y_arrow[1:2:(end - 1)], :y => y_arrow[1:2:end-1],
:u => [x_arrow[i] - x_arrow[i-1] for i in 2:2:lastindex(x_arrow)], :u => [x_arrow[i] - x_arrow[i-1] for i in 2:2:lastindex(x_arrow)],
:v => [y_arrow[i] - y_arrow[i-1] for i in 2:2:lastindex(y_arrow)], :v => [y_arrow[i] - y_arrow[i-1] for i in 2:2:lastindex(y_arrow)],
]) ])
arrow_plot = series_func(merge(series_opt, arrow_opt), coordinates) arrow_plot =
push!(series_opt, "forget plot" => nothing) series_func(merge(series_opt, arrow_opt), coordinates)
push!(axis, arrow_plot) push!(axis, arrow_plot)
coordinates = PGFPlotsX.Table(x_path, y_path) coordinates = PGFPlotsX.Table(x_path, y_path)
segment_plot = series_func(merge(series_opt, segment_opt), coordinates) segment_plot =
series_func(merge(series_opt, segment_opt), coordinates)
push!(axis, segment_plot) push!(axis, segment_plot)
else else
coordinates = PGFPlotsX.Table(pgfx_series_arguments(series, opt, rng)...) coordinates = PGFPlotsX.Table(pgfx_series_arguments(series, opt, rng)...)
segment_plot = series_func(merge(series_opt, segment_opt), coordinates) segment_plot =
series_func(merge(series_opt, segment_opt), coordinates)
push!(axis, segment_plot) push!(axis, segment_plot)
end end
# fill between functions # fill between functions
@ -459,10 +456,7 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o
end # for segments end # for segments
# get that last marker # get that last marker
if !isnothing(opt[:y]) && !any(isnan, opt[:y]) && opt[:markershape] isa AVec if !isnothing(opt[:y]) && !any(isnan, opt[:y]) && opt[:markershape] isa AVec
additional_plot = PGFPlotsX.PlotInc( additional_plot = PGFPlotsX.PlotInc(pgfx_marker(opt, length(segments) + 1), PGFPlotsX.Coordinates(tuple((last(opt[:x]), last(opt[:y])))))
pgfx_marker(opt, length(segments) + 1),
PGFPlotsX.Coordinates(tuple((last(opt[:x]), last(opt[:y])))),
)
push!(axis, additional_plot) push!(axis, additional_plot)
end end
end end
@ -499,7 +493,9 @@ function pgfx_add_series!(::Val{:surface}, axis, series_opt, series, series_func
end end
function pgfx_add_series!(::Val{:wireframe}, axis, series_opt, series, series_func, opt) function pgfx_add_series!(::Val{:wireframe}, axis, series_opt, series, series_func, opt)
push!(series_opt, "mesh" => nothing, "mesh/rows" => length(opt[:x])) push!(series_opt, "mesh" => nothing,
"mesh/rows" => length(opt[:x])
)
pgfx_add_series!(axis, series_opt, series, series_func, opt) pgfx_add_series!(axis, series_opt, series, series_func, opt)
end end
@ -524,34 +520,12 @@ function pgfx_add_series!(::Val{:heatmap}, axis, series_opt, series, series_func
end end
function pgfx_add_series!(::Val{:mesh3d}, axis, series_opt, series, series_func, opt) function pgfx_add_series!(::Val{:mesh3d}, axis, series_opt, series, series_func, opt)
if opt[:connections] isa Tuple{Array,Array,Array} ptable = join([ string(i, " ", j, " ", k, "\\\\") for (i, j, k) in zip(opt[:connections]...) ], "\n ")
# 0-based indexing
ptable = join(
[string(i, " ", j, " ", k, "\\\\") for (i, j, k) in zip(opt[:connections]...)],
"\n ",
)
elseif typeof(opt[:connections]) <: AbstractVector{NTuple{3,Int}}
# 1-based indexing
ptable = join(
[
string(i - 1, " ", j - 1, " ", k - 1, "\\\\") for
(i, j, k) in opt[:connections]
],
"\n ",
)
else
throw(
ArgumentError(
"Argument connections has to be either a tuple of three arrays (0-based indexing)
or an AbstractVector{NTuple{3,Int}} (1-based indexing).",
),
)
end
push!( push!(
series_opt, series_opt,
"patch" => nothing, "patch" => nothing,
"table/row sep" => "\\\\", "table/row sep" => "\\\\",
"patch table" => ptable, "patch table" => ptable
) )
pgfx_add_series!(axis, series_opt, series, series_func, opt) pgfx_add_series!(axis, series_opt, series, series_func, opt)
end end
@ -588,8 +562,7 @@ function pgfx_add_series!(::Val{:contour3d}, axis, series_opt, series, series_fu
) )
series_opt = merge( series_opt, pgfx_linestyle(opt) ) series_opt = merge( series_opt, pgfx_linestyle(opt) )
args = pgfx_series_arguments(series, opt) args = pgfx_series_arguments(series, opt)
series_plot = series_plot = series_func(series_opt, PGFPlotsX.Table(Contour.contours(args..., opt[:levels])))
series_func(series_opt, PGFPlotsX.Table(Contour.contours(args..., opt[:levels])))
push!(axis, series_plot) push!(axis, series_plot)
pgfx_add_legend!(axis, series, opt) pgfx_add_legend!(axis, series, opt)
end end
@ -664,7 +637,7 @@ function pgfx_add_series!(::Val{:xsticks}, axis, series_opt, series, series_func
end end
function pgfx_add_legend!(axis, series, opt, i = 1) function pgfx_add_legend!(axis, series, opt, i = 1)
if series[:subplot][:legend_position] != :none if series[:subplot][:legend] != :none
leg_entry = if opt[:label] isa AVec leg_entry = if opt[:label] isa AVec
get(opt[:label], i, "") get(opt[:label], i, "")
elseif opt[:label] isa AbstractString elseif opt[:label] isa AbstractString
@ -687,8 +660,7 @@ function pgfx_add_legend!(axis, series, opt, i = 1)
return nothing return nothing
end end
pgfx_series_arguments(series, opt, range) = pgfx_series_arguments(series, opt, range) = (arg[range] for arg in pgfx_series_arguments(series, opt))
(arg[range] for arg in pgfx_series_arguments(series, opt))
function pgfx_series_arguments(series, opt) function pgfx_series_arguments(series, opt)
st = series[:seriestype] st = series[:seriestype]
return if st in (:contour, :contour3d) return if st in (:contour, :contour3d)
@ -726,7 +698,7 @@ pgfx_get_marker(k) = get(
none = "none", none = "none",
cross = "+", cross = "+",
xcross = "x", xcross = "x",
(+) = "+", + = "+",
x = "x", x = "x",
utriangle = "triangle*", utriangle = "triangle*",
dtriangle = "triangle*", dtriangle = "triangle*",
@ -752,7 +724,7 @@ pgfx_get_xguide_pos(k) = get(
left = "at={(ticklabel* cs:-0.02)}, anchor=east,", left = "at={(ticklabel* cs:-0.02)}, anchor=east,",
), ),
k, k,
"at={(ticklabel cs:0.5)}, anchor=near ticklabel", "at={(ticklabel cs:0.5)}, anchor=near ticklabel"
) )
pgfx_get_yguide_pos(k) = get( pgfx_get_yguide_pos(k) = get(
@ -762,7 +734,7 @@ pgfx_get_yguide_pos(k) = get(
bottom = "at={(ticklabel* cs:-0.02)}, anchor=north,", bottom = "at={(ticklabel* cs:-0.02)}, anchor=north,",
), ),
k, k,
"at={(ticklabel cs:0.5)}, anchor=near ticklabel", "at={(ticklabel cs:0.5)}, anchor=near ticklabel"
) )
pgfx_get_legend_pos(k) = get( pgfx_get_legend_pos(k) = get(
@ -787,17 +759,15 @@ pgfx_get_legend_pos(k) = get(
Symbol(k), Symbol(k),
("at" => string((1.02, 1)), "anchor" => "north west"), ("at" => string((1.02, 1)), "anchor" => "north west"),
) )
pgfx_get_legend_pos(t::Tuple{S,T}) where {S<:Real,T<:Real} = pgfx_get_legend_pos(t::Tuple{S,T}) where {S<:Real,T<:Real} = ("at" => "{$(string(t))}", "anchor" => "north west")
("at" => "{$(string(t))}", "anchor" => "north west") pgfx_get_legend_pos(nt::NamedTuple) = ("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
pgfx_get_legend_pos(nt::NamedTuple) =
("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
pgfx_get_legend_pos(theta::Real) = pgfx_get_legend_pos((theta,:inner)) pgfx_get_legend_pos(theta::Real) = pgfx_get_legend_pos((theta,:inner))
function pgfx_get_legend_pos(v::Tuple{S,Symbol}) where {S<:Real} function pgfx_get_legend_pos(v::Tuple{S,Symbol}) where S <: Real
(s,c) = sincosd(v[1]) (s,c) = sincosd(v[1])
anchors = [ anchors = [
"south west" "south" "south east" "south west" "south" "south east";
"west" "center" "east" "west" "center" "east";
"north west" "north" "north east" "north west" "north" "north east";
] ]
if v[2] === :inner if v[2] === :inner
@ -811,30 +781,27 @@ function pgfx_get_legend_pos(v::Tuple{S,Symbol}) where {S<:Real}
end end
function pgfx_get_legend_style(sp) function pgfx_get_legend_style(sp)
cstr = plot_color(sp[:legend_background_color]) cstr = plot_color(sp[:background_color_legend])
a = alpha(cstr) a = alpha(cstr)
fg_alpha = alpha(plot_color(sp[:legend_foreground_color])) fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
legfont = legendfont(sp) legfont = legendfont(sp)
PGFPlotsX.Options( PGFPlotsX.Options(
pgfx_linestyle( pgfx_linestyle(
pgfx_thickness_scaling(sp), pgfx_thickness_scaling(sp),
sp[:legend_foreground_color], sp[:foreground_color_legend],
fg_alpha, fg_alpha,
"solid", "solid",
) => nothing, ) => nothing,
"fill" => cstr, "fill" => cstr,
"fill opacity" => a, "fill opacity" => a,
"text opacity" => alpha(plot_color(sp[:legend_font_color])), "text opacity" => alpha(plot_color(sp[:legendfontcolor])),
"font" => pgfx_font(sp[:legend_font_pointsize], pgfx_thickness_scaling(sp)), "font" => pgfx_font(
"text" => plot_color(sp[:legend_font_color]), sp[:legendfontsize],
"cells" => PGFPlotsX.Options( pgfx_thickness_scaling(sp),
"anchor" => get(
(left = "west", right = "east", hcenter = "center"),
legfont.halign,
"west",
), ),
), "text" => plot_color(sp[:legendfontcolor]),
pgfx_get_legend_pos(sp[:legend_position])..., "cells" => PGFPlotsX.Options("anchor" => get((left = "west", right = "east", hcenter = "center"), legfont.halign, "west")),
pgfx_get_legend_pos(sp[:legend])...,
) )
end end
@ -842,23 +809,21 @@ pgfx_get_colorbar_pos(s) =
get((left = " left", bottom = " horizontal", top = " horizontal"), s, "") get((left = " left", bottom = " horizontal", top = " horizontal"), s, "")
pgfx_get_colorbar_pos(b::Bool) = "" pgfx_get_colorbar_pos(b::Bool) = ""
pgfx_get_title_pos(s) = get( pgfx_get_title_pos(s) =
( get((
left = ("at" => "{(0,1)}", "anchor" => "south west"), left = ("at" => "{(0,1)}", "anchor" => "south west"),
right = ("at" => "{(1,1)}", "anchor" => "south east"), right = ("at" => "{(1,1)}", "anchor" => "south east"),
), ), s,
s, ("at" => "{(0.5,1)}", "anchor" => "south"))
("at" => "{(0.5,1)}", "anchor" => "south"),
)
pgfx_get_title_pos(t::Tuple) = ("at" => "{$(string(t))}", "anchor" => "south") pgfx_get_title_pos(t::Tuple) = ("at" => "{$(string(t))}", "anchor" => "south")
pgfx_get_title_pos(nt::NamedTuple) = pgfx_get_title_pos(nt::NamedTuple) = ("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
function pgfx_get_ticklabel_style(sp, axis) function pgfx_get_ticklabel_style(sp, axis)
cstr = plot_color(axis[:tickfontcolor]) cstr = plot_color(axis[:tickfontcolor])
return PGFPlotsX.Options( return PGFPlotsX.Options(
"font" => pgfx_font(axis[:tickfontsize], pgfx_thickness_scaling(sp)), "font" => pgfx_font(
"color" => cstr, axis[:tickfontsize], pgfx_thickness_scaling(sp)
), "color" => cstr,
"draw opacity" => alpha(cstr), "draw opacity" => alpha(cstr),
"rotate" => axis[:tickfontrotation], "rotate" => axis[:tickfontrotation],
) )
@ -867,8 +832,9 @@ end
function pgfx_get_colorbar_ticklabel_style(sp) function pgfx_get_colorbar_ticklabel_style(sp)
cstr = plot_color(sp[:colorbar_tickfontcolor]) cstr = plot_color(sp[:colorbar_tickfontcolor])
return PGFPlotsX.Options( return PGFPlotsX.Options(
"font" => pgfx_font(sp[:colorbar_tickfontsize], pgfx_thickness_scaling(sp)), "font" => pgfx_font(
"color" => cstr, sp[:colorbar_tickfontsize], pgfx_thickness_scaling(sp)
), "color" => cstr,
"draw opacity" => alpha(cstr), "draw opacity" => alpha(cstr),
"rotate" => sp[:colorbar_tickfontrotation], "rotate" => sp[:colorbar_tickfontrotation],
) )
@ -912,26 +878,18 @@ function pgfx_colormap(v::Vector{<:Colorant})
end, "\n") end, "\n")
end end
function pgfx_colormap(cg::ColorGradient) function pgfx_colormap(cg::ColorGradient)
join( join(map(1:length(cg)) do i
map(1:length(cg)) do i @sprintf("rgb(%.8f)=(%.8f,%.8f,%.8f)", cg.values[i], red(cg.colors[i]), green(cg.colors[i]), blue(cg.colors[i]))
@sprintf( end, "\n")
"rgb(%.8f)=(%.8f,%.8f,%.8f)",
cg.values[i],
red(cg.colors[i]),
green(cg.colors[i]),
blue(cg.colors[i])
)
end,
"\n",
)
end end
function pgfx_framestyle(style::Symbol) function pgfx_framestyle(style::Symbol)
if style in (:box, :axes, :origin, :zerolines, :grid, :none) if style in (:box, :axes, :origin, :zerolines, :grid, :none)
return style return style
else else
default_style = get((semi = :box,), style, :axes) default_style = get((semi = :box,), style, :axes)
@warn "Framestyle :$style is not (yet) supported by the PGFPlotsX backend. :$default_style was chosen instead." @warn( "Framestyle :$style is not (yet) supported by the PGFPlotsX backend. :$default_style was cosen instead.",)
default_style default_style
end end
end end
@ -960,9 +918,6 @@ function pgfx_linestyle(linewidth::Real, color, α = 1, linestyle = :solid)
) )
end end
pgfx_legend_col(s::Symbol) = s == :horizontal ? -1 : 1
pgfx_legend_col(n) = n
function pgfx_linestyle(plotattributes, i = 1) function pgfx_linestyle(plotattributes, i = 1)
lw = pgfx_thickness_scaling(plotattributes) * get_linewidth(plotattributes, i) lw = pgfx_thickness_scaling(plotattributes) * get_linewidth(plotattributes, i)
lc = single_color(get_linecolor(plotattributes, i)) lc = single_color(get_linecolor(plotattributes, i))
@ -984,7 +939,8 @@ function pgfx_font(fontsize::Nothing, thickness_scaling = 1, font = "\\selectfon
end end
function pgfx_should_add_to_legend(series::Series) function pgfx_should_add_to_legend(series::Series)
series.plotattributes[:primary] && !( series.plotattributes[:primary] &&
!(
series.plotattributes[:seriestype] in ( series.plotattributes[:seriestype] in (
:hexbin, :hexbin,
:bins2d, :bins2d,
@ -1014,8 +970,7 @@ function pgfx_marker(plotattributes, i = 1)
pgfx_thickness_scaling(plotattributes) * pgfx_thickness_scaling(plotattributes) *
0.75 * 0.75 *
_cycle(plotattributes[:markersize], i) _cycle(plotattributes[:markersize], i)
mark_freq = mark_freq = !any(isnan, plotattributes[:y]) && plotattributes[:markershape] isa AVec ?
!any(isnan, plotattributes[:y]) && plotattributes[:markershape] isa AVec ?
length(plotattributes[:markershape]) : 1 length(plotattributes[:markershape]) : 1
return PGFPlotsX.Options( return PGFPlotsX.Options(
"mark" => shape isa Shape ? "PlotsShape$i" : pgfx_get_marker(shape), "mark" => shape isa Shape ? "PlotsShape$i" : pgfx_get_marker(shape),
@ -1039,47 +994,29 @@ function pgfx_marker(plotattributes, i = 1)
else else
0 0
end, end,
pgfx_get_linestyle(_cycle(plotattributes[:markerstrokestyle], i)) => pgfx_get_linestyle(_cycle(plotattributes[:markerstrokestyle], i)) => nothing,
nothing,
), ),
) )
end end
function pgfx_add_annotation!( function pgfx_add_annotation!(o, x, y, val, thickness_scaling = 1)
o,
x,
y,
val,
thickness_scaling = 1;
cs = "axis cs:",
options = PGFPlotsX.Options(),
)
# Construct the style string. # Construct the style string.
cstr = val.font.color cstr = val.font.color
a = alpha(cstr) a = alpha(cstr)
push!( push!(
o, o,
join([ [
"\\node", "\\node",
sprint(
PGFPlotsX.print_tex,
merge(
PGFPlotsX.Options( PGFPlotsX.Options(
get( get((center = "", left = "right", right = "left"), val.font.halign, "") =>
(hcenter = "", left = "right", right = "left"), nothing,
val.font.halign,
"",
) => nothing,
"color" => cstr, "color" => cstr,
"draw opacity" => convert(Float16, a), "draw opacity" => convert(Float16, a),
"rotate" => val.font.rotation, "rotate" => val.font.rotation,
"font" => pgfx_font(val.font.pointsize, thickness_scaling), "font" => pgfx_font(val.font.pointsize, thickness_scaling),
), ),
options, " at (axis cs:$x, $y) {$(val.str)};",
), ],
),
string(" at (", cs, x, ",", y, ") {", val.str, "};"),
]),
) )
end end
@ -1147,10 +1084,12 @@ function pgfx_fillrange_series!(axis, series, series_func, i, fillrange, rng)
push!(fillrange_opt, "mark" => "none") # no markers on fillranges push!(fillrange_opt, "mark" => "none") # no markers on fillranges
push!(fillrange_opt, "forget plot" => nothing) push!(fillrange_opt, "forget plot" => nothing)
opt = series.plotattributes opt = series.plotattributes
args = args = RecipesPipeline.is3d(series) ? (opt[:x][rng], opt[:y][rng], opt[:z][rng]) :
RecipesPipeline.is3d(series) ? (opt[:x][rng], opt[:y][rng], opt[:z][rng]) :
(opt[:x][rng], opt[:y][rng]) (opt[:x][rng], opt[:y][rng])
push!(axis, PGFPlotsX.PlotInc(fillrange_opt, pgfx_fillrange_args(fillrange, args...))) push!(
axis,
PGFPlotsX.PlotInc(fillrange_opt, pgfx_fillrange_args(fillrange, args...)),
)
return axis return axis
end end
@ -1202,24 +1141,16 @@ function pgfx_sanitize_plot!(plt)
if key == :annotations && subplot.attr[:annotations] !== nothing if key == :annotations && subplot.attr[:annotations] !== nothing
old_ann = subplot.attr[key] old_ann = subplot.attr[key]
for i in eachindex(old_ann) for i in eachindex(old_ann)
subplot.attr[key][i] = subplot.attr[key][i] = (old_ann[i][1], old_ann[i][2], pgfx_sanitize_string(old_ann[i][3]))
(old_ann[i][1], old_ann[i][2], pgfx_sanitize_string(old_ann[i][3]))
end end
elseif value isa Union{AbstractString, AbstractVector{<:AbstractString}} elseif value isa Union{AbstractString, AbstractVector{<:AbstractString}}
subplot.attr[key] = pgfx_sanitize_string.(value) subplot.attr[key] = pgfx_sanitize_string.(value)
elseif value isa Axis
for (k, v) in value.plotattributes
if v isa Union{AbstractString,AbstractVector{<:AbstractString}}
value.plotattributes[k] = pgfx_sanitize_string.(v)
end
end
end end
end end
end end
for series in plt.series_list for series in plt.series_list
for (key, value) in series.plotattributes for (key, value) in series.plotattributes
if key == :series_annotations && if key == :series_annotations && series.plotattributes[:series_annotations] !== nothing
series.plotattributes[:series_annotations] !== nothing
old_ann = series.plotattributes[key].strs old_ann = series.plotattributes[key].strs
for i in eachindex(old_ann) for i in eachindex(old_ann)
series.plotattributes[key].strs[i] = pgfx_sanitize_string(old_ann[i]) series.plotattributes[key].strs[i] = pgfx_sanitize_string(old_ann[i])
@ -1231,37 +1162,29 @@ function pgfx_sanitize_plot!(plt)
end end
## ##
end end
function wrap_power_labels(ticks)
# wrap the power part of label with }
tick_labels = similar(ticks)
for (i, label) in enumerate(ticks)
base, power = split(label, "^")
power = string("{", power, "}")
tick_labels[i] = string(base, "^", power)
end
tick_labels
end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
axis = sp[get_attr_symbol(letter, :axis)] axis = sp[Symbol(letter, :axis)]
# turn off scaled ticks # turn off scaled ticks
push!(opt, "scaled $(letter) ticks" => "false", string(letter, :label) => axis[:guide])
tick_color = plot_color(axis[:foreground_color_axis])
push!( push!(
opt, opt,
"$(letter) tick style" => "scaled $(letter) ticks" => "false",
PGFPlotsX.Options("color" => color(tick_color), "opacity" => alpha(tick_color)), string(letter, :label) => axis[:guide],
)
tick_color = plot_color(axis[:foreground_color_axis])
push!(opt,
"$(letter) tick style" => PGFPlotsX.Options(
"color" => color(tick_color),
"opacity" => alpha(tick_color),
),
) )
tick_label_color = plot_color(axis[:tickfontcolor]) tick_label_color = plot_color(axis[:tickfontcolor])
push!( push!(opt,
opt,
"$(letter) tick label style" => PGFPlotsX.Options( "$(letter) tick label style" => PGFPlotsX.Options(
"color" => color(tick_color), "color" => color(tick_color),
"opacity" => alpha(tick_color), "opacity" => alpha(tick_color),
"rotate" => axis[:rotation], "rotate" => axis[:rotation]
), ),
) )
@ -1283,12 +1206,6 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
opt, opt,
string(letter, "label style") => PGFPlotsX.Options( string(letter, "label style") => PGFPlotsX.Options(
labelpos => nothing, labelpos => nothing,
"at" => string(
"{(ticklabel cs:",
get((left = 0, right = 1), axis[:guidefonthalign], 0.5),
")}",
),
"anchor" => "near ticklabel",
"font" => pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)), "font" => pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)),
"color" => cstr, "color" => cstr,
"draw opacity" => α, "draw opacity" => α,
@ -1301,10 +1218,10 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
# scale # scale
scale = axis[:scale] scale = axis[:scale]
is_log_scale = scale in (:ln, :log2, :log10) if scale in (:log2, :ln, :log10)
if is_log_scale
push!(opt, string(letter, :mode) => "log") push!(opt, string(letter, :mode) => "log")
scale == :ln || push!(opt, "log basis $letter" => "$(scale == :log2 ? 2 : 10)") scale == :ln ||
push!(opt, "log basis $letter" => "$(scale == :log2 ? 2 : 10)")
end end
# ticks on or off # ticks on or off
@ -1315,14 +1232,14 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
end end
# grid on or off # grid on or off
push!( if axis[:grid] && framestyle != :none
opt, push!(opt, "$(letter)majorgrids" => "true")
"$(letter)majorgrids" => axis[:grid] && framestyle != :none ? "true" : "false", else
) push!(opt, "$(letter)majorgrids" => "false")
end
# limits # limits
lims = lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) :
ispolar(sp) && letter == :x ? rad2deg.(axis_limits(sp, :x)) :
axis_limits(sp, letter) axis_limits(sp, letter)
push!(opt, string(letter, :min) => lims[1], string(letter, :max) => lims[2]) push!(opt, string(letter, :min) => lims[1], string(letter, :max) => lims[2])
@ -1333,35 +1250,45 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
tick_values = tick_values =
ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] :
ticks[1] ticks[1]
push!(opt, string(letter, "tick") => string("{", join(tick_values, ","), "}")) push!(
if axis[:showaxis] && is_log_scale && axis[:ticks] == :auto opt,
tick_labels = wrap_power_labels(ticks[2]) string(letter, "tick") => string("{", join(tick_values, ","), "}"),
if tick_labels isa Vector{String} )
if axis[:showaxis] &&
axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
# wrap the power part of label with }
tick_labels = Vector{String}(undef, length(ticks[2]))
for (i, label) in enumerate(ticks[2])
base, power = split(label, "^")
power = string("{", power, "}")
tick_labels[i] = string(base, "^", power)
end
push!( push!(
opt, opt,
string(letter, "ticklabels") => string(letter, "ticklabels") =>
string("{\$", join(tick_labels, "\$,\$"), "\$}"), string("{\$", join(tick_labels, "\$,\$"), "\$}"),
) )
elseif tick_labels isa Vector{LaTeXString}
push!(opt, string(letter, "ticklabels") => join(tick_labels))
end
elseif axis[:showaxis] elseif axis[:showaxis]
tick_labels = tick_labels =
ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2] ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] :
is_log_scale && (tick_labels = wrap_power_labels(tick_labels)) ticks[2]
if axis[:formatter] in (:scientific, :auto) && tick_labels isa Vector{String} 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!( push!(
opt, opt,
string(letter, "ticklabels") => string("{", join(tick_labels, ","), "}"), string(letter, "ticklabels") =>
string("{", join(tick_labels, ","), "}"),
) )
else else
push!(opt, string(letter, "ticklabels") => "{}") push!(opt, string(letter, "ticklabels") => "{}")
end end
if axis[:tick_direction] === :none if axis[:tick_direction] === :none
push!(opt, string(letter, "tick style") => "draw=none") push!(
opt,
string(letter, "tick style") => "draw=none",
)
else else
push!( push!(
opt, opt,
@ -1369,7 +1296,9 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
(axis[:tick_direction] == :out ? "outside" : "inside"), (axis[:tick_direction] == :out ? "outside" : "inside"),
) )
end end
push!(opt, string(letter, "ticklabel style") => pgfx_get_ticklabel_style(sp, axis)) push!(
opt, string(letter, "ticklabel style") => pgfx_get_ticklabel_style(sp, axis)
)
push!( push!(
opt, opt,
string(letter, " grid style") => pgfx_linestyle( string(letter, " grid style") => pgfx_linestyle(
@ -1393,8 +1322,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
minor_ticks minor_ticks
push!( push!(
opt, opt,
string("extra ", letter, " ticks") => string("extra ", letter, " ticks") => string("{", join(minor_ticks, ","), "}"),
string("{", join(minor_ticks, ","), "}"),
) )
push!(opt, string("extra ", letter, " tick labels") => "") push!(opt, string("extra ", letter, " tick labels") => "")
push!( push!(
@ -1407,9 +1335,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
axis[:minorgridalpha], axis[:minorgridalpha],
axis[:minorgridstyle], axis[:minorgridstyle],
), ),
"major tick length" => "major tick length" => typeof(axis[:minorticks]) <: Integer && axis[:minorticks] > 1 || axis[:minorticks] ? "0.1cm" : "0"
typeof(axis[:minorticks]) <: Integer && axis[:minorticks] > 1 ||
axis[:minorticks] ? "0.1cm" : "0",
), ),
) )
end end
@ -1465,9 +1391,8 @@ end
# Set the (left, top, right, bottom) minimum padding around the plot area # Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc. # to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PGFPlotsXBackend}) function _update_min_padding!(sp::Subplot{PGFPlotsXBackend})
leg = sp[:legend_position] leg = sp[:legend]
if leg in (:best, :outertopright, :outerright, :outerbottomright) || if leg in (:best, :outertopright, :outerright, :outerbottomright) || (leg isa Tuple && leg[1] >= 1)
(leg isa Tuple && leg[1] >= 1)
sp.minpad = (0mm, 0mm, 5mm, 0mm) sp.minpad = (0mm, 0mm, 5mm, 0mm)
else else
sp.minpad = (0mm, 0mm, 0mm, 0mm) sp.minpad = (0mm, 0mm, 0mm, 0mm)
@ -1487,13 +1412,21 @@ function _update_plot_object(plt::Plot{PGFPlotsXBackend})
end end
for mime in ("application/pdf", "image/svg+xml") for mime in ("application/pdf", "image/svg+xml")
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{PGFPlotsXBackend}) @eval function _show(
io::IO,
mime::MIME{Symbol($mime)},
plt::Plot{PGFPlotsXBackend},
)
plt.o.was_shown = true plt.o.was_shown = true
show(io, mime, plt.o.the_plot) show(io, mime, plt.o.the_plot)
end end
end end
function _show(io::IO, mime::MIME{Symbol("image/png")}, plt::Plot{PGFPlotsXBackend}) function _show(
io::IO,
mime::MIME{Symbol("image/png")},
plt::Plot{PGFPlotsXBackend},
)
plt.o.was_shown = true plt.o.was_shown = true
plt_file = tempname() * ".png" plt_file = tempname() * ".png"
PGFPlotsX.pgfsave(plt_file, plt.o.the_plot; dpi=plt[:dpi]) PGFPlotsX.pgfsave(plt_file, plt.o.the_plot; dpi=plt[:dpi])
@ -1501,7 +1434,11 @@ function _show(io::IO, mime::MIME{Symbol("image/png")}, plt::Plot{PGFPlotsXBacke
rm(plt_file; force = true) rm(plt_file; force = true)
end end
function _show(io::IO, mime::MIME{Symbol("application/x-tex")}, plt::Plot{PGFPlotsXBackend}) function _show(
io::IO,
mime::MIME{Symbol("application/x-tex")},
plt::Plot{PGFPlotsXBackend},
)
plt.o.was_shown = true plt.o.was_shown = true
PGFPlotsX.print_tex( PGFPlotsX.print_tex(
io, io,

View File

@ -7,13 +7,12 @@ 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( @warn("Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was chosen instead.")
"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
@ -38,20 +37,25 @@ function plotly_font(font::Font, color = font.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( merge(plotly_annotation_dict(x, y, ptxt.str; xref=xref, yref=yref), KW(
plotly_annotation_dict(x, y, ptxt.str; xref = xref, yref = yref),
KW(
:font => plotly_font(ptxt.font), :font => plotly_font(ptxt.font),
:xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign, :xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign,
:yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign, :yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign,
:rotation => -ptxt.font.rotation, :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)
@ -114,6 +118,7 @@ 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]
@ -124,6 +129,7 @@ function plotly_domain(sp::Subplot)
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]
@ -131,15 +137,13 @@ function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
:visible => framestyle != :none, :visible => framestyle != :none,
:title => axis[:guide], :title => axis[:guide],
:showgrid => axis[:grid], :showgrid => axis[:grid],
:gridcolor => :gridcolor => rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])),
rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])),
:gridwidth => axis[:gridlinewidth], :gridwidth => axis[:gridlinewidth],
:zeroline => framestyle == :zerolines, :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 => :ticks => axis[:tick_direction] === :out ? "outside" :
axis[:tick_direction] === :out ? "outside" :
axis[:tick_direction] === :in ? "inside" : "", axis[:tick_direction] === :in ? "inside" : "",
:mirror => framestyle == :box, :mirror => framestyle == :box,
:showticklabels => axis[:showaxis], :showticklabels => axis[:showaxis],
@ -162,9 +166,7 @@ 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] = ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
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
@ -193,7 +195,10 @@ 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(:visible => axis[:showaxis], :showline => axis[:grid]) ax = KW(
: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))
@ -234,10 +239,7 @@ function plotly_layout(plt::Plot)
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!( push!(plotattributes_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font)))
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])
@ -246,10 +248,8 @@ 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)")] = plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis])
plotly_polaraxis(sp, sp[:xaxis]) plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis])
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)
@ -286,28 +286,16 @@ function plotly_layout(plt::Plot)
# annotations # annotations
for ann in sp[:annotations] for ann in sp[:annotations]
append!( append!(plotattributes_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")])
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!( push!(plotattributes_out[:annotations], plotly_annotation_dict(
plotattributes_out[:annotations],
plotly_annotation_dict(
xi, xi,
yi, yi,
PlotText(str, fnt); PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)")
xref = "x$(x_idx)",
yref = "y$(y_idx)",
),
) )
end end
end end
@ -337,13 +325,14 @@ function plotly_layout(plt::Plot)
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_position] != :none plotattributes_out[:showlegend] = sp[:legend] != :none
legend_position = plotly_legend_pos(sp[:legend_position]) legend_position = plotly_legend_pos(sp[:legend])
if sp[:legend_position] != :none if sp[:legend] != :none
plotattributes_out[:legend_position] = KW( plotattributes_out[:legend] = KW(
:bgcolor => rgba_string(sp[:legend_background_color]), :bgcolor => rgba_string(sp[:background_color_legend]),
:bordercolor => rgba_string(sp[:legend_foreground_color]), :bordercolor => rgba_string(sp[:foreground_color_legend]),
:borderwidth => 1, :borderwidth => 1,
:traceorder => "normal", :traceorder => "normal",
:xanchor => legend_position.xanchor, :xanchor => legend_position.xanchor,
@ -353,7 +342,7 @@ function plotly_add_legend!(plotattributes_out::KW, sp::Subplot)
: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[:legend_title] === nothing ? "" : string(sp[:legend_title]), :text => sp[:legendtitle] === nothing ? "" : string(sp[:legendtitle]),
:font => plotly_font(legendtitlefont(sp)), :font => plotly_font(legendtitlefont(sp)),
), ),
) )
@ -362,7 +351,6 @@ 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
@ -373,47 +361,33 @@ 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 = [xright, ycenter], xanchor = "right", yanchor = "middle"), right = (coords = [1.0, 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 = [xright, ybot], xanchor = "right", yanchor = "bottom"), bottomright = (coords = [1.0, ybot], xanchor = "right", yanchor = "bottom"),
topright = (coords = [xright, ytop], xanchor = "right", yanchor = "top"), topright = (coords = [1.0, 1.0], xanchor = "right", yanchor = "top"),
topleft = (coords = [xleft, ytop], xanchor = "left", yanchor = "top"), topleft = (coords = [xleft, 1.0], 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 = ( outertopright = (coords = [xouterright, ytop], xanchor = "upper", yanchor = "right"),
coords = [xouterright, ytop], outerbottomleft =(coords = [xouterleft, ybot], xanchor = "lower", yanchor = "left"),
xanchor = "upper", outerbottomright =(coords = [xouterright, ybot], xanchor = "lower", yanchor = "right"),
yanchor = "right", default = (coords = [1.0, 1.0], xanchor = "auto", yanchor = "auto")
),
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 = legend_position = get(plotly_legend_position_mapping, pos, plotly_legend_position_mapping.default)
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} = plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = (coords=v, xanchor="left", yanchor="top")
(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"]
@ -427,17 +401,15 @@ function plotly_legend_pos(v::Tuple{S,Symbol}) where {S<:Real}
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 ( return (coords=legend_pos_from_angle(v[1],rect...), xanchor=xanchor, yanchor=yanchor)
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)
@ -456,12 +428,13 @@ 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]], α))] for [cg.values[vinds[i]], rgba_string(plot_color(color_list(cg)[cinds[i]], α))]
i in eachindex(cinds) for 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",
@ -488,11 +461,12 @@ 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 in eachindex(xs) for i=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
@ -500,7 +474,7 @@ 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][get_attr_symbol(letter, :axis)] axis = series[:subplot][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)
@ -538,9 +512,7 @@ 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( error("Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter")
"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)
@ -581,9 +553,8 @@ function plotly_series(plt::Plot, series::Series)
x, y, z = series[:x], series[:y], series[:z] x, y, z = series[:x], series[:y], series[:z]
end end
x, y, z = ( x, y, z = (plotly_data(series, letter, data)
plotly_data(series, letter, data) for for (letter, data) in zip((:x, :y, :z), (x, y, z))
(letter, data) in zip((:x, :y, :z), (x, y, z))
) )
plotattributes_out[:name] = series[:label] plotattributes_out[:name] = series[:label]
@ -591,8 +562,7 @@ 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 = hasfillrange = st in (:path, :scatter, :scattergl, :straightline) &&
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])
@ -610,44 +580,16 @@ 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] = plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
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[:contours] = KW( plotattributes_out[:ncontours] = series[:levels] + 2
:coloring => filled ? "fill" : "lines", plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
:showlabels => series[:contour_labels] == true, plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
)
# 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)
@ -657,16 +599,13 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:hidesurface] = true plotattributes_out[:hidesurface] = true
wirelines = KW( wirelines = KW(
:show => true, :show => true,
:color => :color => rgba_string(plot_color(series[:linecolor], series[:linealpha])),
rgba_string(plot_color(series[:linecolor], series[:linealpha])),
:highlightwidth => series[:linewidth], :highlightwidth => series[:linewidth],
) )
plotattributes_out[:contours] = plotattributes_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
KW(:x => wirelines, :y => wirelines, :z => wirelines)
plotattributes_out[:showscale] = false plotattributes_out[:showscale] = false
else else
plotattributes_out[:colorscale] = plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
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])
@ -679,40 +618,19 @@ function plotly_series(plt::Plot, series::Series)
if series[:connections] !== nothing if series[:connections] !== nothing
if typeof(series[:connections]) <: Tuple{Array,Array,Array} if typeof(series[:connections]) <: Tuple{Array,Array,Array}
# 0-based indexing
i,j,k = series[:connections] i,j,k = series[:connections]
if !(length(i) == length(j) == length(k)) if !(length(i) == length(j) == length(k))
throw( throw(ArgumentError("Argument connections must consist of equally sized arrays."))
ArgumentError(
"Argument connections must consist of equally sized arrays.",
),
)
end end
plotattributes_out[:i] = i plotattributes_out[:i] = i
plotattributes_out[:j] = j plotattributes_out[:j] = j
plotattributes_out[:k] = k plotattributes_out[:k] = k
elseif typeof(series[:connections]) <: AbstractVector{NTuple{3,Int}}
# 1-based indexing
i, j, k = broadcast(
i -> [inds[i] - 1 for inds in series[:connections]],
(1, 2, 3),
)
plotattributes_out[:i] = i
plotattributes_out[:j] = j
plotattributes_out[:k] = k
else else
throw( throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
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
end end
plotattributes_out[:colorscale] = plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:color] = rgba_string(plot_color(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])
@ -727,39 +645,26 @@ 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 => :symbol => get_plotly_marker(series[:markershape], string(series[:markershape])),
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 => :color => rgba_string.(plot_color.(get_markercolor.(series, inds), get_markeralpha.(series, inds))),
rgba_string.(
plot_color.(
get_markercolor.(series, inds),
get_markeralpha.(series, inds),
),
),
:line => KW( :line => KW(
:color => :color => rgba_string.(plot_color.(get_markerstrokecolor.(series, inds), get_markerstrokealpha.(series, inds))),
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_adjust_hover_label!(plotattributes_out, series[:hover]) plotly_hover!(plotattributes_out, series[:hover])
return [merge(plotattributes_out, series[:extra_kwargs])] return [plotattributes_out]
end end
function plotly_series_shapes(plt::Plot, series::Series, clims) function plotly_series_shapes(plt::Plot, series::Series, clims)
segments = series_segments(series; check=true) segments = series_segments(series; check=true)
plotattributes_outs = [KW() for _ in 1:length(segments)] plotattributes_outs = Vector{KW}(undef, 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]
@ -773,9 +678,8 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
:legendgroup => series[:label], :legendgroup => series[:label],
) )
x, y = ( x, y = (plotly_data(series, letter, data)
plotly_data(series, letter, data) for for (letter, data) in zip((:x, :y), shape_data(series, 100))
(letter, data) in zip((:x, :y), shape_data(series, 100))
) )
for (k, segment) in enumerate(segments) for (k, segment) in enumerate(segments)
@ -783,42 +687,32 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
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_out = merge(plotattributes_base, KW(
plotattributes_base,
KW(
:type => "scatter", :type => "scatter",
:mode => "lines", :mode => "lines",
:x => vcat(x[rng], x[rng[1]]), :x => vcat(x[rng], x[rng[1]]),
:y => vcat(y[rng], y[rng[1]]), :y => vcat(y[rng], y[rng[1]]),
:fill => "tozeroy", :fill => "tozeroy",
:fillcolor => rgba_string( :fillcolor => rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))),
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( :color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))),
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] = k==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_adjust_hover_label!(plotattributes_out, _cycle(series[:hover], i)) plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[k] = merge(plotattributes_out, series[:extra_kwargs]) plotattributes_outs[k] = plotattributes_out
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!( push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
plotattributes_outs,
plotly_colorbar_hack(series, plotattributes_base, :marker),
)
end end
plotattributes_outs plotattributes_outs
end end
@ -829,8 +723,7 @@ 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 = hasfillrange = st in (:path, :scatter, :scattergl, :straightline) &&
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))
@ -853,22 +746,14 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
else else
hasline ? "lines" : "none" hasline ? "lines" : "none"
end end
if series[:fillrange] == true || if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple)
series[:fillrange] == 0 ||
isa(series[:fillrange], Tuple)
plotattributes_out[:fill] = "tozeroy" plotattributes_out[:fill] = "tozeroy"
plotattributes_out[:fillcolor] = rgba_string( plotattributes_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)))
plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
)
elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real} elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real}
plotattributes_out[:fill] = "tonexty" plotattributes_out[:fill] = "tonexty"
plotattributes_out[:fillcolor] = rgba_string( plotattributes_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)))
plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
)
elseif !(series[:fillrange] in (false, nothing)) elseif !(series[:fillrange] in (false, nothing))
@warn( @warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])")
"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]
@ -879,32 +764,20 @@ 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] = plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x[rng], y[rng], z[rng]
x[rng], y[rng], z[rng]
end end
# add "marker" # add "marker"
if hasmarker if hasmarker
mcolor = rgba_string( mcolor = rgba_string(plot_color(get_markercolor(series, clims, i), get_markeralpha(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)))
)
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( :symbol => get_plotly_marker(_cycle(series[:markershape], i), string(_cycle(series[:markershape], i))),
_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 => :color => needs_scatter_fix ? [lcolor, "rgba(0, 0, 0, 0.000)"] : lcolor,
needs_scatter_fix ? [lcolor, "rgba(0, 0, 0, 0.000)"] : lcolor,
:width => _cycle(series[:markerstrokewidth], i), :width => _cycle(series[:markerstrokewidth], i),
), ),
) )
@ -913,9 +786,7 @@ 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( :color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))),
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"
@ -931,7 +802,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_adjust_hover_label!(plotattributes_out, _cycle(series[:hover], rng)) plotly_hover!(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
@ -940,15 +811,11 @@ 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
plotattributes_out[:fillrange] = fill(series[:fillrange], length(rng)) series[:fillrange] = fill(series[:fillrange], length(rng))
elseif typeof(series[:fillrange]) <: Tuple elseif typeof(series[:fillrange]) <: Tuple
f1 = f1 = typeof(series[:fillrange][1]) <: Real ? fill(series[:fillrange][1], length(rng)) : series[:fillrange][1][rng]
typeof(series[:fillrange][1]) <: Real ? f2 = typeof(series[:fillrange][2]) <: Real ? fill(series[:fillrange][2], length(rng)) : series[:fillrange][2][rng]
fill(series[:fillrange][1], length(rng)) : series[:fillrange][1][rng] series[:fillrange] = (f1, f2)
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]
@ -957,19 +824,16 @@ 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] = plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] = concatenate_fillrange(x[rng], series[:fillrange])
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_outs[(2k-1):(2k)] = [plotattributes_out_fillrange, plotattributes_out]
[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
@ -977,10 +841,7 @@ 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!( push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
plotattributes_outs,
plotly_colorbar_hack(series, plotattributes_base, :marker),
)
end end
plotattributes_outs plotattributes_outs
@ -1010,34 +871,33 @@ 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[:theta] = rad2deg.(theta) plotattributes_out[:t] = rad2deg.(theta)
plotattributes_out[:r] = r plotattributes_out[:r] = r
plotattributes_out[:type] = :scatterpolar
end end
end end
function plotly_adjust_hover_label!(plotattributes_out::KW, hover) function plotly_hover!(plotattributes_out::KW, hover)
if hover === nothing # hover text
return nothing if hover === nothing || all(in([:none, false]), hover)
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)
if isempty(plt.series_list) slist = []
return KW[] for series in plt.series_list
append!(slist, plotly_series(plt, series))
end end
reduce(vcat, plotly_series(plt, series) for series in plt.series_list) slist
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
@ -1050,15 +910,11 @@ 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[]) : use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) : "https://cdn.plot.ly/$(_plotly_min_js_filename)"
"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 = 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"
include_mathjax != "cdn" ? ("file://" * include_mathjax) : mathjax_head = include_mathjax == "" ? "" : "<script src=\"$mathjax_file\"></script>\n\t\t"
"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
@ -1078,9 +934,8 @@ 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[]) : use_local_dependencies[] ? ("file:///" * plotly_local_file_path[]) : "https://cdn.plot.ly/$(_plotly_min_js_filename)"
"https://cdn.plot.ly/$(_plotly_min_js_filename)" plotly_no_ext = plotly_no_ext[1:end-3]
plotly_no_ext = plotly_no_ext[1:(end - 3)]
requirejs_prefix = """ requirejs_prefix = """
requirejs.config({ requirejs.config({
@ -1107,12 +962,16 @@ end
function js_body(plt::Plot, uuid) function js_body(plt::Plot, uuid)
js = """ js = """
Plotly.newPlot('$(uuid)', $(plotly_series_json(plt)), $(plotly_layout_json(plt))); var PLOT = document.getElementById('$(uuid)');
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 = plotly_series(plot) data = []
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
@ -1125,10 +984,12 @@ 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, embeddable_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,7 +8,6 @@ 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...)
@ -26,19 +25,16 @@ 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}) = @eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
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}) = _show(io::IO, mime::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) = plotly_show_js(io, plt)
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}) = _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, embeddable_html(plt))
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,373 +1,180 @@
# https://github.com/JuliaPlots/UnicodePlots.jl
const _canvas_map = ( # https://github.com/Evizero/UnicodePlots.jl
# don't warn on unsupported... there's just too many warnings!!
warn_on_unsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
# --------------------------------------------------------------------------------------
function _canvas_map()
(
braille = UnicodePlots.BrailleCanvas, braille = UnicodePlots.BrailleCanvas,
density = UnicodePlots.DensityCanvas,
heatmap = UnicodePlots.HeatmapCanvas,
lookup = UnicodePlots.LookupCanvas,
ascii = UnicodePlots.AsciiCanvas, ascii = UnicodePlots.AsciiCanvas,
block = UnicodePlots.BlockCanvas, block = UnicodePlots.BlockCanvas,
dot = UnicodePlots.DotCanvas, dot = UnicodePlots.DotCanvas,
density = UnicodePlots.DensityCanvas,
) )
end
should_warn_on_unsupported(::UnicodePlotsBackend) = false
function _before_layout_calcs(plt::Plot{UnicodePlotsBackend}) # do all the magic here... build it all at once, since we need to know about all the series at the very beginning
plt.o = UnicodePlots.Plot[] function rebuildUnicodePlot!(plt::Plot, width, height)
up_width = UnicodePlots.DEFAULT_WIDTH[] plt.o = []
up_height = UnicodePlots.DEFAULT_HEIGHT[]
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 = collect(axis_limits(sp, :x)) xlim = axis_limits(sp, :x)
ylim = collect(axis_limits(sp, :y)) ylim = axis_limits(sp, :y)
zlim = collect(axis_limits(sp, :z))
F = float(eltype(xlim))
# We set x/y to have a single point, # make vectors
# since we need to create the plot with some data. xlim = [xlim[1], xlim[2]]
# Since this point is at the bottom left corner of the plot, ylim = [ylim[1], ylim[2]]
# it should be hidden by consecutive plotting commands.
x = Vector{F}(xlim)
y = Vector{F}(ylim)
z = Vector{F}(zlim)
# create a plot window with xlim/ylim set, # we set x/y to have a single point, since we need to create the plot with some data.
# but the X/Y vectors are outside the bounds # since this point is at the bottom left corner of the plot, it shouldn't actually be shown
canvas = if (up_c = get(sp_kw, :canvas, :auto)) === :auto x = Float64[xlim[1]]
isijulia() ? :ascii : :braille y = Float64[ylim[1]]
# 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
up_c _canvas_map()[ct]
end end
border = if (up_b = get(sp_kw, :border, :auto)) === :auto # special handling for spy
isijulia() ? :ascii : :solid if length(sp.series_list) == 1
else series = sp.series_list[1]
up_b if series[:seriestype] == :spy
end push!(plt.o, UnicodePlots.spy(
series[:z].surf,
# blank plots will not be shown
width = has_layout && isempty(series_list(sp)) ? 0 : get(sp_kw, :width, up_width)
height = get(sp_kw, :height, up_height)
plot_3d = is3d(sp)
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
grid &= !(quiver || contour)
blend &= !(quiver || contour)
plot_3d && (xlim = ylim = (0, 0)) # determined using projection
azimuth, elevation = sp[:camera] # PyPlot: azimuth = -60 & elevation = 30
projection = plot_3d ? get(sp_kw, :projection, :orthographic) : nothing
kw = (
compact = true,
title = texmath2unicode(sp[:title]),
xlabel = texmath2unicode(xaxis[:guide]),
ylabel = texmath2unicode(yaxis[:guide]),
grid = grid,
blend = blend,
height = height,
width = width, width = width,
xscale = xaxis[:scale], height = height,
yscale = yaxis[:scale], title = sp[:title],
border = border, canvas = canvas_type
))
continue
end
end
# # make it a bar canvas if plotting bar
# if any(series -> series[:seriestype] == :bar, series_list(sp))
# canvas_type = UnicodePlots.BarplotGraphics
# end
o = UnicodePlots.Plot(x, y, canvas_type;
width = width,
height = height,
title = sp[:title],
xlim = xlim, xlim = xlim,
ylim = ylim, ylim = ylim,
# 3d border = isijulia() ? :ascii : :solid
projection = projection,
elevation = elevation,
azimuth = azimuth,
zoom = get(sp_kw, :zoom, 1),
up = get(sp_kw, :up, :z),
) )
o = UnicodePlots.Plot(x, y, plot_3d ? z : nothing, _canvas_map[canvas]; kw...) # set the axis labels
for series in series_list(sp) UnicodePlots.xlabel!(o, xaxis[:guide])
o = addUnicodeSeries!( UnicodePlots.ylabel!(o, yaxis[:guide])
sp,
o,
kw,
series,
sp[:legend_position] !== :none,
plot_3d,
)
end
for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...)
o = UnicodePlots.annotate!(
o,
x,
y,
texmath2unicode(val.str);
color = up_color(val.font.color),
halign = val.font.halign,
valign = val.font.valign,
)
end
push!(plt.o, o) # save the object
end
end
up_color(col::UnicodePlots.UserColorType) = col
up_color(col::RGBA) =
(c = convert(ARGB32, col); map(Int, (red(c).i, green(c).i, blue(c).i)))
up_color(col) = :auto
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
function addUnicodeSeries!(
sp::Subplot{UnicodePlotsBackend},
up::UnicodePlots.Plot,
kw,
series,
addlegend::Bool,
plot_3d::Bool,
)
st = series[:seriestype]
se_kw = series[:extra_kwargs]
# get the series data and label
x, y = if st === :straightline
straightline_data(series)
elseif st === :shape
shape_data(series)
else
series[:x], series[:y]
end
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 # now use the ! functions to add to the plot
if st in (:path, :path3d, :straightline, :shape, :mesh3d) for series in series_list(sp)
addUnicodeSeries!(o, series.plotattributes, sp[:legend] != :none, xlim, ylim)
end
# save the object
push!(plt.o, o)
end
end
# add a single series
function addUnicodeSeries!(o, plotattributes, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
st = plotattributes[:seriestype]
if st == :histogram2d
UnicodePlots.densityplot!(o, plotattributes[:x], plotattributes[:y])
return
end
if st in (:path, :straightline)
func = UnicodePlots.lineplot! func = UnicodePlots.lineplot!
series_kw = (; head_tail = series[:arrow] isa Arrow ? series[:arrow].side : nothing) elseif st == :scatter || plotattributes[:markershape] != :none
elseif st in (:scatter, :scatter3d) || series[:markershape] !== :none
func = UnicodePlots.scatterplot! func = UnicodePlots.scatterplot!
series_kw = (; marker = series[:markershape]) # elseif st == :bar
# func = UnicodePlots.barplot!
elseif st == :shape
func = UnicodePlots.lineplot!
else else
error("Plots(UnicodePlots): series type $st not supported") error("Linestyle $st not supported by UnicodePlots")
end end
label = addlegend ? series[:label] : "" # get the series data and label
x, y = if st == :straightline
for (n, segment) in enumerate(series_segments(series, st; check = true)) straightline_data(plotattributes)
i, rng = segment.attr_index, segment.range elseif st == :shape
lc = get_linecolor(series, i) shape_data(plotattributes)
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
# ------------------------------------------------------------------------------------------
function _show(io::IO, ::MIME"image/png", plt::Plot{UnicodePlotsBackend})
prepare_output(plt)
nr, nc = size(plt.layout)
s1 = zeros(Int, nr, nc)
s2 = zeros(Int, nr, nc)
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 else
img = UnicodePlots.png_image(plt.o[sps += 1]) [collect(float(plotattributes[s])) for s in (:x, :y)]
canvas_type = eltype(img)
h, w = size(img)
s1[r, c] = h
s2[r, c] = w
push!(imgs, img)
end end
end label = addlegend ? plotattributes[:label] : ""
end
if canvas_type !== nothing # if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
m1 = maximum(s1; dims = 2) color = plotattributes[:linecolor] in UnicodePlots.color_cycle ? plotattributes[:linecolor] : :auto
m2 = maximum(s2; dims = 1)
img = zeros(canvas_type, sum(m1), sum(m2)) # add the series
sps = 0 x, y = RecipesPipeline.unzip(collect(Base.Iterators.filter(xy->isfinite(xy[1])&&isfinite(xy[2]), zip(x,y))))
n1 = 1 func(o, x, y; color = color, name = label)
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)
# 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
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
end
# -------------------------------
# we don't do very much for subplots... just stack them vertically
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend})
w, h = plt[:size]
plt.attr[:color_palette] = [RGB(0,0,0)]
rebuildUnicodePlot!(plt, div(w, 10), div(h, 20))
end
# 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})
prepare_output(plt) unicodeplots_rebuild(plt)
nr, nc = size(plt.layout) foreach(x -> show(io, x), plt.o)
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})
show(stdout, plt) unicodeplots_rebuild(plt)
println(stdout) map(show, plt.o)
nothing
end end

View File

@ -3,10 +3,7 @@
# 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( function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl"))
plt::AbstractPlot;
title::AbstractString = get(plt.attr, :window_title, "Plots.jl"),
)
""" """
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -52,8 +49,7 @@ 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[] = use_local_dependencies[] = plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[])
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
@ -62,9 +58,7 @@ 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( run(`wkhtmltoimage -f png -q --width $w --height $h --disable-smart-width $html_fn $png_fn`)
`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,60 +1,47 @@
# 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}) = process_clims(lims::Tuple{<:Number,<:Number}) = (zlims -> ifelse.(isfinite.(lims), lims, zlims)) ignorenan_extrema
(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
get_clims(sp::Subplot)::Tuple{Float64,Float64} = function get_clims(sp::Subplot, op=process_clims(sp[:clims]))
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]::Bool if series[:colorbar_entry]
zmin, zmax = _update_clims(zmin, zmax, update_clims(series, op)...) zmin, zmax = _update_clims(zmin, zmax, get_clims(series, op)...)
end
end
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
function get_clims(sp::Subplot, series::Series, op=process_clims(sp[:clims]))
zmin, zmax = if series[:colorbar_entry]
get_clims(sp, op)
else else
update_clims(series, op) get_clims(series, op)
end end
end return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
return sp[:clims_calculated] = zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end end
""" """
update_clims(::Series, op=Plots.ignorenan_extrema) get_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. The value is stored as a series property, which is retrieved by `get_clims`. values of the input.
""" """
function update_clims(series::Series, op = ignorenan_extrema)::Tuple{Float64,Float64} function get_clims(series::Series, op=ignorenan_extrema)
zmin, zmax = Inf, -Inf zmin, zmax = Inf, -Inf
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface, :hexbin)
# keeping this unrolled has higher performance for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
if series[:seriestype] _z_colored_series && series[:z] !== nothing if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real})
zmin, zmax = update_clims(zmin, zmax, series[:z], op) zmin, zmax = _update_clims(zmin, zmax, op(vals.surf)...)
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
zmin, zmax = _update_clims(zmin, zmax, op(vals)...)
end end
if series[:line_z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:line_z], op)
end end
if series[:marker_z] !== nothing return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
zmin, zmax = update_clims(zmin, zmax, series[:marker_z], op)
end end
if series[:fill_z] !== nothing
zmin, zmax = update_clims(zmin, zmax, series[:fill_z], op)
end
return series[:clims_calculated] = zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
end
update_clims(zmin, zmax, vals::AbstractSurface, op)::Tuple{Float64,Float64} =
update_clims(zmin, zmax, vals.surf, op)
update_clims(zmin, zmax, vals::Any, op)::Tuple{Float64,Float64} =
_update_clims(zmin, zmax, op(vals)...)
update_clims(zmin, zmax, ::Nothing, ::Any)::Tuple{Float64,Float64} = zmin, zmax
_update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax) _update_clims(zmin, zmax, emin, emax) = NaNMath.min(zmin, emin), NaNMath.max(zmax, emax)
@ -74,7 +61,7 @@ function colorbar_style(series::Series)
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 in [:marker_z, :line_z, :fill_z]) any(series[z] !== nothing for z [:marker_z,:line_z,:fill_z])
cbar_gradient cbar_gradient
else else
nothing nothing
@ -82,8 +69,7 @@ function colorbar_style(series::Series)
end end
hascolorbar(series::Series) = colorbar_style(series) !== nothing hascolorbar(series::Series) = colorbar_style(series) !== nothing
hascolorbar(sp::Subplot) = hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
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)
@ -101,5 +87,4 @@ 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

View File

@ -1,13 +1,10 @@
const P2 = GeometryBasics.Point2{Float64} const P2 = GeometryBasics.Point2{Float64}
const P3 = GeometryBasics.Point3{Float64} const P3 = GeometryBasics.Point3{Float64}
const _haligns = :hcenter, :left, :right nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
const _valigns = :vcenter, :top, :bottom nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
nanpush!(a::AbstractVector{P3}, b) = (push!(a, P3(NaN,NaN,NaN)); push!(a, b))
nanpush!(a::AVec{P2}, b) = (push!(a, P2(NaN, NaN)); push!(a, b)) nanappend!(a::AbstractVector{P3}, b) = (push!(a, P3(NaN,NaN,NaN)); append!(a, b))
nanappend!(a::AVec{P2}, b) = (push!(a, P2(NaN, NaN)); append!(a, b))
nanpush!(a::AVec{P3}, b) = (push!(a, P3(NaN, NaN, NaN)); push!(a, b))
nanappend!(a::AVec{P3}, b) = (push!(a, P3(NaN, NaN, NaN)); append!(a, b))
compute_angle(v::P2) = (angle = atan(v[2], v[1]); angle < 0 ? 2π - angle : angle) compute_angle(v::P2) = (angle = atan(v[2], v[1]); angle < 0 ? 2π - angle : angle)
# ------------------------------------------------------------- # -------------------------------------------------------------
@ -41,13 +38,22 @@ vertices(shape::Shape) = collect(zip(shape.x, shape.y))
@deprecate shape_coords coords @deprecate shape_coords coords
"return the vertex points from a Shape or Segments object" "return the vertex points from a Shape or Segments object"
coords(shape::Shape) = shape.x, shape.y function coords(shape::Shape)
shape.x, shape.y
end
coords(shapes::AVec{<:Shape}) = unzip(map(coords, shapes)) #coords(shapes::AVec{Shape}) = unzip(map(coords, shapes))
function coords(shapes::AVec{<:Shape})
c = map(coords, shapes)
x = [q[1] for q in c]
y = [q[2] for q in c]
x, y
end
"get an array of tuples of points on a circle with radius `r`" "get an array of tuples of points on a circle with radius `r`"
partialcircle(start_θ, end_θ, n = 20, r = 1) = function partialcircle(start_θ, end_θ, n = 20, r=1)
[(r*cos(u), r*sin(u)) for u in range(start_θ, stop=end_θ, length=n)] [(r*cos(u), r*sin(u)) for u in range(start_θ, stop=end_θ, length=n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)" "interleave 2 vectors into each other (like a zipper's teeth)"
function weave(x,y; ordering = Vector[x,y]) function weave(x,y; ordering = Vector[x,y])
@ -75,33 +81,27 @@ function makestar(n; offset = -0.5, radius = 1.0)
end end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle" "create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
makeshape(n; offset = -0.5, radius = 1.0) = function makeshape(n; offset = -0.5, radius = 1.0)
Shape(partialcircle(offset * π, offset * π + 2π, n + 1, radius)) z = offset * π
Shape(partialcircle(z, z + 2π, n+1, radius))
end
function makecross(; offset = -0.5, radius = 1.0) function makecross(; offset = -0.5, radius = 1.0)
z2 = offset * π z2 = offset * π
z1 = z2 - π/8 z1 = z2 - π/8
outercircle = partialcircle(z1, z1 + 2π, 9, radius) outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius) innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius)
Shape( Shape(weave(outercircle, innercircle,
weave( ordering=Vector[outercircle,innercircle,outercircle]))
outercircle,
innercircle,
ordering = Vector[outercircle, innercircle, outercircle],
),
)
end end
from_polar(angle, dist) = P2(dist*cos(angle), dist*sin(angle)) from_polar(angle, dist) = P2(dist*cos(angle), dist*sin(angle))
makearrowhead(angle; h = 2.0, w = 0.4, tip = from_polar(angle, h)) = Shape( function makearrowhead(angle; h = 2.0, w = 0.4)
P2[ tip = from_polar(angle, h)
(0, 0), Shape(P2[(0,0), from_polar(angle - 0.5π, w) - tip,
from_polar(angle - 0.5π, w) - tip, from_polar(angle + 0.5π, w) - tip, (0,0)])
from_polar(angle + 0.5π, w) - tip, end
(0, 0),
],
)
const _shapes = KW( const _shapes = KW(
:circle => makeshape(20), :circle => makeshape(20),
@ -121,7 +121,7 @@ const _shapes = KW(
:hline => Shape([(1,0),(-1,0)]), :hline => Shape([(1,0),(-1,0)]),
) )
for n in 4:8 for n in [4,5,6,7,8]
_shapes[Symbol("star$n")] = makestar(n) _shapes[Symbol("star$n")] = makestar(n)
end end
@ -129,18 +129,19 @@ Shape(k::Symbol) = deepcopy(_shapes[k])
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# uses the centroid calculation from https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon # uses the centroid calculation from https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
"return the centroid of a Shape" "return the centroid of a Shape"
function center(shape::Shape) function center(shape::Shape)
x, y = coords(shape) x, y = coords(shape)
n = length(x) n = length(x)
A, Cx, Cy = 0, 0, 0 A, Cx, Cy = 0.0, 0.0, 0.0
for i in 1:n for i=1:n
ip1 = i==n ? 1 : i+1 ip1 = i==n ? 1 : i+1
A += x[i] * y[ip1] - x[ip1] * y[i] A += x[i] * y[ip1] - x[ip1] * y[i]
end end
A *= 0.5 A *= 0.5
for i in 1:n for i=1:n
ip1 = i==n ? 1 : i+1 ip1 = i==n ? 1 : i+1
m = (x[i] * y[ip1] - x[ip1] * y[i]) m = (x[i] * y[ip1] - x[ip1] * y[i])
Cx += (x[i] + x[ip1]) * m Cx += (x[i] + x[ip1]) * m
@ -152,52 +153,52 @@ end
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape)) function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = coords(shape) sx, sy = coords(shape)
cx, cy = c cx, cy = c
for i in eachindex(sx) for i=eachindex(sx)
sx[i] = (sx[i] - cx) * x + cx sx[i] = (sx[i] - cx) * x + cx
sy[i] = (sy[i] - cy) * y + cy sy[i] = (sy[i] - cy) * y + cy
end end
shape shape
end end
""" function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
scale(shape, x, y = x, c = center(shape)) shapecopy = deepcopy(shape)
scale!(shape, x, y = x, c = center(shape)) scale!(shapecopy, x, y, c)
end
Scale shape by a factor.
"""
scale(shape::Shape, x::Real, y::Real = x, c = center(shape)) =
scale!(deepcopy(shape), x, y, c)
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x) function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape) sx, sy = coords(shape)
for i in eachindex(sx) for i=eachindex(sx)
sx[i] += x sx[i] += x
sy[i] += y sy[i] += y
end end
shape shape
end end
""" function translate(shape::Shape, x::Real, y::Real = x)
translate(shape, x, y = x) shapecopy = deepcopy(shape)
translate!(shape, x, y = x) translate!(shapecopy, x, y)
end
Translate a Shape in space. function rotate_x(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
""" (x - centerx) * cos(Θ) - (y - centery) * sin(Θ) + centerx
translate(shape::Shape, x::Real, y::Real = x) = translate!(deepcopy(shape), x, y) end
rotate_x(x::Real, y::Real, θ::Real, centerx::Real, centery::Real) = function rotate_y(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
((x - centerx) * cos(θ) - (y - centery) * sin(θ) + centerx) (y - centery) * cos(Θ) + (x - centerx) * sin(Θ) + centery
end
rotate_y(x::Real, y::Real, θ::Real, centerx::Real, centery::Real) = function rotate(x::Real, y::Real, θ::Real, c = center(shape))
((y - centery) * cos(θ) + (x - centerx) * sin(θ) + centery) cx, cy = c
rotate_x(x, y, Θ, cx, cy), rotate_y(x, y, Θ, cx, cy)
end
rotate(x::Real, y::Real, θ::Real, c) = (rotate_x(x, y, θ, c...), rotate_y(x, y, θ, c...)) function rotate!(shape::Shape, Θ::Real, c = center(shape))
function rotate!(shape::Shape, θ::Real, c = center(shape))
x, y = coords(shape) x, y = coords(shape)
for i in eachindex(x) cx, cy = c
xi = rotate_x(x[i], y[i], θ, c...) for i=eachindex(x)
yi = rotate_y(x[i], y[i], θ, c...) xi = rotate_x(x[i], y[i], Θ, cx, cy)
yi = rotate_y(x[i], y[i], Θ, cx, cy)
x[i], y[i] = xi, yi x[i], y[i] = xi, yi
end end
shape shape
@ -206,13 +207,15 @@ end
"rotate an object in space" "rotate an object in space"
function rotate(shape::Shape, θ::Real, c = center(shape)) function rotate(shape::Shape, θ::Real, c = center(shape))
x, y = coords(shape) x, y = coords(shape)
x_new = rotate_x.(x, y, θ, c...) cx, cy = c
y_new = rotate_y.(x, y, θ, c...) x_new = rotate_x.(x, y, θ, cx, cy)
y_new = rotate_y.(x, y, θ, cx, cy)
Shape(x_new, y_new) Shape(x_new, y_new)
end end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
mutable struct Font mutable struct Font
family::AbstractString family::AbstractString
pointsize::Int pointsize::Int
@ -240,17 +243,17 @@ julia> font(family="serif", halign=:center, rotation=45.0)
``` ```
""" """
function font(args...;kw...) function font(args...;kw...)
# defaults # defaults
family = "sans-serif" family = "sans-serif"
pointsize = 14 pointsize = 14
halign = :hcenter halign = :hcenter
valign = :vcenter valign = :vcenter
rotation = 0 rotation = 0.0
color = colorant"black" color = colorant"black"
for arg in args for arg in args
T = typeof(arg) T = typeof(arg)
@assert arg !== :match
if T == Font if T == Font
family = arg.family family = arg.family
@ -262,9 +265,9 @@ function font(args...; kw...)
elseif arg == :center elseif arg == :center
halign = :hcenter halign = :hcenter
valign = :vcenter valign = :vcenter
elseif arg _haligns elseif arg in (:hcenter, :left, :right)
halign = arg halign = arg
elseif arg _valigns elseif arg in (:vcenter, :top, :bottom)
valign = arg valign = arg
elseif T <: Colorant elseif T <: Colorant
color = arg color = arg
@ -274,34 +277,38 @@ function font(args...; kw...)
catch catch
family = string(arg) family = string(arg)
end end
elseif T <: Integer elseif typeof(arg) <: Integer
pointsize = arg pointsize = arg
elseif T <: Real elseif typeof(arg) <: Real
rotation = convert(Float64, arg) rotation = convert(Float64, arg)
else else
@warn "Unused font arg: $arg ($T)" @warn("Unused font arg: $arg ($(typeof(arg)))")
end end
end end
for sym in keys(kw) for symbol in keys(kw)
if sym == :family if symbol == :family
family = string(kw[sym]) family = string(kw[:family])
elseif sym == :pointsize elseif symbol == :pointsize
pointsize = kw[sym] pointsize = kw[:pointsize]
elseif sym == :halign elseif symbol == :halign
halign = kw[sym] halign = kw[:halign]
halign == :center && (halign = :hcenter) if halign == :center
@assert halign _haligns halign = :hcenter
elseif sym == :valign end
valign = kw[sym] @assert halign in (:hcenter, :left, :right)
valign == :center && (valign = :vcenter) elseif symbol == :valign
@assert valign _valigns valign = kw[:valign]
elseif sym == :rotation if valign == :center
rotation = kw[sym] valign = :vcenter
elseif sym == :color end
color = parse(Colorant, kw[sym]) @assert valign in (:vcenter, :top, :bottom)
elseif symbol == :rotation
rotation = kw[:rotation]
elseif symbol == :color
color = parse(Colorant, kw[:color])
else else
@warn "Unused font kwarg: $sym" @warn("Unused font kwarg: $symbol")
end end
end end
@ -320,13 +327,13 @@ end
Scales all **current** font sizes by `factor`. For example `scalefontsizes(1.1)` increases all current font sizes by 10%. To reset to initial sizes, use `scalefontsizes()` Scales all **current** font sizes by `factor`. For example `scalefontsizes(1.1)` increases all current font sizes by 10%. To reset to initial sizes, use `scalefontsizes()`
""" """
function scalefontsizes(factor::Number) function scalefontsizes(factor::Number)
for k in keys(merge(_initial_plt_fontsizes, _initial_sp_fontsizes)) for k in (:titlefontsize, :legendfontsize, :legendtitlefontsize)
scalefontsize(k, factor) scalefontsize(k, factor)
end end
for letter in (:x,:y,:z) for letter in (:x,:y,:z)
for k in keys(_initial_ax_fontsizes) for k in (:guidefontsize, :tickfontsize)
scalefontsize(get_attr_symbol(letter, k), factor) scalefontsize(Symbol(letter, k), factor)
end end
end end
end end
@ -337,7 +344,7 @@ end
Resets font sizes to initial default values. Resets font sizes to initial default values.
""" """
function scalefontsizes() function scalefontsizes()
for k in keys(merge(_initial_plt_fontsizes, _initial_sp_fontsizes)) for k in (:titlefontsize, :legendfontsize, :legendtitlefontsize)
f = default(k) f = default(k)
if k in keys(_initial_fontsizes) if k in keys(_initial_fontsizes)
factor = f / _initial_fontsizes[k] factor = f / _initial_fontsizes[k]
@ -346,11 +353,11 @@ function scalefontsizes()
end end
for letter in (:x,:y,:z) for letter in (:x,:y,:z)
for k in keys(_initial_ax_fontsizes) for k in (:guidefontsize, :tickfontsize)
if k in keys(_initial_fontsizes) if k in keys(_initial_fontsizes)
f = default(get_attr_symbol(letter, k)) f = default(Symbol(letter, k))
factor = f / _initial_fontsizes[k] factor = f / _initial_fontsizes[k]
scalefontsize(get_attr_symbol(letter, k), 1.0 / factor) scalefontsize(Symbol(letter, k), 1.0/factor)
end end
end end
end end
@ -374,12 +381,16 @@ Create a PlotText object wrapping a string with font info, for plot annotations.
text(t::PlotText) = t text(t::PlotText) = t
text(t::PlotText, font::Font) = PlotText(t.str, font) text(t::PlotText, font::Font) = PlotText(t.str, font)
text(str::AbstractString, f::Font) = PlotText(str, f) text(str::AbstractString, f::Font) = PlotText(str, f)
text(str, args...; kw...) = PlotText(string(str), font(args...; kw...)) function text(str, args...;kw...)
PlotText(string(str), font(args...;kw...))
end
Base.length(t::PlotText) = length(t.str) Base.length(t::PlotText) = length(t.str)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# -----------------------------------------------------------------------
struct Stroke struct Stroke
width width
color color
@ -415,13 +426,14 @@ function stroke(args...; alpha = nothing)
elseif allReals(arg) elseif allReals(arg)
width = arg width = arg
else else
@warn "Unused stroke arg: $arg ($(typeof(arg)))" @warn("Unused stroke arg: $arg ($(typeof(arg)))")
end end
end end
Stroke(width, color, alpha, style) Stroke(width, color, alpha, style)
end end
struct Brush struct Brush
size # fillrange, markersize, or any other sizey attribute size # fillrange, markersize, or any other sizey attribute
color color
@ -447,7 +459,7 @@ function brush(args...; alpha = nothing)
elseif allReals(arg) elseif allReals(arg)
size = arg size = arg
else else
@warn "Unused brush arg: $arg ($(typeof(arg)))" @warn("Unused brush arg: $arg ($(typeof(arg)))")
end end
end end
@ -457,40 +469,33 @@ end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
mutable struct SeriesAnnotations mutable struct SeriesAnnotations
strs::AVec # the labels/names strs::AbstractVector # the labels/names
font::Font font::Font
baseshape::Union{Shape,AVec{Shape},Nothing} baseshape::Union{Shape, AbstractVector{Shape}, Nothing}
scalefactor::Tuple scalefactor::Tuple
end end
_text_label(lab::Tuple, font) = text(lab[1], font, lab[2:end]...)
_text_label(lab::PlotText, font) = lab
_text_label(lab, font) = text(lab, font)
series_annotations(anns::AMat) = map(series_annotations, anns)
series_annotations(scalar) = series_annotations([scalar]) series_annotations(scalar) = series_annotations([scalar])
series_annotations(anns::SeriesAnnotations) = anns function series_annotations(anns::AMat)
series_annotations(::Nothing) = nothing map(series_annotations, anns)
end
function series_annotations(strs::AVec, args...) function series_annotations(strs::AbstractVector, args...)
fnt = font() fnt = font()
shp = nothing shp = nothing
scalefactor = 1, 1 scalefactor = (1,1)
for arg in args for arg in args
if isa(arg, Shape) || (isa(arg, AVec) && eltype(arg) == Shape) if isa(arg, Shape) || (isa(arg, AbstractVector) && eltype(arg) == Shape)
shp = arg shp = arg
elseif isa(arg, Font) elseif isa(arg, Font)
fnt = arg fnt = arg
elseif isa(arg, Symbol) && haskey(_shapes, arg) elseif isa(arg, Symbol) && haskey(_shapes, arg)
shp = _shapes[arg] shp = _shapes[arg]
elseif isa(arg, Number) elseif isa(arg, Number)
scalefactor = arg, arg scalefactor = (arg,arg)
elseif is_2tuple(arg) elseif is_2tuple(arg)
scalefactor = arg scalefactor = arg
elseif isa(arg, AVec)
strs = collect(zip(strs, arg))
else else
@warn "Unused SeriesAnnotations arg: $arg ($(typeof(arg)))" @warn("Unused SeriesAnnotations arg: $arg ($(typeof(arg)))")
end end
end end
# if scalefactor != 1 # if scalefactor != 1
@ -498,14 +503,16 @@ function series_annotations(strs::AVec, args...)
# scale!(s, scalefactor, scalefactor, (0,0)) # scale!(s, scalefactor, scalefactor, (0,0))
# end # end
# end # end
SeriesAnnotations([_text_label(s, fnt) for s in strs], fnt, shp, scalefactor) SeriesAnnotations(strs, fnt, shp, scalefactor)
end end
series_annotations(anns::SeriesAnnotations) = anns
series_annotations(::Nothing) = nothing
function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels) function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
anns = series[:series_annotations] anns = series[:series_annotations]
# msw,msh = anns.scalefactor # msw,msh = anns.scalefactor
# ms = series[:markersize] # ms = series[:markersize]
# msw, msh = if isa(ms, AVec) # msw,msh = if isa(ms, AbstractVector)
# 1,1 # 1,1
# elseif is_2tuple(ms) # elseif is_2tuple(ms)
# ms # ms
@ -538,8 +545,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
maxscale = max(xscale, yscale) maxscale = max(xscale, yscale)
push!(msize, maxscale) push!(msize, maxscale)
baseshape = _cycle(anns.baseshape, i) baseshape = _cycle(anns.baseshape, i)
shapes[i] = shapes[i] = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
scale(baseshape, msw * xscale / maxscale, msh * yscale / maxscale, (0, 0))
end end
series[:markershape] = shapes series[:markershape] = shapes
series[:markersize] = msize series[:markersize] = msize
@ -555,7 +561,7 @@ end
function Base.iterate(ea::EachAnn, i = 1) function Base.iterate(ea::EachAnn, i = 1)
if ea.anns === nothing || isempty(ea.anns.strs) || i > length(ea.y) if ea.anns === nothing || isempty(ea.anns.strs) || i > length(ea.y)
return return nothing
end end
tmp = _cycle(ea.anns.strs,i) tmp = _cycle(ea.anns.strs,i)
@ -567,14 +573,21 @@ function Base.iterate(ea::EachAnn, i = 1)
((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1) ((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1)
end end
# -----------------------------------------------------------------------
annotations(anns::AMat) = map(annotations, anns)
annotations(sa::SeriesAnnotations) = sa
annotations(anns::AVec) = anns
annotations(anns) = Any[anns]
annotations(::Nothing) = [] annotations(::Nothing) = []
annotations(anns::AVec) = anns
annotations(anns::AMat) = map(annotations, anns)
annotations(anns) = Any[anns]
annotations(sa::SeriesAnnotations) = sa
_annotationfont(sp::Subplot) = Plots.font(; # Expand arrays of coordinates, positions and labels into induvidual annotations
# and make sure labels are of type PlotText
function process_annotation(sp::Subplot, xs, ys, labs, font = nothing)
anns = []
labs = makevec(labs)
xlength = length(methods(length, (typeof(xs),))) == 0 ? 1 : length(xs)
ylength = length(methods(length, (typeof(ys),))) == 0 ? 1 : length(ys)
if isnothing(font)
font = Plots.font(;
family=sp[:annotationfontfamily], family=sp[:annotationfontfamily],
pointsize=sp[:annotationfontsize], pointsize=sp[:annotationfontsize],
halign=sp[:annotationhalign], halign=sp[:annotationhalign],
@ -582,80 +595,66 @@ _annotationfont(sp::Subplot) = Plots.font(;
rotation=sp[:annotationrotation], rotation=sp[:annotationrotation],
color=sp[:annotationcolor], color=sp[:annotationcolor],
) )
end
_annotation(sp::Subplot, font, lab, pos...; alphabet = "abcdefghijklmnopqrstuvwxyz") = (
pos...,
lab == :auto ? text("($(alphabet[sp[:subplot_index]]))", font) : _text_label(lab, font),
)
# Expand arrays of coordinates, positions and labels into individual annotations
# and make sure labels are of type PlotText
function process_annotation(sp::Subplot, xs, ys, labs, font = _annotationfont(sp))
anns = []
labs = makevec(labs)
xlength = length(methods(length, (typeof(xs),))) == 0 ? 1 : length(xs)
ylength = length(methods(length, (typeof(ys),))) == 0 ? 1 : length(ys)
for i in 1:max(xlength, ylength, length(labs)) for i in 1:max(xlength, ylength, length(labs))
x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i) x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i)
x = typeof(x) <: TimeType ? Dates.value(x) : x x = typeof(x) <: TimeType ? Dates.value(x) : x
y = typeof(y) <: TimeType ? Dates.value(y) : y y = typeof(y) <: TimeType ? Dates.value(y) : y
push!(anns, _annotation(sp, font, lab, x, y)) if lab == :auto
alphabet = "abcdefghijklmnopqrstuvwxyz"
push!(anns, (x, y, text(string("(", alphabet[sp[:subplot_index]], ")"), font)))
else
push!(anns, (x, y, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab[1], font, lab[2:end]...) : text(lab, font)))
end
end end
anns anns
end end
function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol}, labs, font = nothing)
function process_annotation(
sp::Subplot,
positions::Union{AVec{Symbol},Symbol,Tuple},
labs,
font = _annotationfont(sp),
)
anns = [] anns = []
positions, labs = makevec(positions), makevec(labs) positions, labs = makevec(positions), makevec(labs)
if isnothing(font)
font = Plots.font(;
family=sp[:annotationfontfamily],
pointsize=sp[:annotationfontsize],
halign=sp[:annotationhalign],
valign=sp[:annotationvalign],
rotation=sp[:annotationrotation],
color=sp[:annotationcolor],
)
end
for i in 1:max(length(positions), length(labs)) for i in 1:max(length(positions), length(labs))
pos, lab = _cycle(positions, i), _cycle(labs, i) pos, lab = _cycle(positions, i), _cycle(labs, i)
push!(anns, _annotation(sp, font, lab, get(_positionAliases, pos, pos))) pos = get(_positionAliases, pos, pos)
if lab == :auto
alphabet = "abcdefghijklmnopqrstuvwxyz"
push!(anns, (pos, text(string("(", alphabet[sp[:subplot_index]], ")"), font)))
else
push!(anns, (pos, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab[1], font, lab[2:end]...) : text(lab, font)))
end
end end
anns anns
end end
_relative_position(xmin, xmax, pos::Length{:pct}) = xmin + pos.value * (xmax - xmin) function process_any_label(lab, font=Font())
lab isa Tuple ? text(lab...) : text( lab, font )
end
# Give each annotation coordinates based on specified position # Give each annotation coordinates based on specified position
function locate_annotation( function locate_annotation(sp::Subplot, pos::Symbol, lab::PlotText)
sp::Subplot,
pos::Symbol,
label::PlotText;
position_multiplier = Dict{Symbol, Tuple{Float64,Float64}}( position_multiplier = Dict{Symbol, Tuple{Float64,Float64}}(
:topleft => (0.1pct, 0.9pct), :topleft => (0.1, 0.9),
:topcenter => (0.5pct, 0.9pct), :topcenter => (0.5, 0.9),
:topright => (0.9pct, 0.9pct), :topright => (0.9, 0.9),
:bottomleft => (0.1pct, 0.1pct), :bottomleft => (0.1, 0.1),
:bottomcenter => (0.5pct, 0.1pct), :bottomcenter => (0.5, 0.1),
:bottomright => (0.9pct, 0.1pct), :bottomright => (0.9, 0.1),
),
)
x, y = position_multiplier[pos]
(
_relative_position(axis_limits(sp, :x)..., x),
_relative_position(axis_limits(sp, :y)..., y),
label,
) )
xmin, xmax = ignorenan_extrema(sp[:xaxis])
ymin, ymax = ignorenan_extrema(sp[:yaxis])
x, y = (xmin, ymin).+ position_multiplier[pos].* (xmax - xmin, ymax - ymin)
(x, y, lab)
end end
locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label) locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label)
locate_annotation(sp::Subplot, x, y, z, label::PlotText) = (x, y, z, label) locate_annotation(sp::Subplot, x, y, z, label::PlotText) = (x, y, z, label)
locate_annotation(sp::Subplot, rel::NTuple{2,<:Number}, label::PlotText) = (
_relative_position(axis_limits(sp, :x)..., rel[1] * Plots.pct),
_relative_position(axis_limits(sp, :y)..., rel[2] * Plots.pct),
label,
)
locate_annotation(sp::Subplot, rel::NTuple{3,<:Number}, label::PlotText) = (
_relative_position(axis_limits(sp, :x)..., rel[1] * Plots.pct),
_relative_position(axis_limits(sp, :y)..., rel[2] * Plots.pct),
_relative_position(axis_limits(sp, :z)..., rel[3] * Plots.pct),
label,
)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
"type which represents z-values for colors and sizes (and anything else that might come up)" "type which represents z-values for colors and sizes (and anything else that might come up)"
@ -664,10 +663,7 @@ struct ZValues
zrange::Tuple{Float64,Float64} zrange::Tuple{Float64,Float64}
end end
function zvalues( function zvalues(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values))) where T<:Real
values::AVec{T},
zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values)),
) where {T<:Real}
ZValues(collect(float(values)), map(Float64, zrange)) ZValues(collect(float(values)), map(Float64, zrange))
end end
@ -686,11 +682,14 @@ struct SurfaceFunction <: AbstractSurface
f::Function f::Function
end end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# # I don't want to clash with ValidatedNumerics, but this would be nice: # # I don't want to clash with ValidatedNumerics, but this would be nice:
# ..(a::T, b::T) = (a,b) # ..(a::T, b::T) = (a,b)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# style is :open or :closed (for now) # style is :open or :closed (for now)
@ -710,7 +709,8 @@ Define arrowheads to apply to lines - args are `style` (`:open` or `:closed`),
function arrow(args...) function arrow(args...)
style = :simple style = :simple
side = :head side = :head
headlength = headwidth = 0.3 headlength = 0.3
headwidth = 0.3
setlength = false setlength = false
for arg in args for arg in args
T = typeof(arg) T = typeof(arg)
@ -730,16 +730,17 @@ function arrow(args...)
elseif T <: Tuple && length(arg) == 2 elseif T <: Tuple && length(arg) == 2
headlength, headwidth = Float64(arg[1]), Float64(arg[2]) headlength, headwidth = Float64(arg[1]), Float64(arg[2])
else else
@warn "Skipped arrow arg $arg" @warn("Skipped arrow arg $arg")
end end
end end
Arrow(style, side, headlength, headwidth) Arrow(style, side, headlength, headwidth)
end end
# allow for do-block notation which gets called on every valid start/end pair which # allow for do-block notation which gets called on every valid start/end pair which
# we need to draw an arrow # we need to draw an arrow
function add_arrows(func::Function, x::AVec, y::AVec) function add_arrows(func::Function, x::AVec, y::AVec)
for i in 2:length(x) for i=2:length(x)
xyprev = (x[i-1], y[i-1]) xyprev = (x[i-1], y[i-1])
xy = (x[i], y[i]) xy = (x[i], y[i])
if ok(xyprev) && ok(xy) if ok(xyprev) && ok(xy)
@ -768,8 +769,13 @@ end
@deprecate curve_points coords @deprecate curve_points coords
coords(curve::BezierCurve, n::Integer = 30; range = [0, 1]) = coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, Base.range(first(range), stop=last(range), length=n))
map(curve, Base.range(first(range), stop = last(range), length = n))
# build a BezierCurve which leaves point p vertically upwards and arrives point q vertically upwards.
# may create a loop if necessary. Assumes the view is [0,1]
function directed_curve(args...; kw...)
error("directed_curve has been moved to PlotRecipes")
end
function extrema_plus_buffer(v, buffmult = 0.2) function extrema_plus_buffer(v, buffmult = 0.2)
vmin,vmax = ignorenan_extrema(v) vmin,vmax = ignorenan_extrema(v)
@ -777,20 +783,3 @@ function extrema_plus_buffer(v, buffmult = 0.2)
buffer = vdiff * buffmult buffer = vdiff * buffmult
vmin - buffer, vmax + buffer vmin - buffer, vmax + buffer
end end
### Legend
@add_attributes subplot struct Legend
background_color = :match
foreground_color = :match
position = :best
title = nothing
font::Font = font(8)
title_font::Font = font(11)
column = 1
end :match = (
:legend_font_family,
:legend_font_color,
:legend_title_font_family,
:legend_title_font_color,
)

View File

@ -1,88 +0,0 @@
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)

View File

@ -28,33 +28,35 @@ const _examples = PlotExample[
to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the
animation. animation.
""", """,
[ [:(
:(
begin begin
p = plot( p = plot([sin, cos], zeros(0), leg = false, xlims = (0, 2π), ylims = (-1, 1))
[sin, cos],
zeros(0),
leg = false,
xlims = (0, 2π),
ylims = (-1, 1),
)
anim = Animation() anim = Animation()
for x in range(0, stop = 2π, length = 20) for x in range(0, stop = 2π, length = 20)
push!(p, x, Float64[sin(x), cos(x)]) push!(p, x, Float64[sin(x), cos(x)])
frame(anim) frame(anim)
end end
end end
), )],
],
), ),
PlotExample( # 3 PlotExample( # 3
"Parametric plots", "Parametric plots",
"Plot function pair (x(u), y(u)).", "Plot function pair (x(u), y(u)).",
[:( [
:(
begin begin
plot(sin, x -> sin(2x), 0, 2π, line = 4, leg = false, fill = (0, :orange)) plot(
sin,
x -> sin(2x),
0,
2π,
line = 4,
leg = false,
fill = (0, :orange),
)
end end
)], ),
],
), ),
PlotExample( # 4 PlotExample( # 4
"Colors", "Colors",
@ -113,11 +115,12 @@ const _examples = PlotExample[
) )
vline!([5, 10]) vline!([5, 10])
title!("TITLE") title!("TITLE")
yaxis!("YLABEL", :log10, minorgrid = true) yaxis!("YLABEL", :log10)
end end
), ),
], ],
), ),
PlotExample( # 6 PlotExample( # 6
"Images", "Images",
"Plot an image. y-axis is set to flipped", "Plot an image. y-axis is set to flipped",
@ -125,10 +128,8 @@ const _examples = PlotExample[
:( :(
begin begin
import FileIO import FileIO
import Downloads path =
path = Downloads.download( download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png")
"http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png",
)
img = FileIO.load(path) img = FileIO.load(path)
plot(img) plot(img)
end end
@ -189,11 +190,12 @@ const _examples = PlotExample[
PlotExample( # 11 PlotExample( # 11
"Line types", "Line types",
"", "",
[:( [
:(
begin begin
linetypes = [:path :steppre :steppost :sticks :scatter] linetypes = [:path :steppre :steppost :sticks :scatter]
n = length(linetypes) n = length(linetypes)
x = Vector[sort(rand(20)) for i in 1:n] x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20, n) y = rand(20, n)
plot( plot(
x, x,
@ -203,7 +205,8 @@ const _examples = PlotExample[
ms = 15, ms = 15,
) )
end end
)], ),
],
), ),
PlotExample( # 12 PlotExample( # 12
"Line styles", "Line styles",
@ -234,8 +237,10 @@ const _examples = PlotExample[
[ [
:( :(
begin begin
markers = markers = filter(
filter(m -> m in Plots.supported_markers(), Plots._shape_keys) m -> m in Plots.supported_markers(),
Plots._shape_keys,
)
markers = permutedims(markers) markers = permutedims(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)]
@ -266,11 +271,17 @@ const _examples = PlotExample[
PlotExample( # 15 PlotExample( # 15
"Histogram", "Histogram",
"", "",
[:( [
:(
begin begin
histogram(randn(1000), bins = :scott, weights = repeat(1:5, outer = 200)) histogram(
randn(1000),
bins = :scott,
weights = repeat(1:5, outer = 200),
)
end end
)], ),
],
), ),
PlotExample( # 16 PlotExample( # 16
"Subplots", "Subplots",
@ -316,13 +327,15 @@ const _examples = PlotExample[
PlotExample( # 18 PlotExample( # 18
"", "",
"", "",
[:( [
:(
begin begin
using Random using Random
Random.seed!(111) Random.seed!(111)
plot!(Plots.fakedata(100, 10)) plot!(Plots.fakedata(100, 10))
end end
)], )
]
), ),
PlotExample( # 19 PlotExample( # 19
"Open/High/Low/Close", "Open/High/Low/Close",
@ -345,7 +358,8 @@ const _examples = PlotExample[
bot[i] + hgt[i], bot[i] + hgt[i],
bot[i], bot[i],
closepct[i] * hgt[i] + bot[i], closepct[i] * hgt[i] + bot[i],
) for i in 1:n )
for i = 1:n
] ]
ohlc(y) ohlc(y)
end end
@ -356,21 +370,10 @@ const _examples = PlotExample[
"Annotations", "Annotations",
""" """
The `annotations` keyword is used for text annotations in data-coordinates. Pass in a The `annotations` keyword is used for text annotations in data-coordinates. Pass in a
tuple `(x, y, text)`, a vector of annotations, each of which is a tuple of `x`, `y` tuple (x,y,text) or a vector of annotations. `annotate!(ann)` is shorthand for `plot!(;
and `text`. You can position annotations using relative coordinates with the syntax annotation=ann)`. Series annotations are used for annotating individual data points.
`((px, py), text)`, where for example `px=.25` positions the annotation at `25%` of They require only the annotation... x/y values are computed. A `PlotText` object can be
the subplot's axis width. build with the method `text(string, attr...)`, which wraps font and color attributes.
`text` may be a simple `String`, or a `PlotText` object, which can be built with the
method `text(string, attrs...)`.
This wraps font and color attributes and allows you to set text styling.
`text` may also be a tuple `(string, attrs...)` of arguments which are passed
to `Plots.text`.
`annotate!(ann)` is shorthand for `plot!(; annotation=ann)`.
Series annotations are used for annotating individual data points.
They require only the annotation; x/y values are computed. Series annotations
require either plain `String`s or `PlotText` objects.
""", """,
[ [
:( :(
@ -382,8 +385,12 @@ const _examples = PlotExample[
leg = false, leg = false,
) )
annotate!([ annotate!([
(5, y[5], ("this is #5", 16, :red, :center)), (5, y[5], Plots.text("this is #5", 16, :red, :center)),
(10, y[10], ("this is #10", :right, 20, "courier")), (
10,
y[10],
Plots.text("this is #10", :right, 20, "courier"),
),
]) ])
scatter!( scatter!(
range(2, stop = 8, length = 6), range(2, stop = 8, length = 6),
@ -562,8 +569,8 @@ const _examples = PlotExample[
"", "",
[:( [:(
begin 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, :))
heatmap(xs, ys, z, aspect_ratio = 1) heatmap(xs, ys, z, aspect_ratio = 1)
end end
@ -598,7 +605,12 @@ const _examples = PlotExample[
begin begin
import RDatasets import RDatasets
singers = RDatasets.dataset("lattice", "singer") singers = RDatasets.dataset("lattice", "singer")
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue)) @df singers violin(
:VoicePart,
:Height,
line = 0,
fill = (0.2, :blue),
)
@df singers boxplot!( @df singers boxplot!(
:VoicePart, :VoicePart,
:Height, :Height,
@ -626,7 +638,11 @@ const _examples = PlotExample[
anim = Animation() anim = Animation()
for x in range(1, stop = 2π, length = 20) for x in range(1, stop = 2π, length = 20)
plot(push!(p, x, Float64[sin(x), cos(x), atan(x), cos(x), log(x)])) plot(push!(
p,
x,
Float64[sin(x), cos(x), atan(x), cos(x), log(x)],
))
frame(anim) frame(anim)
end end
end end
@ -651,8 +667,18 @@ const _examples = PlotExample[
10 => ones(40), 10 => ones(40),
-10 => ones(40), -10 => ones(40),
) )
b = spdiagm(0 => 1:50, 1 => 1:49, -1 => 1:49, 10 => 1:40, -10 => 1:40) b = spdiagm(
plot(spy(a), spy(b), title = ["Unique nonzeros" "Different nonzeros"]) 0 => 1:50,
1 => 1:49,
-1 => 1:49,
10 => 1:40,
-10 => 1:40,
)
plot(
spy(a),
spy(b),
title = ["Unique nonzeros" "Different nonzeros"],
)
end end
), ),
], ],
@ -717,24 +743,33 @@ const _examples = PlotExample[
You can use the `line_z` and `marker_z` properties to associate a color with You can use the `line_z` and `marker_z` properties to associate a color with
each line segment or marker in the plot. each line segment or marker in the plot.
""", """,
[:( [
:(
begin 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(x, y, marker_z = +, color = :bluesreds, legend = false) p2 = scatter(
x,
y,
marker_z = +,
color = :bluesreds,
legend = false,
)
plot(p1, p2) plot(p1, p2)
end end
)], ),
],
), ),
PlotExample( # 36 PlotExample( # 36
"Portfolio Composition maps", "Portfolio Composition maps",
""" """
see: http://stackoverflow.com/a/37732384/5075246 see: http://stackoverflow.com/a/37732384/5075246
""", """,
[:( [
:(
begin begin
using Random using Random
Random.seed!(111) Random.seed!(111)
@ -745,9 +780,14 @@ const _examples = PlotExample[
weights ./= sum(weights, dims = 2) weights ./= sum(weights, dims = 2)
returns = sort!((1:N) + D * randn(N)) returns = sort!((1:N) + D * randn(N))
portfoliocomposition(weights, returns, labels = permutedims(tickers)) portfoliocomposition(
weights,
returns,
labels = permutedims(tickers),
)
end end
)], ),
],
), ),
PlotExample( # 37 PlotExample( # 37
"Ribbons", "Ribbons",
@ -760,7 +800,10 @@ const _examples = PlotExample[
:( :(
begin begin
plot( plot(
plot(0:10; ribbon = (LinRange(0, 2, 11), LinRange(0, 1, 11))), plot(
0:10;
ribbon = (LinRange(0, 2, 11), LinRange(0, 1, 11)),
),
plot(0:10; ribbon = 0:0.5:5), plot(0:10; ribbon = 0:0.5:5),
plot(0:10; ribbon = sqrt), plot(0:10; ribbon = sqrt),
plot(0:10; ribbon = 1), plot(0:10; ribbon = 1),
@ -825,7 +868,11 @@ const _examples = PlotExample[
plot!([(0, 0), (0, 0.9), (2, 0.9), (3, 1), (4, 0.9), (80, 0)]) plot!([(0, 0), (0, 0.9), (2, 0.9), (3, 1), (4, 0.9), (80, 0)])
plot!([(0, 0), (0, 0.9), (3, 0.9), (4, 1), (5, 0.9), (80, 0)]) plot!([(0, 0), (0, 0.9), (3, 0.9), (4, 1), (5, 0.9), (80, 0)])
plot!([(0, 0), (0, 0.9), (4, 0.9), (5, 1), (6, 0.9), (80, 0)]) plot!([(0, 0), (0, 0.9), (4, 0.9), (5, 1), (6, 0.9), (80, 0)])
lens!([1, 6], [0.9, 1.1], inset = (1, bbox(0.5, 0.0, 0.4, 0.4))) lens!(
[1, 6],
[0.9, 1.1],
inset = (1, bbox(0.5, 0.0, 0.4, 0.4)),
)
end end
end, end,
], ],
@ -833,7 +880,8 @@ const _examples = PlotExample[
PlotExample( # 41 PlotExample( # 41
"Array Types", "Array Types",
"Plots supports different `Array` types that follow the `AbstractArray` interface, like `StaticArrays` and `OffsetArrays.`", "Plots supports different `Array` types that follow the `AbstractArray` interface, like `StaticArrays` and `OffsetArrays.`",
[quote [
quote
begin begin
using StaticArrays, OffsetArrays using StaticArrays, OffsetArrays
sv = SVector{10}(rand(10)) sv = SVector{10}(rand(10))
@ -841,7 +889,8 @@ const _examples = PlotExample[
plot([sv, ov], label = ["StaticArray" "OffsetArray"]) plot([sv, ov], label = ["StaticArray" "OffsetArray"])
plot!(3ov, ribbon=ov, label="OffsetArray ribbon") plot!(3ov, ribbon=ov, label="OffsetArray ribbon")
end end
end], end,
],
), ),
PlotExample( # 42 PlotExample( # 42
"Setting defaults and font arguments", "Setting defaults and font arguments",
@ -849,6 +898,7 @@ const _examples = PlotExample[
[ [
quote quote
begin begin
using Plots
default( default(
titlefont = (20, "times"), titlefont = (20, "times"),
legendfontsize = 18, legendfontsize = 18,
@ -856,7 +906,7 @@ const _examples = PlotExample[
tickfont = (12, :orange), tickfont = (12, :orange),
guide = "x", guide = "x",
framestyle = :zerolines, framestyle = :zerolines,
yminorgrid = true, yminorgrid = true
) )
plot( plot(
[sin, cos], [sin, cos],
@ -875,7 +925,8 @@ const _examples = PlotExample[
PlotExample( # 43 PlotExample( # 43
"Heatmap with DateTime axis", "Heatmap with DateTime axis",
"", "",
[quote [
quote
begin begin
using Dates using Dates
z = rand(5, 5) z = rand(5, 5)
@ -883,17 +934,20 @@ const _examples = PlotExample[
y = 1:5 y = 1:5
heatmap(x, y, z) heatmap(x, y, z)
end end
end], end,
],
), ),
PlotExample( # 44 PlotExample( # 44
"Linked axes", "Linked axes",
"", "",
[quote [
quote
begin begin
x = -5:0.1:5 x = -5:0.1:5
plot(plot(x, x->x^2), plot(x, x->sin(x)), layout = 2, link = :y) plot(plot(x, x->x^2), plot(x, x->sin(x)), layout = 2, link = :y)
end end
end], end,
],
), ),
PlotExample( # 45 PlotExample( # 45
"Error bars and array type recipes", "Error bars and array type recipes",
@ -908,21 +962,8 @@ const _examples = PlotExample[
value(m::Measurement) = m.val value(m::Measurement) = m.val
uncertainty(m::Measurement) = m.err uncertainty(m::Measurement) = m.err
@recipe function f( @recipe function f(::Type{T}, m::T) where T <: AbstractArray{<:Measurement}
::Type{T}, if !(get(plotattributes, :seriestype, :path) in [:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image])
m::T,
) where {T<:AbstractArray{<:Measurement}}
if !(
get(plotattributes, :seriestype, :path) in [
:contour,
:contourf,
:contour3d,
:heatmap,
:surface,
:wireframe,
:image,
]
)
error_sym = Symbol(plotattributes[:letter], :error) error_sym = Symbol(plotattributes[:letter], :error)
plotattributes[error_sym] = uncertainty.(m) plotattributes[error_sym] = uncertainty.(m)
end end
@ -939,7 +980,7 @@ const _examples = PlotExample[
scatter(x, y, z), scatter(x, y, z),
heatmap(x, y, surf), heatmap(x, y, surf),
wireframe(x, y, surf), wireframe(x, y, surf),
legend = :topleft, legend = :topleft
) )
end end
end, end,
@ -954,17 +995,15 @@ const _examples = PlotExample[
d = MvNormal([1.0 0.75; 0.75 2.0]) d = MvNormal([1.0 0.75; 0.75 2.0])
plot([(1,2),(3,2),(2,1),(2,3)]) plot([(1,2),(3,2),(2,1),(2,3)])
scatter!(Point2.(eachcol(rand(d,1000))), alpha=0.25) scatter!(Point2.(eachcol(rand(d,1000))), alpha=0.25)
end], end]
), ),
PlotExample( # 47 PlotExample( # 47
"Mesh3d", "Mesh3d",
""" """
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically. Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically.
You can also specify the connections using the connections keyword. You can also specify the connections using the connections keyword.
The connections can be specified in two ways: Either as a tuple of vectors where each vector The connections are specified using a tuple of vectors. Each vector contains the 0-based indices of one point of a triangle,
contains the 0-based indices of one point of a triangle, such that elements at the same such that elements at the same position of these vectors form a triangle.
position of these vectors form a triangle. Or as a vector of NTuple{3,Ints} where each element
contains the 1-based indices of the three points of a triangle.
""", """,
[ [
:( :(
@ -980,21 +1019,9 @@ const _examples = PlotExample[
i=[0, 0, 0, 1] i=[0, 0, 0, 1]
j=[1, 2, 3, 2] j=[1, 2, 3, 2]
k=[2, 3, 1, 3] k=[2, 3, 1, 3]
# Or: cns = [(1, 2, 3), (1, 3, 4), (1, 4, 2), (2, 3, 4)] (1-based indexing)
# the four triangles gives above give a tetrahedron # the four triangles gives above give a tetrahedron
mesh3d( mesh3d(x,y,z;connections=(i,j,k))
x,
y,
z;
connections = (i, j, k), # connections = cns
title = "triangles",
xlabel = "x",
ylabel = "y",
zlabel = "z",
legend = :none,
margin = 2Plots.mm,
)
end end
), ),
], ],
@ -1002,8 +1029,7 @@ const _examples = PlotExample[
PlotExample( # 48 PlotExample( # 48
"Vectors of markershapes and segments", "Vectors of markershapes and segments",
"", "",
[ [quote
quote
using Base.Iterators: cycle, take using Base.Iterators: cycle, take
yv = ones(9) yv = ones(9)
@ -1015,7 +1041,7 @@ const _examples = PlotExample[
seriestype = [:path :path :scatter :scatter], seriestype = [:path :path :scatter :scatter],
markershape = collect(take(cycle((:utriangle, :rect)), 9)), markershape = collect(take(cycle((:utriangle, :rect)), 9)),
markersize = 8, markersize = 8,
color = collect(take(cycle((:red, :black)), 9)), color = collect(take(cycle((:red, :black)), 9))
) )
plt_z_cols = plot( plt_z_cols = plot(
@ -1024,12 +1050,11 @@ const _examples = PlotExample[
markersize = [5 10 10 5], markersize = [5 10 10 5],
marker_z = [5 4 3 2], marker_z = [5 4 3 2],
line_z = [1 3 3 1], line_z = [1 3 3 1],
linewidth = [1 10 5 1], linewidth = [1 10 5 1]
) )
plot(plt_color_rows, plt_z_cols) plot(plt_color_rows, plt_z_cols)
end, end]
],
), ),
PlotExample( # 49 PlotExample( # 49
"Polar heatmaps", "Polar heatmaps",
@ -1039,57 +1064,47 @@ const _examples = PlotExample[
y = 0:4 y = 0:4
z = (1:4) .+ (1:8)' z = (1:4) .+ (1:8)'
heatmap(x, y, z, projection = :polar) heatmap(x, y, z, projection = :polar)
end], end]
), ),
PlotExample( # 50 PlotExample( # 50
"3D surface with axis guides", "3D surface with axis guides",
"", "",
[ [quote
quote
f(x,a) = 1/x + a*x^2 f(x,a) = 1/x + a*x^2
xs = collect(0.1:0.05:2.0) xs = collect(0.1:0.05:2.0);
as = collect(0.2:0.1:2.0) as = collect(0.2:0.1:2.0);
x_grid = [x for x in xs for y in as] x_grid = [x for x in xs for y in as];
a_grid = [y for x in xs for y in as] a_grid = [y for x in xs for y in as];
plot( plot(x_grid, a_grid, f.(x_grid,a_grid),
x_grid,
a_grid,
f.(x_grid, a_grid),
st = :surface, st = :surface,
xlabel = "longer xlabel", xlabel = "longer xlabel",
ylabel = "longer ylabel", ylabel = "longer ylabel",
zlabel = "longer zlabel", zlabel = "longer zlabel",
) )
end, end]
],
), ),
PlotExample( # 51 PlotExample( # 51
"Images with custom axes", "Images with custom axes",
"", "",
[ [quote
quote using Plots
using TestImages using TestImages
img = testimage("lighthouse") img = testimage("lighthouse")
# plot the image reversing the first dimension and setting yflip = false # plot the image reversing the first dimension and setting yflip = false
plot( plot([-π, π], [-1, 1], reverse(img, dims=1), yflip=false, aspect_ratio=:none)
[-π, π],
[-1, 1],
reverse(img, dims = 1),
yflip = false,
aspect_ratio = :none,
)
# plot other data # plot other data
plot!(sin, -π, π, lw=3, color=:red) plot!(sin, -π, π, lw=3, color=:red)
end, end]
],
), ),
PlotExample( # 52 PlotExample(
"3d quiver", "3d quiver",
"", "",
[quote [quote
using Plots
ϕs = range(-π, π, length=50) ϕs = range(-π, π, length=50)
θs = range(0, π, length=25) θs = range(0, π, length=25)
θqs = range(1, π-1, length=25) θqs = range(1, π-1, length=25)
@ -1103,7 +1118,7 @@ const _examples = PlotExample[
w = 0.1 * vec([cos(θ) for (ϕ, θ) in Iterators.product(ϕs, θqs)]) w = 0.1 * vec([cos(θ) for (ϕ, θ) in Iterators.product(ϕs, θqs)])
quiver(x,y,z, quiver=(u,v,w)) quiver(x,y,z, quiver=(u,v,w))
end], end]
), ),
PlotExample( # 53 PlotExample( # 53
"Step Types", "Step Types",
@ -1115,28 +1130,10 @@ const _examples = PlotExample[
y = [1, 2, 3, 2, 1] y = [1, 2, 3, 2, 1]
default(shape=:circle) default(shape=:circle)
plot( plot(
plot( plot(x, y, markershape=:circle, seriestype=:steppre, label="steppre"),
x, plot(x, y, markershape=:circle, seriestype=:stepmid, label="stepmid"),
y, plot(x, y, markershape=:circle, seriestype=:steppost, label="steppost"),
markershape = :circle, layout=(3,1)
seriestype = :steppre,
label = "steppre",
),
plot(
x,
y,
markershape = :circle,
seriestype = :stepmid,
label = "stepmid",
),
plot(
x,
y,
markershape = :circle,
seriestype = :steppost,
label = "steppost",
),
layout = (3, 1),
) )
end end
), ),
@ -1160,7 +1157,7 @@ const _examples = PlotExample[
ymirror=[false true true false], ymirror=[false true true false],
xmirror=[false false true true], xmirror=[false false true true],
legend=false, legend=false,
seriestype = [:bar :scatter :path :stepmid], seriestype=[:bar :scatter :path :stepmid]
) )
end end
), ),
@ -1173,54 +1170,38 @@ const _examples = PlotExample[
:( :(
begin begin
using LinearAlgebra using LinearAlgebra
scalefontsizes(0.4) scalefontsizes(.4)
x, y = collect(-6:0.5:10), collect(-8:0.5:8) x, y = collect(-6:0.5:10), collect(-8:0.5:8)
args = x, y, (x, y) -> sinc(norm([x, y]) / π) args = x, y, (x, y) -> sinc(norm([x, y]) / π)
kwargs = Dict( kwargs = Dict(:xlabel=>"x", :ylabel=>"y", :zlabel=>"z", :grid=>true, :minorgrid=>true)
:xlabel => "x",
:ylabel => "y",
:zlabel => "z",
:grid => true,
:minorgrid => true,
)
plots = [wireframe(args..., title = "wire"; kwargs...)] plots = [wireframe(args..., title = "wire"; kwargs...)]
for ax in (:x, :y, :z) for ax (:x, :y, :z)
push!( push!(plots, wireframe(
plots,
wireframe(
args..., args...,
title = "wire-flip-$ax", title = "wire-flip-$ax",
xflip = ax == :x, xflip = ax == :x,
yflip = ax == :y, yflip = ax == :y,
zflip = ax == :z; zflip = ax == :z;
kwargs..., kwargs...,
), ))
)
end end
for ax in (:x, :y, :z) for ax (:x, :y, :z)
push!( push!(plots, wireframe(
plots,
wireframe(
args..., args...,
title = "wire-mirror-$ax", title = "wire-mirror-$ax",
xmirror = ax == :x, xmirror = ax == :x,
ymirror = ax == :y, ymirror = ax == :y,
zmirror = ax == :z; zmirror = ax == :z;
kwargs..., kwargs...,
), ))
)
end end
plt = plot( plt = plot(plots..., layout=(@layout [_ ° _; ° ° °; ° ° °]), margin=0Plots.px)
plots...,
layout = (@layout [_ ° _; ° ° °; ° ° °]),
margin = 0Plots.px,
)
resetfontsizes() resetfontsizes()
plt plt
@ -1228,77 +1209,15 @@ const _examples = PlotExample[
), ),
], ],
), ),
PlotExample( # 56
"Bar plot customizations",
"""
Width of bars may be specified as `bar_width`.
The bars' baseline may be specified as `fillto`.
Each may be scalar, or a vector spcifying one value per bar.
""",
[
:(
begin
plot(
bar(
[-1, 0, 2, 3],
[1, 3, 6, 2],
fill_z = 4:-1:1,
alpha = [1, 0.2, 0.8, 0.5],
label = "",
bar_width = 1:4,
),
bar(
rand(5),
bar_width = 1.2,
alpha = 0.8,
color = [:lightsalmon, :tomato, :crimson, :firebrick, :darkred],
fillto = 0:-0.1:-0.4,
label = "reds",
),
)
end
),
],
),
PlotExample( # 57
"Vertical and horizonal spans",
"""
`vspan` and `hspan` can be used to shade horizontal and vertical ranges.
""",
[:(
begin
hspan([1, 2, 3, 4]; label = "hspan", legend = :topleft)
vspan!([2, 3]; alpha = 0.5, label = "vspan")
plot!([0, 2, 3, 5], [-1, 3, 2, 6]; c = :black, lw = 2, label = "line")
end
)],
),
PlotExample( # 58
"Stacked area chart",
"""
`areaplot` draws stacked area plots.
""",
[
:(
begin
areaplot(
1:3,
[1 2 3; 7 8 9; 4 5 6],
seriescolor = [:red :green :blue],
fillalpha = [0.2 0.3 0.4],
)
end
),
],
),
] ]
# Some constants for PlotDocs and PlotReferenceImages # Some constants for PlotDocs and PlotReferenceImages
_animation_examples = [2, 31] _animation_examples = [2, 31]
_backend_skips = Dict( _backend_skips = Dict(
:gr => [30], :gr => [25, 30, 47],
:pyplot => [2, 25, 30, 31, 49, 55, 56], :pyplot => [2, 25, 30, 31, 47, 49, 55],
:plotlyjs => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55, 56], :plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55],
:plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55],
:pgfplotsx => [ :pgfplotsx => [
2, # animation 2, # animation
6, # images 6, # images
@ -1308,35 +1227,10 @@ _backend_skips = Dict(
32, # spy 32, # spy
49, # polar heatmap 49, # polar heatmap
51, # image with custom axes 51, # image with custom axes
56, # custom bar plot
],
:inspectdr => [4, 6, 10, 22, 24, 28, 30, 38, 43, 45, 47, 48, 49, 50, 51, 55, 56],
:unicodeplots => [
5, # limits issue
6, # embedded images unsupported
16, # nested layout unsupported
21, # custom markers unsupported
26, # nested layout unsupported
29, # nested layout unsupported
31, # nested layout unsupported
33, # grid lines unsupported
34, # framestyle unsupported
37, # ribbons / filled unsupported
43, # heatmap with DateTime
45, # error bars
49, # polar heatmap
51, # embedded images unsupported
55, # mirror unsupported, resolution too low
56, # barplots
],
:gaston => [
2, # animations
31, # animations
49, # TODO: support polar
50, # TODO: 1D data not supported for pm3d
], ],
) )
_backend_skips[:plotly] = _backend_skips[:plotlyjs]
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
@ -1352,8 +1246,11 @@ function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
Base.eval(m, :(using Plots)) Base.eval(m, :(using Plots))
map(exprs -> Base.eval(m, exprs), _examples[idx].exprs) map(exprs -> Base.eval(m, exprs), _examples[idx].exprs)
disp && Base.eval(m, :(gui(current()))) plt = current()
current() if disp
gui(plt)
end
plt
end end
# generate all plots and create a dict mapping idx --> plt # generate all plots and create a dict mapping idx --> plt

View File

@ -1,10 +1,8 @@
# --------------------------------------------------------- # ---------------------------------------------------------
# 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(@nospecialize(filename::AbstractString)) = FileIO.load(filename::AbstractString)
FileIO.load(filename::AbstractString) _fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) = FileIO.save(filename::AbstractString, x)
_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()
@ -23,5 +21,4 @@ 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 = const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}

View File

@ -1,14 +1,15 @@
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[] = use_local_plotlyjs[] = plotly_local_file_path[] === nothing ? false : isfile(plotly_local_file_path[])
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.
@ -19,17 +20,22 @@ 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"] = out["application/vnd.plotly.v1+json"] = Dict(
Dict(:data => plotly_series(plt), :layout => plotly_layout(plt)) :data => plotly_series(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"] = out["application/vnd.plotly.v1+json"] = Dict(
Dict(:data => plotly_series(plt), :layout => plotly_layout(plt)) :data => plotly_series(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
@ -49,9 +55,6 @@ 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

@ -3,6 +3,7 @@ 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)
copy(Dict{Symbol,Any}(Main.PLOTS_DEFAULTS)) copy(Dict{Symbol,Any}(Main.PLOTS_DEFAULTS))
@ -11,6 +12,7 @@ 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)
@ -19,27 +21,14 @@ function __init__()
default(; user_defaults...) default(; user_defaults...)
end end
insert!( insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
Base.Multimedia.displays,
findlast(
x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay,
Base.Multimedia.displays,
) + 1,
PlotsDisplay(),
)
atreplinit( atreplinit(i -> begin
i -> begin
while PlotsDisplay() in Base.Multimedia.displays while PlotsDisplay() in Base.Multimedia.displays
popdisplay(PlotsDisplay()) popdisplay(PlotsDisplay())
end end
insert!( insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
Base.Multimedia.displays, end)
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")
@ -89,18 +78,15 @@ function __init__()
@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[] = global plotly_local_file_path[] = joinpath(@get_scratch!("plotly"), _plotly_min_js_filename)
joinpath(@get_scratch!("plotly"), _plotly_min_js_filename)
if !isfile(plotly_local_file_path[]) if !isfile(plotly_local_file_path[])
Downloads.download( download("https://cdn.plot.ly/$(_plotly_min_js_filename)", plotly_local_file_path[])
"https://cdn.plot.ly/$(_plotly_min_js_filename)",
plotly_local_file_path[],
)
end end
use_local_plotlyjs[] = true use_local_plotlyjs[] = true
@ -108,8 +94,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(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt)
_show_pdfbackends(io, mime, plt)
end end
end end

View File

@ -61,10 +61,7 @@ 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( print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
io,
"BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}",
)
end end
# ----------------------------------------------------------- # -----------------------------------------------------------
@ -91,6 +88,7 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
xy xy
end end
# ----------------------------------------------------------- # -----------------------------------------------------------
# AbstractLayout # AbstractLayout
@ -162,8 +160,7 @@ 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]) = update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing
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))
@ -238,13 +235,11 @@ columns of different width.
""" """
grid(args...; kw...) = GridLayout(args...; kw...) grid(args...; kw...) = GridLayout(args...; kw...)
function GridLayout( function GridLayout(dims...;
dims...;
parent = RootLayout(), parent = RootLayout(),
widths = zeros(dims[2]), widths = zeros(dims[2]),
heights = zeros(dims[1]), heights = zeros(dims[1]),
kw..., kw...)
)
grid = Matrix{AbstractLayout}(undef, dims...) grid = Matrix{AbstractLayout}(undef, dims...)
layout = GridLayout( layout = GridLayout(
parent, parent,
@ -255,8 +250,7 @@ function GridLayout(
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
@ -269,15 +263,13 @@ 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 end
function Base.setindex!(layout::GridLayout, v, ci::CartesianIndex)
layout.grid[ci] = v
end
leftpad(layout::GridLayout) = layout.minpad[1] leftpad(layout::GridLayout) = layout.minpad[1]
toppad(layout::GridLayout) = layout.minpad[2] 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
@ -292,10 +284,11 @@ function _update_min_padding!(layout::GridLayout)
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
@ -314,9 +307,7 @@ 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( error("Not enough length left over in layout! v = $v, cnt = $cnt, leftover = $leftover")
"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
@ -364,7 +355,7 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm, 0mm,
# 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 in 1:nr, c in 1:nc for r=1:nr, c=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)
@ -376,10 +367,7 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm, 0mm,
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!( plotarea!(child, BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height))
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]
@ -392,7 +380,7 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm, 0mm,
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
@ -407,15 +395,12 @@ 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!( bbox!(sp, bbox(
sp,
bbox(
left(p_area) - leftpad(sp), left(p_area) - leftpad(sp),
top(p_area) - toppad(sp), top(p_area) - toppad(sp),
width(p_area) + leftpad(sp) + rightpad(sp), width(p_area) + leftpad(sp) + rightpad(sp),
height(p_area) + toppad(sp) + bottompad(sp), height(p_area) + toppad(sp) + bottompad(sp)
), ))
)
end end
end end
@ -456,9 +441,7 @@ 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( 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.")
"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
@ -494,19 +477,6 @@ function layout_args(sztup::NTuple{3,Integer})
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
@ -514,18 +484,20 @@ function layout_args(layout::GridLayout)
layout, n layout, n
end end
layout_args(n_override::Integer, layout::Union{AbstractVecOrMat,GridLayout}) = layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
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, Array{Plot}(undef, 0)) build_layout(layout, n, Array{Plot}(undef, 0))
end end
# n is the number of subplots... # n is the number of subplots...
function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot}) function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot})
nr, nc = size(layout) nr, nc = size(layout)
@ -533,7 +505,7 @@ function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot})
spmap = SubplotMap() spmap = SubplotMap()
empty = isempty(plts) empty = isempty(plts)
i = 0 i = 0
for r in 1:nr, c in 1:nc for r = 1:nr, c = 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)
if empty if empty
@ -579,13 +551,122 @@ function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot})
layout, subplots, spmap layout, subplots, spmap
end 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 in 2:length(axes) for i=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)
@ -624,18 +705,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) end function link_axes!(l::AbstractLayout, link::Symbol)
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 in 1:nc for c=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 in 1:nr for r=1:nr
link_axes!(layout.grid[r,:], :yaxis) link_axes!(layout.grid[r,:], :yaxis)
end end
end end
@ -662,8 +744,7 @@ 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)
plot!( plot!(sp.plt,
sp.plt,
inset = (sp[:subplot_index], bbox(0,0,1,1)), inset = (sp[:subplot_index], bbox(0,0,1,1)),
right_margin = sp[:right_margin], right_margin = sp[:right_margin],
left_margin = sp[:left_margin], left_margin = sp[:left_margin],

View File

@ -4,7 +4,8 @@ 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`, `xmax`, `ymin`, `ymax`). `(xcenter,ycenter)` on a rectangle defined by (`xmin`,
`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)
@ -14,6 +15,7 @@ function legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax)
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]`
""" """
@ -32,7 +34,7 @@ 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),
@ -53,5 +55,5 @@ legend_angle(leg::Symbol) = get(
outerbottomright = (315,:outer), outerbottomright = (315,:outer),
), ),
leg, leg,
(45, :inner), (45, :inner)
) )

View File

@ -2,68 +2,78 @@
defaultOutputFormat(plt::Plot) = "png" defaultOutputFormat(plt::Plot) = "png"
function png(plt::Plot, fn::AbstractString) function png(plt::Plot, fn::AbstractString)
open(addExtension(fn, "png"), "w") do io fn = addExtension(fn, "png")
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)
open(addExtension(fn, "svg"), "w") do io fn = addExtension(fn, "svg")
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)
open(addExtension(fn, "pdf"), "w") do io fn = addExtension(fn, "pdf")
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)
open(addExtension(fn, "ps"), "w") do io fn = addExtension(fn, "ps")
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)
open(addExtension(fn, "eps"), "w") do io fn = addExtension(fn, "eps")
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)
open(addExtension(fn, "tex"), "w") do io fn = addExtension(fn, "tex")
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)
open(addExtension(fn, "json"), "w") do io fn = addExtension(fn, "json")
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)
open(addExtension(fn, "html"), "w") do io fn = addExtension(fn, "html")
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; color::Bool = true) function txt(plt::Plot, fn::AbstractString)
open(addExtension(fn, "txt"), "w") do io fn = addExtension(fn, "txt")
show(IOContext(io, :color => color), MIME("text/plain"), plt) io = open(fn, "w")
end show(io, MIME("text/plain"), plt)
close(io)
end end
txt(fn::AbstractString) = txt(current(), fn) txt(fn::AbstractString) = txt(current(), fn)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
const _savemap = Dict( const _savemap = Dict(
@ -79,13 +89,6 @@ 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)
@ -125,6 +128,7 @@ function savefig(plt::Plot, fn::AbstractString)
end end
savefig(fn::AbstractString) = savefig(current(), fn) savefig(fn::AbstractString) = savefig(current(), fn)
# --------------------------------------------------------- # ---------------------------------------------------------
""" """
@ -194,7 +198,6 @@ 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",
@ -215,14 +218,13 @@ 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)
@ -239,6 +241,7 @@ closeall() = closeall(backend())
# #
# html_output_format("svg") # html_output_format("svg")
# --------------------------------------------------------- # ---------------------------------------------------------
# Atom PlotPane # Atom PlotPane
# --------------------------------------------------------- # ---------------------------------------------------------

View File

@ -8,18 +8,29 @@ function RecipesPipeline.warn_on_recipe_aliases!(
recipe_type::Symbol, recipe_type::Symbol,
@nospecialize(args) @nospecialize(args)
) )
pkeys = keys(plotattributes) for k in keys(plotattributes)
for k in pkeys if !is_default_attribute(k)
dk = get(_keyAliases, k, nothing) dk = get(_keyAliases, k, k)
if dk !== nothing if k !== dk
kv = RecipesPipeline.pop_kw!(plotattributes, k) if recipe_type == :user
if dk pkeys signature_string = RecipesPipeline.userrecipe_signature_string(args)
plotattributes[dk] = kv elseif recipe_type == :type
end 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
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) =
@ -30,6 +41,7 @@ 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
@ -50,6 +62,7 @@ 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)
@ -68,32 +81,23 @@ 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, default(:marker_z)), Function) if isa(get(kw, :marker_z, nothing), Function)
# TODO: should this take y and/or z as arguments? # TODO: should this take y and/or z as arguments?
kw[:marker_z] = kw[:marker_z] = isa(kw[:z], Nothing) ? map(kw[:marker_z], kw[:x], kw[:y]) :
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, default(:line_z)), Function) if isa(get(kw, :line_z, nothing), Function)
kw[:line_z] = kw[:line_z] = isa(kw[:z], Nothing) ? map(kw[:line_z], kw[:x], kw[:y]) :
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
@ -136,12 +140,15 @@ 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)
@ -152,8 +159,7 @@ 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 = err_inds = findall(kw -> get(kw, :seriestype, :path) in (:xerror, :yerror, :zerror), kw_list)
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])
@ -161,25 +167,10 @@ function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_l
kw_list[ind-1] = tmp kw_list[ind-1] = tmp
end end
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
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
@ -202,6 +193,7 @@ 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
@ -251,33 +243,25 @@ 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)
v = pop!(kw, k) attr[k] = 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[get_attr_symbol(letter, k)] = v attr[Symbol(letter, k)] = v
end
end end
end end
for k in (:scale,), letter in (:x, :y, :z) for k in (:scale,), letter in (:x, :y, :z)
# Series recipes may need access to this information # Series recipes may need access to this information
lk = get_attr_symbol(letter, k) lk = Symbol(letter, k)
if haskey(attr, lk) if haskey(attr, lk)
kw[lk] = attr[lk] kw[lk] = attr[lk]
end 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
@ -290,48 +274,12 @@ 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
@ -349,19 +297,6 @@ 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)
@ -378,10 +313,7 @@ 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 ( if RecipesPipeline.needs_3d_axes(st) || (st == :quiver && plotattributes[:z] !== nothing)
RecipesPipeline.needs_3d_axes(st) ||
(st == :quiver && plotattributes[:z] !== nothing)
)
sp.attr[:projection] = "3d" sp.attr[:projection] = "3d"
end end
@ -397,10 +329,8 @@ 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 ( if z !== nothing &&
z !== nothing &&
(size(plotattributes[:x]) == size(plotattributes[:y]) == size(z)) (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
@ -411,7 +341,7 @@ end
function needs_any_3d_axes(sp::Subplot) function needs_any_3d_axes(sp::Subplot)
any( any(
RecipesPipeline.needs_3d_axes( RecipesPipeline.needs_3d_axes(
_override_seriestype_check(s.plotattributes, s.plotattributes[:seriestype]), _override_seriestype_check(s.plotattributes, s.plotattributes[:seriestype])
) for s in series_list(sp) ) for s in series_list(sp)
) )
end end
@ -451,16 +381,6 @@ 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)
z_order = plotattributes[:z_order]
if z_order == :front
push!(sp.series_list, series) 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

@ -20,17 +20,14 @@ 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))
function Base.show(io::IO, plt::Plot) function Base.show(io::IO, plt::Plot)
print(io, string(plt)) print(io, string(plt))
sp_ekwargs = getindex.(plt.subplots, :extra_kwargs) sp_ekwargs = getindex.(plt.subplots, :extra_kwargs)
s_ekwargs = getindex.(plt.series_list, :extra_kwargs) s_ekwargs = getindex.(plt.series_list, :extra_kwargs)
if ( if isempty(plt[:extra_plot_kwargs]) && all(isempty, sp_ekwargs) && all(isempty, s_ekwargs)
isempty(plt[:extra_plot_kwargs]) &&
all(isempty, sp_ekwargs) &&
all(isempty, s_ekwargs)
)
return return
end end
print(io,"\nCaptured extra kwargs:\n") print(io,"\nCaptured extra kwargs:\n")
@ -65,6 +62,7 @@ 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:
@ -75,7 +73,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")`.
""" """
@ -93,8 +91,7 @@ end
# build a new plot from existing plots # build a new plot from existing plots
# note: we split into plt1, plt2 and plts_tail so we can dispatch correctly # note: we split into plt1, plt2 and plts_tail so we can dispatch correctly
plot(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...) = plot(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...) = plot!(deepcopy(plt1), deepcopy(plt2), deepcopy.(plts_tail)...; kw...)
plot!(deepcopy(plt1), deepcopy(plt2), deepcopy.(plts_tail)...; kw...)
function plot!(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...) function plot!(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...)
@nospecialize @nospecialize
plotattributes = KW(kw) plotattributes = KW(kw)
@ -163,11 +160,10 @@ function plot!(plt1::Plot, plt2::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, idx == ttl_idx ? KW() : plotattributes, idx, false) _update_subplot_args(plt, sp, plotattributes, idx, false)
end end
# finish up # finish up
@ -176,6 +172,8 @@ function plot!(plt1::Plot, plt2::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
@ -211,6 +209,7 @@ 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)
@ -226,17 +225,6 @@ 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)
@ -247,12 +235,6 @@ 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,10 +1,8 @@
const _attribute_defaults = Dict( const _attribute_defaults = Dict(:Series => _series_defaults,
:Series => _series_defaults,
:Subplot => _subplot_defaults, :Subplot => _subplot_defaults,
:Plot => _plot_defaults, :Plot => _plot_defaults,
:Axis => _axis_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])))
@ -23,9 +21,7 @@ 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( println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
"Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())",
)
end end
function plotattr(attrtype::Symbol) function plotattr(attrtype::Symbol)
@ -48,8 +44,7 @@ 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)) || in(attrtype, keys(_attribute_defaults)) || ArgumentError("`attrtype` must match one of $(attrtypes())")
ArgumentError("`attrtype` must match one of $(attrtypes())")
attribute = Symbol(lookup_aliases(attrtype, attribute)) attribute = Symbol(lookup_aliases(attrtype, attribute))
@ -59,21 +54,17 @@ function plotattr(attrtype::Symbol, attribute::AbstractString)
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( println("$(printnothing(attribute)) ", typedesc == "" ? "" : "{$(printnothing(typedesc))}", "\n",
"$(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, ", "$(printnothing(attrtype)) attribute, ", def == "" ? "" : " default: $(printnothing(def))")
def == "" ? "" : " default: $(printnothing(def))",
)
end end

View File

@ -1,40 +1,20 @@
#! format: off
should_precompile = true 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 = true ismultiversion = false
# precompile_enclosure # precompile_enclosure
@static if !should_precompile @static if !should_precompile
# nothing # nothing
elseif !ismultios && !ismultiversion elseif !ismultios && !ismultiversion
@static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_Plots.jl")) @static if isfile(joinpath(
@__DIR__,
"../deps/SnoopCompile/precompile/precompile_Plots.jl",
))
include("../deps/SnoopCompile/precompile/precompile_Plots.jl") 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,16 +41,17 @@ 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} = RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $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,7 +115,7 @@ 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 in 1:3, yi in y]) newy = vec(Float64[yi for i = 1:3, yi in y])
x := newx x := newx
y := newy y := newy
seriestype := :straightline seriestype := :straightline
@ -124,7 +125,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 in 1:3, yi in y]) newx = vec(Float64[yi for i = 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
@ -135,7 +136,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 in 1:n]...) newy = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...)
linewidth --> 0 linewidth --> 0
x := newx x := newx
y := newy y := newy
@ -146,7 +147,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 in 1:n]...) newx = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 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
@ -178,6 +179,7 @@ end
end end
@deps scatterpath path scatter @deps scatterpath path scatter
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# regression line and scatter # regression line and scatter
@ -200,8 +202,10 @@ end
() ()
end end
@specialize @specialize
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# steps # steps
@ -211,7 +215,7 @@ 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 in 2:n for i = 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
@ -225,6 +229,7 @@ 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
@ -302,6 +307,7 @@ end
end end
@deps steppost path scatter @deps steppost path scatter
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# sticks # sticks
@ -320,7 +326,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)) in enumerate(zip(x, y, z !== nothing ? z : 1:n)) for (i, (xi, yi, zi)) = 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
@ -337,11 +343,7 @@ end
end end
fillrange := nothing fillrange := nothing
seriestype := :path seriestype := :path
if ( if plotattributes[:linecolor] == :auto && plotattributes[:marker_z] !== nothing && plotattributes[:line_z] === nothing
plotattributes[:linecolor] == :auto &&
plotattributes[:marker_z] !== nothing &&
plotattributes[:line_z] === nothing
)
line_z := plotattributes[:marker_z] line_z := plotattributes[:marker_z]
end end
@ -366,6 +368,7 @@ end
@specialize @specialize
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# bezier curves # bezier curves
@ -435,18 +438,17 @@ 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 = _preprocess_barlike(plotattributes, x, y) procx, procy, xscale, yscale, baseline =
_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!(plotattributes, :x, xi)[1] for xi in procx] cv = [discrete_value!(axis, 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( 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))")
"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
@ -470,8 +472,18 @@ 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 in 1:ny for i = 1:ny
yi = procy[i] yi = procy[i]
if !isnan(yi) if !isnan(yi)
center = procx[i] center = procx[i]
@ -495,42 +507,15 @@ 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)
# draw the bar shapes
@series begin
seriestype := :shape
series_annotations := nothing
primary := true
x := xseg.pts x := xseg.pts
y := yseg.pts y := yseg.pts
# expand attributes to match indices in new series data seriestype := :shape
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
@ -542,8 +527,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 in 1:m # y for i = 1:m # y
for j in 1:n # x for j = 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]]
@ -590,6 +575,7 @@ 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)
@ -598,6 +584,7 @@ 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,
@ -626,10 +613,12 @@ 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 = _preprocess_binlike(plotattributes, x, y) edge, weights, xscale, yscale, baseline =
_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
@ -640,8 +629,10 @@ 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 = _preprocess_binlike(plotattributes, x, y) edge, weights, xscale, yscale, baseline =
_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
@ -658,7 +649,13 @@ end
@specialize @specialize
function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol) function _stepbins_path(
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
@ -720,9 +717,11 @@ end
@recipe function f(::Type{Val{:stepbins}}, x, y, z) @recipe function f(::Type{Val{:stepbins}}, x, y, z)
@nospecialize @nospecialize
axis = plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis] axis =
plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis]
edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y) edge, weights, xscale, yscale, baseline =
_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)
@ -774,9 +773,12 @@ 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 = nd = N == 2 ?
N == 2 ? min(
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 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
v = vs[dim] v = vs[dim]
@ -795,7 +797,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
wand_edges(v) # this makes this function not type stable, but the type instability does not propagate _cl(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
@ -805,8 +807,11 @@ _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(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} = _hist_edge(
binning vs::NTuple{N,AbstractVector},
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...,))
@ -898,6 +903,7 @@ 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
@ -907,7 +913,8 @@ 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 := get(st_map, plotattributes[:seriestype], plotattributes[:seriestype]) 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
@ -921,6 +928,7 @@ 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
@ -929,6 +937,7 @@ end
end end
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Histogram 2D # Histogram 2D
@ -955,6 +964,7 @@ 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),
@ -970,11 +980,13 @@ 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)
@ -996,6 +1008,7 @@ end
end end
@deps pie shape @deps pie shape
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# mesh 3d replacement for non-plotly backends # mesh 3d replacement for non-plotly backends
@ -1003,15 +1016,12 @@ 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( throw(ArgumentError("Giving triangles using the connections argument is only supported on Plotly backend."))
ArgumentError(
"Giving triangles using the connections argument is only supported on Plotly backend.",
),
)
end end
() ()
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# scatter 3d # scatter 3d
@ -1037,45 +1047,36 @@ 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]
xscale = sp[:xaxis][:scale] xl1, xl2 = xlims(plt.subplots[sp_index])
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(sp) yl1, yl2 = ylims(plt.subplots[sp_index])
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 * (sp[:xaxis][:flip] ? -1 : 1) bbx = bbx1 + width(inset_bbox).value * (xl2 - xl1) / 2
bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2 * (sp[:yaxis][:flip] ? -1 : 1) bby = bby1 + height(inset_bbox).value * (yl2 - yl1) / 2
lens_index = last(plt.subplots)[:subplot_index] + 1 lens_index = last(plt.subplots)[:subplot_index] + 1
x1, x2 = RecipesPipeline.inverse_scale_func(xscale).(plotattributes[:x]) x1, x2 = plotattributes[:x]
y1, y2 = RecipesPipeline.inverse_scale_func(yscale).(plotattributes[:y]) y1, y2 = 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 := get(backup, :linecolor, :lightgray) 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 = xi_lens, yi_lens = intersection_point(bbx_mag, bby_mag, bbx, bby, abs(bby2 - bby1), abs(bbx2 - bbx1))
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))
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 && yl1 < yi_lens < yl2 if xl1 < xi_lens < xl2 &&
yl1 < yi_lens < yl2
@series begin @series begin
primary := false primary := false
subplot := sp_index subplot := sp_index
x := RecipesPipeline.scale_func(xscale).([xi_mag, xi_lens]) x := [xi_mag, xi_lens]
y := RecipesPipeline.scale_func(yscale).([yi_mag, yi_lens]) y := [yi_mag, yi_lens]
() ()
end end
end end
@ -1083,8 +1084,8 @@ export lens!
@series begin @series begin
primary := false primary := false
subplot := sp_index subplot := sp_index
x := RecipesPipeline.scale_func(xscale).([x1, x1, x2, x2, x1]) x := [x1, x1, x2, x2, x1]
y := RecipesPipeline.scale_func(yscale).([y1, y2, y2, y1, y1]) y := [y1, y2, y2, y1, y1]
() ()
end end
# add subplot # add subplot
@ -1093,8 +1094,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 := RecipesPipeline.scale_func(xscale).((x1, x2)) xlims := (x1, x2)
ylims := RecipesPipeline.scale_func(yscale).((y1, y2)) ylims := (y1, y2)
() ()
end end
end end
@ -1140,13 +1141,6 @@ 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]
@ -1277,7 +1271,7 @@ function quiver_using_arrows(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
x, y = zeros(0), zeros(0) x, y = zeros(0), zeros(0)
is_3d && ( z = zeros(0)) is_3d && ( z = zeros(0))
for i in 1:max(length(xorig), length(yorig), is_3d ? 0 : length(zorig)) for i = 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)
@ -1327,7 +1321,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 in 1:max(length(xorig), length(yorig)) for i = 1:max(length(xorig), length(yorig))
# get the starting position # get the starting position
xi = _cycle(xorig, i) xi = _cycle(xorig, i)
@ -1356,7 +1350,10 @@ function quiver_using_hack(plotattributes::AKW)
U2 *= arrow_w U2 *= arrow_w
ppv = p + v ppv = p + v
nanappend!(pts, P2[p, ppv - U1, ppv - U1 + U2, ppv, ppv - U1 - U2, ppv - U1]) nanappend!(
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])
@ -1375,6 +1372,7 @@ end
end end
@deps quiver shape path @deps quiver shape path
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# 1 argument # 1 argument
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -1389,8 +1387,7 @@ function clamp_greys!(mat::AMat{<:Gray})
end end
@recipe function f(mat::AMat{<:Gray}) @recipe function f(mat::AMat{<:Gray})
n, m = map(a -> range(0.5, stop = a.stop + 0.5), axes(mat)) n, m = axes(mat)
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
yflip --> true yflip --> true
@ -1408,7 +1405,7 @@ end
# images - colors # images - colors
@recipe function f(mat::AMat{T}) where {T <: Colorant} @recipe function f(mat::AMat{T}) where {T <: Colorant}
n, m = map(a -> range(0.5, stop = a.stop + 0.5), axes(mat)) n, m = axes(mat)
if is_seriestype_supported(:image) if is_seriestype_supported(:image)
seriestype := :image seriestype := :image
@ -1453,6 +1450,7 @@ end
end end
end end
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# 3 arguments # 3 arguments
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -1551,7 +1549,8 @@ 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} = x, OHLC[OHLC(t...) for t in ohlc] ) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} =
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
@ -1570,6 +1569,7 @@ 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,:)
@ -1617,6 +1617,7 @@ 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
@ -1632,6 +1633,7 @@ 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...)
@ -1655,6 +1657,7 @@ 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
@ -1676,6 +1679,16 @@ 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,6 +241,7 @@ julia> ohlc(y)
""" """
@shorthands ohlc @shorthands ohlc
""" """
contour(x,y,z) contour(x,y,z)
contour!(x,y,z) contour!(x,y,z)
@ -262,6 +263,7 @@ 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
""" """
@ -348,10 +350,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)
- `whisker_range`: Real. Whiskers extend `whisker_range`*IQR below the first quartile - `range`: Real. Values more than range*IQR below the first quartile
and above the third quartile. Values outside this range are shown as outliers (1.5) or above the third quartile are shown as outliers (1.5)
- `outliers`: Bool. Show outliers? (true) - `outliers`: Bool. Show outliers? (true)
- `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) - `whisker_width`: Real or Symbol. Length of whiskers (:match)
# Example # Example
```julia-repl ```julia-repl
@ -431,16 +433,17 @@ 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!(ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = xticks!(
plot!(; xticks = (ticks, labels), kw...) ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
yticks!(ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = yticks!(
plot!(; yticks = (ticks, labels), kw...) ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...)
""" """
annotate!(anns...) annotate!(anns...)
@ -450,14 +453,12 @@ 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`, `PlotText` PlotText (created with `text(args...)`), can be a `String` or `PlotText`.
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...)
@ -472,33 +473,10 @@ 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,5 +1,6 @@
function Subplot(::T; parent = RootLayout()) where {T<:AbstractBackend}
function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
Subplot{T}( Subplot{T}(
parent, parent,
Series[], Series[],
@ -8,7 +9,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
@ -20,6 +21,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

View File

@ -34,8 +34,11 @@ end
@userplot ShowTheme @userplot ShowTheme
_color_functions = _color_functions = KW(
KW(:protanopic => protanopic, :deuteranopic => deuteranopic, :tritanopic => tritanopic) :protanopic => protanopic,
: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)
@ -107,8 +110,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
@ -116,8 +119,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
@ -134,4 +137,5 @@ _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,8 +6,7 @@ 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 = const TicksArgs = Union{AVec{T}, Tuple{AVec{T}, AVec{S}}, Symbol} where {T<:Real, S<:AbstractString}
Union{AVec{T},Tuple{AVec{T},AVec{S}},Symbol} where {T<:Real,S<:AbstractString}
struct PlotsDisplay <: AbstractDisplay end struct PlotsDisplay <: AbstractDisplay end
@ -64,6 +63,7 @@ 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,18 +78,9 @@ mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
end end
function Plot() function Plot()
Plot( Plot(backend(), 0, DefaultsDict(KW(), _plot_defaults), Series[], nothing,
backend(), Subplot[], SubplotMap(), EmptyLayout(),
0, Subplot[], false)
DefaultsDict(KW(), _plot_defaults),
Series[],
nothing,
Subplot[],
SubplotMap(),
EmptyLayout(),
Subplot[],
false,
)
end end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------

View File

@ -1,12 +1,10 @@
# --------------------------------------------------------------- function treats_y_as_x(seriestype)
return seriestype in (:vline, :vspan, :histogram, :barhist, :stephist, :scatterhist)
treats_y_as_x(seriestype) = end
seriestype in (:vline, :vspan, :histogram, :barhist, :stephist, :scatterhist) function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
function replace_image_with_heatmap(z::Array{T}) where {T<:Colorant}
n, m = size(z) n, m = size(z)
colors = palette(vec(z)) colors = palette(vec(z))
newz = reshape(1:(n * m), n, m) newz = reshape(1:n*m, n, m)
newz, colors newz, colors
end end
@ -23,6 +21,7 @@ Segments() = Segments(Float64)
Segments(::Type{T}) where {T} = Segments(T[]) Segments(::Type{T}) where {T} = Segments(T[])
Segments(p::Int) = Segments(NTuple{p, Float64}[]) Segments(p::Int) = Segments(NTuple{p, Float64}[])
# Segments() = Segments(zeros(0)) # Segments() = Segments(zeros(0))
to_nan(::Type{Float64}) = NaN to_nan(::Type{Float64}) = NaN
@ -30,13 +29,10 @@ to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
to_nan(::Type{NTuple{3,Float64}}) = (NaN, NaN, NaN) to_nan(::Type{NTuple{3,Float64}}) = (NaN, NaN, NaN)
coords(segs::Segments{Float64}) = segs.pts coords(segs::Segments{Float64}) = segs.pts
coords(segs::Segments{NTuple{2,Float64}}) = coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts] coords(segs::Segments{NTuple{3,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts], Float64[p[3] for p in segs.pts]
coords(segs::Segments{NTuple{3,Float64}}) = Float64[p[1] for p in segs.pts],
Float64[p[2] for p in segs.pts],
Float64[p[3] for p in segs.pts]
function Base.push!(segments::Segments{T}, vs...) where {T} function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts) if !isempty(segments.pts)
push!(segments.pts, to_nan(T)) push!(segments.pts, to_nan(T))
end end
@ -46,7 +42,7 @@ function Base.push!(segments::Segments{T}, vs...) where {T}
segments segments
end end
function Base.push!(segments::Segments{T}, vs::AVec) where {T} function Base.push!(segments::Segments{T}, vs::AVec) where T
if !isempty(segments.pts) if !isempty(segments.pts)
push!(segments.pts, to_nan(T)) push!(segments.pts, to_nan(T))
end end
@ -56,6 +52,7 @@ function Base.push!(segments::Segments{T}, vs::AVec) where {T}
segments segments
end end
struct SeriesSegment struct SeriesSegment
# indexes of this segement in series data vectors # indexes of this segement in series data vectors
range::UnitRange range::UnitRange
@ -87,14 +84,13 @@ function series_segments(series::Series, seriestype::Symbol = :path; check = fal
if check if check
scales = :xscale, :yscale, :zscale scales = :xscale, :yscale, :zscale
for (n, s) in enumerate(args) for (n, s) enumerate(args)
scale = get(series, scales[n], :identity) scale = get(series, scales[n], :identity)
if scale _logScales if scale _logScales
for (i, v) in enumerate(s) for (i, v) enumerate(s)
if v <= 0 if v <= 0
@warn "Invalid negative or zero value $v found at series index $i for $(scale) based $(scales[n])" @warn "Invalid negative or zero value $v found at series index $i for $(scale) based $(scales[n])"
@debug "" exception=(DomainError(v), stacktrace()) @debug "" exception=(DomainError(v), stacktrace())
break
end end
end end
end end
@ -103,13 +99,10 @@ function series_segments(series::Series, seriestype::Symbol = :path; check = fal
segments = if has_attribute_segments(series) segments = if has_attribute_segments(series)
Iterators.flatten(map(nan_segments) do r Iterators.flatten(map(nan_segments) do r
if seriestype == :shape if seriestype in (:scatter, :scatter3d)
warn_on_inconsistent_shape_attr(series, x, y, z, r)
(SeriesSegment(r, first(r)),)
elseif seriestype in (:scatter, :scatter3d)
(SeriesSegment(i:i, i) for i in r) (SeriesSegment(i:i, i) for i in r)
else else
(SeriesSegment(i:(i + 1), i) for i in first(r):(last(r) - 1)) (SeriesSegment(i:i+1, i) for i in first(r):last(r)-1)
end end
end) end)
else else
@ -122,10 +115,8 @@ end
function warn_on_attr_dim_mismatch(series, x, y, z, segments) function warn_on_attr_dim_mismatch(series, x, y, z, segments)
isempty(segments) && return isempty(segments) && return
seg_range = UnitRange( seg_range = UnitRange(minimum(first(seg.range) for seg in segments),
minimum(first(seg.range) for seg in segments), maximum(last(seg.range) for seg in segments))
maximum(last(seg.range) for seg in segments),
)
for attr in _segmenting_vector_attributes for attr in _segmenting_vector_attributes
v = get(series, attr, nothing) v = get(series, attr, nothing)
if v isa AVec && eachindex(v) != seg_range if v isa AVec && eachindex(v) != seg_range
@ -143,35 +134,21 @@ function warn_on_attr_dim_mismatch(series, x, y, z, segments)
end end
end end
function warn_on_inconsistent_shape_attr(series, x, y, z, r)
for attr in _segmenting_vector_attributes
v = get(series, attr, nothing)
if v isa AVec && length(unique(v[r])) > 1
@warn "Different values of `$attr` specified for different shape vertices. Only first one will be used."
break
end
end
end
# helpers to figure out if there are NaN values in a list of array types # helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> try anynan(i::Int, args::Tuple) = any(a -> try isnan(_cycle(a,i)) catch MethodError false end, args)
isnan(_cycle(a, i))
catch MethodError
false
end, args)
anynan(args::Tuple) = i -> anynan(i,args) anynan(args::Tuple) = i -> anynan(i,args)
anynan(istart::Int, iend::Int, args::Tuple) = any(anynan(args), istart:iend) anynan(istart::Int, iend::Int, args::Tuple) = any(anynan(args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend) allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend)
function Base.iterate(itr::NaNSegmentsIterator, nextidx::Int = itr.n1) function Base.iterate(itr::NaNSegmentsIterator, nextidx::Int = itr.n1)
i = findfirst(!anynan(itr.args), nextidx:(itr.n2)) i = findfirst(!anynan(itr.args), nextidx:itr.n2)
i === nothing && return i === nothing && return nothing
nextval = nextidx + i - 1 nextval = nextidx + i - 1
j = findfirst(anynan(itr.args), nextval:(itr.n2)) j = findfirst(anynan(itr.args), nextval:itr.n2)
nextnan = j === nothing ? itr.n2 + 1 : nextval + j - 1 nextnan = j === nothing ? itr.n2 + 1 : nextval + j - 1
nextval:(nextnan - 1), nextnan nextval:nextnan-1, nextnan
end end
Base.IteratorSize(::NaNSegmentsIterator) = Base.SizeUnknown() Base.IteratorSize(::NaNSegmentsIterator) = Base.SizeUnknown()
@ -183,6 +160,7 @@ float_extended_type(x::AbstractArray{T}) where {T<:Real} = Float64
# ------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------
nop() = nothing nop() = nothing
notimpl() = error("This has not been implemented yet") notimpl() = error("This has not been implemented yet")
@ -215,12 +193,20 @@ makevec(v::T) where {T} = T[v]
maketuple(x::Real) = (x,x) maketuple(x::Real) = (x,x)
maketuple(x::Tuple{T,S}) where {T,S} = x maketuple(x::Tuple{T,S}) where {T,S} = x
RecipesPipeline.unzip(v) = unzip(v) for i in 2:4
RecipesPipeline.unzip(points::AbstractVector{<:GeometryBasics.Point}) = @eval begin
unzip(Tuple.(points)) RecipesPipeline.unzip(
RecipesPipeline.unzip(points::AbstractVector{GeometryBasics.Point{N,T}}) where {N,T} = v::Union{AVec{<:Tuple{Vararg{T,$i} where T}}, AVec{<:GeometryBasics.Point{$i}}},
isbitstype(T) && sizeof(T) > 0 ? unzip(reinterpret(NTuple{N,T}, points)) : ) = $(Expr(:tuple, (:([t[$j] for t in v]) for j=1:i)...))
unzip(Tuple.(points)) end
end
RecipesPipeline.unzip(
::Union{AVec{<:GeometryBasics.Point{N}}, AVec{<:Tuple{Vararg{T,N} where T}}}
) where N = error("$N-dimensional unzip not implemented.")
RecipesPipeline.unzip(::Union{AVec{<:GeometryBasics.Point}, AVec{<:Tuple}}) = error(
"Can't unzip points of different dimensions."
)
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x # given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x) function _expand_limits(lims, x)
@ -233,7 +219,7 @@ function _expand_limits(lims, x)
nothing nothing
end end
expand_data(v, n::Integer) = [_cycle(v, i) for i in 1:n] expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
# if the type exists in a list, replace the first occurence. otherwise add it to the end # if the type exists in a list, replace the first occurence. otherwise add it to the end
function addOrReplace(v::AbstractVector, t::DataType, args...; kw...) function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
@ -267,40 +253,27 @@ end
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end] createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
sortedkeys(plotattributes::Dict) = sort(collect(keys(plotattributes))) sortedkeys(plotattributes::Dict) = sort(collect(keys(plotattributes)))
function _heatmap_edges(v::AVec, isedges::Bool = false, ispolar::Bool = false) function _heatmap_edges(v::AVec, isedges::Bool = false, ispolar::Bool = false)
length(v) == 1 && return v[1] .+ [ispolar ? max(-v[1], -0.5) : -0.5, 0.5] length(v) == 1 && return v[1] .+ [ispolar ? max(-v[1], -0.5) : -0.5, 0.5]
if isedges if isedges return v end
return v
end
# `isedges = true` means that v is a vector which already describes edges # `isedges = true` means that v is a vector which already describes edges
# and does not need to be extended. # and does not need to be extended.
vmin, vmax = ignorenan_extrema(v) vmin, vmax = ignorenan_extrema(v)
extra_min = ispolar ? min(v[1], (v[2] - v[1]) / 2) : (v[2] - v[1]) / 2 extra_min = ispolar ? min(v[1], (v[2] - v[1]) / 2) : (v[2] - v[1]) / 2
extra_max = (v[end] - v[end - 1]) / 2 extra_max = (v[end] - v[end - 1]) / 2
vcat(vmin - extra_min, 0.5 * (v[1:(end - 1)] + v[2:end]), vmax + extra_max) vcat(vmin-extra_min, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra_max)
end end
"create an (n+1) list of the outsides of heatmap rectangles" "create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges( function heatmap_edges(v::AVec, scale::Symbol = :identity, isedges::Bool = false, ispolar::Bool = false)
v::AVec,
scale::Symbol = :identity,
isedges::Bool = false,
ispolar::Bool = false,
)
f, invf = RecipesPipeline.scale_func(scale), RecipesPipeline.inverse_scale_func(scale) f, invf = RecipesPipeline.scale_func(scale), RecipesPipeline.inverse_scale_func(scale)
map(invf, _heatmap_edges(map(f,v), isedges, ispolar)) map(invf, _heatmap_edges(map(f,v), isedges, ispolar))
end end
function heatmap_edges( function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size::Tuple{Int, Int}, ispolar::Bool = false)
x::AVec,
xscale::Symbol,
y::AVec,
yscale::Symbol,
z_size::Tuple{Int,Int},
ispolar::Bool = false,
)
nx, ny = length(x), length(y) nx, ny = length(x), length(y)
# ismidpoints = z_size == (ny, nx) # This fails some tests, but would actually be # ismidpoints = z_size == (ny, nx) # This fails some tests, but would actually be
# the correct check, since (4, 3) != (3, 4) and a missleading plot is produced. # the correct check, since (4, 3) != (3, 4) and a missleading plot is produced.
@ -311,7 +284,8 @@ function heatmap_edges(
Must be either `size(z) == (length(y), length(x))` (x & y define midpoints) Must be either `size(z) == (length(y), length(x))` (x & y define midpoints)
or `size(z) == (length(y)+1, length(x)+1))` (x & y define edges).""") or `size(z) == (length(y)+1, length(x)+1))` (x & y define edges).""")
end end
x, y = heatmap_edges(x, xscale, isedges), heatmap_edges(y, yscale, isedges, ispolar) # special handle for `r` in polar plots x, y = heatmap_edges(x, xscale, isedges),
heatmap_edges(y, yscale, isedges, ispolar) # special handle for `r` in polar plots
return x, y return x, y
end end
@ -328,12 +302,10 @@ function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
x, y x, y
end end
fakedata(sz::Int...) = fakedata(Random.seed!(PLOTS_SEED), sz...) function fakedata(sz...)
function fakedata(rng::AbstractRNG, sz...)
y = zeros(sz...) y = zeros(sz...)
for r in 2:size(y,1) for r in 2:size(y,1)
y[r, :] = 0.95 * vec(y[r - 1, :]) + randn(rng, size(y, 2)) y[r,:] = 0.95 * vec(y[r-1,:]) + randn(size(y,2))
end end
y y
end end
@ -352,20 +324,21 @@ isscalar(::Any) = false
is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2 is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2
isvertical(plotattributes::AKW) =
get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert) isvertical(plotattributes::AKW) = get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert)
isvertical(series::Series) = isvertical(series.plotattributes) isvertical(series::Series) = isvertical(series.plotattributes)
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = :ticks_and_labels
:ticks_and_labels
ticksType(ticks) = :invalid ticksType(ticks) = :invalid
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
limsType(lims) = :invalid limsType(lims) = :invalid
# recursively merge kw-dicts, e.g. for merging extra_kwargs / extra_plot_kwargs in plotly) # recursively merge kw-dicts, e.g. for merging extra_kwargs / extra_plot_kwargs in plotly)
recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...) recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...)
# if values are not AbstractDicts, take the last definition (as does merge) # if values are not AbstractDicts, take the last definition (as does merge)
@ -377,14 +350,15 @@ nanappend!(a::AbstractVector, b) = (push!(a, NaN); append!(a, b))
function nansplit(v::AVec) function nansplit(v::AVec)
vs = Vector{eltype(v)}[] vs = Vector{eltype(v)}[]
while true while true
if (idx = findfirst(isnan, v)) === nothing idx = findfirst(isnan, v)
if idx <= 0
# no nans # no nans
push!(vs, v) push!(vs, v)
break break
elseif idx > 1 elseif idx > 1
push!(vs, v[1:(idx - 1)]) push!(vs, v[1:idx-1])
end end
v = v[(idx + 1):end] v = v[idx+1:end]
end end
vs vs
end end
@ -409,7 +383,9 @@ end
handle_surface(z) = z handle_surface(z) = z
handle_surface(z::Surface) = permutedims(z.surf) handle_surface(z::Surface) = permutedims(z.surf)
ok(x::Number, y::Number, z::Number = 0) = isfinite(x) && isfinite(y) && isfinite(z) function ok(x::Number, y::Number, z::Number = 0)
isfinite(x) && isfinite(y) && isfinite(z)
end
ok(tup::Tuple) = ok(tup...) ok(tup::Tuple) = ok(tup...)
# compute one side of a fill range from a ribbon # compute one side of a fill range from a ribbon
@ -433,13 +409,15 @@ end
#turn tuple of fillranges to one path #turn tuple of fillranges to one path
function concatenate_fillrange(x,y::Tuple) function concatenate_fillrange(x,y::Tuple)
rib1, rib2 = collect(first(y)), collect(last(y)) # collect needed until https://github.com/JuliaLang/julia/pull/37629 is merged rib1, rib2 = first(y), last(y)
yline = vcat(rib1, reverse(rib2)) yline = vcat(rib1,(rib2)[end:-1:1])
xline = vcat(x, reverse(x)) xline = vcat(x,x[end:-1:1])
return xline, yline return xline, yline
end end
get_sp_lims(sp::Subplot, letter::Symbol) = axis_limits(sp, letter) function get_sp_lims(sp::Subplot, letter::Symbol)
axis_limits(sp, letter)
end
""" """
xlims([plt]) xlims([plt])
@ -479,13 +457,16 @@ function contour_levels(series::Series, clims)
if levels isa Integer if levels isa Integer
levels = range(zmin, stop=zmax, length=levels+2) levels = range(zmin, stop=zmax, length=levels+2)
if !isfilledcontour(series) if !isfilledcontour(series)
levels = levels[2:(end - 1)] levels = levels[2:end-1]
end end
end end
levels levels
end end
for comp in (:line, :fill, :marker) for comp in (:line, :fill, :marker)
compcolor = string(comp, :color) compcolor = string(comp, :color)
get_compcolor = Symbol(:get_, compcolor) get_compcolor = Symbol(:get_, compcolor)
comp_z = string(comp, :_z) comp_z = string(comp, :_z)
@ -494,6 +475,7 @@ for comp in (:line, :fill, :marker)
get_compalpha = Symbol(:get_, compalpha) get_compalpha = Symbol(:get_, compalpha)
@eval begin @eval begin
function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1) function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
c = series[$Symbol($compcolor)] c = series[$Symbol($compcolor)]
z = series[$Symbol($comp_z)] z = series[$Symbol($comp_z)]
@ -504,8 +486,7 @@ for comp in (:line, :fill, :marker)
end end
end end
$get_compcolor(series, clims::Tuple{<:Number,<:Number}, i::Int = 1) = $get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
$get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1) function $get_compcolor(series, i::Int = 1)
if series[$Symbol($comp_z)] === nothing if series[$Symbol($comp_z)] === nothing
@ -541,17 +522,26 @@ get_gradient(c) = cgrad()
get_gradient(cg::ColorGradient) = cg get_gradient(cg::ColorGradient) = cg
get_gradient(cp::ColorPalette) = cgrad(cp, categorical = true) get_gradient(cp::ColorPalette) = cgrad(cp, categorical = true)
get_linewidth(series, i::Int = 1) = _cycle(series[:linewidth], i) function get_linewidth(series, i::Int = 1)
get_linestyle(series, i::Int = 1) = _cycle(series[:linestyle], i) _cycle(series[:linewidth], i)
get_fillstyle(series, i::Int = 1) = _cycle(series[:fillstyle], i) end
function get_linestyle(series, i::Int = 1)
_cycle(series[:linestyle], i)
end
function get_markerstrokecolor(series, i::Int = 1) function get_markerstrokecolor(series, i::Int = 1)
msc = series[:markerstrokecolor] msc = series[:markerstrokecolor]
isa(msc, ColorGradient) ? msc : _cycle(msc, i) isa(msc, ColorGradient) ? msc : _cycle(msc, i)
end end
get_markerstrokealpha(series, i::Int = 1) = _cycle(series[:markerstrokealpha], i) function get_markerstrokealpha(series, i::Int = 1)
get_markerstrokewidth(series, i::Int = 1) = _cycle(series[:markerstrokewidth], i) _cycle(series[:markerstrokealpha], i)
end
function get_markerstrokewidth(series, i::Int = 1)
_cycle(series[:markerstrokewidth], i)
end
const _segmenting_vector_attributes = ( const _segmenting_vector_attributes = (
:seriescolor, :seriescolor,
@ -562,7 +552,6 @@ const _segmenting_vector_attributes = (
:linestyle, :linestyle,
:fillcolor, :fillcolor,
:fillalpha, :fillalpha,
:fillstyle,
:markercolor, :markercolor,
:markeralpha, :markeralpha,
:markersize, :markersize,
@ -572,15 +561,15 @@ const _segmenting_vector_attributes = (
:markershape, :markershape,
) )
const _segmenting_array_attributes = :line_z, :fill_z, :marker_z const _segmenting_array_attributes = (:line_z, :fill_z, :marker_z)
function has_attribute_segments(series::Series) function has_attribute_segments(series::Series)
# we want to check if a series needs to be split into segments just because # we want to check if a series needs to be split into segments just because
# of its attributes # of its attributes
series[:seriestype] == :shape && return false
# check relevant attributes if they have multiple inputs # check relevant attributes if they have multiple inputs
return any( return any(series[attr] isa AbstractVector && length(series[attr]) > 1
series[attr] isa AbstractVector && length(series[attr]) > 1 for for attr in _segmenting_vector_attributes
attr in _segmenting_vector_attributes
) || any(series[attr] isa AbstractArray for attr in _segmenting_array_attributes) ) || any(series[attr] isa AbstractArray for attr in _segmenting_array_attributes)
end end
@ -597,10 +586,10 @@ function get_aspect_ratio(sp)
return aspect_ratio return aspect_ratio
end end
get_size(series::Series) = get_size(series.plotattributes[:subplot])
get_size(kw) = get(kw, :size, default(:size)) get_size(kw) = get(kw, :size, default(:size))
get_size(plt::Plot) = get_size(plt.attr) get_size(plt::Plot) = get_size(plt.attr)
get_size(sp::Subplot) = get_size(sp.plt) get_size(sp::Subplot) = get_size(sp.plt)
get_size(series::Series) = get_size(series.plotattributes[:subplot])
get_thickness_scaling(kw) = get(kw, :thickness_scaling, default(:thickness_scaling)) get_thickness_scaling(kw) = get(kw, :thickness_scaling, default(:thickness_scaling))
get_thickness_scaling(plt::Plot) = get_thickness_scaling(plt.attr) get_thickness_scaling(plt::Plot) = get_thickness_scaling(plt.attr)
@ -609,6 +598,7 @@ get_thickness_scaling(series::Series) =
get_thickness_scaling(series.plotattributes[:subplot]) get_thickness_scaling(series.plotattributes[:subplot])
# --------------------------------------------------------------- # ---------------------------------------------------------------
makekw(; kw...) = KW(kw) makekw(; kw...) = KW(kw)
wraptuple(x::Tuple) = x wraptuple(x::Tuple) = x
@ -619,21 +609,16 @@ trueOrAllTrue(f::Function, x) = f(x)
allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg)
allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
allShapes(arg) = ( allShapes(arg) = trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) ||
trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) ||
trueOrAllTrue(a -> isa(a, Shape), arg) trueOrAllTrue(a -> isa(a, Shape), arg)
) allAlphas(arg) = trueOrAllTrue(a -> (typeof(a) <: Real && a > 0 && a < 1) ||
allAlphas(arg) = trueOrAllTrue( (typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg)
a ->
(typeof(a) <: Real && a > 0 && a < 1) || (
typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))
),
arg,
)
allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg) allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg)
allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg) allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg)
# --------------------------------------------------------------- # ---------------------------------------------------------------
# ---------------------------------------------------------------
""" """
Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example: Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example:
@ -651,7 +636,7 @@ function with(f::Function, args...; kw...)
newdefs[:xticks] = nothing newdefs[:xticks] = nothing
newdefs[:yticks] = nothing newdefs[:yticks] = nothing
newdefs[:grid] = false newdefs[:grid] = false
newdefs[:legend_position] = false newdefs[:legend] = false
end end
# dict to store old and new keyword args for anything that changes # dict to store old and new keyword args for anything that changes
@ -667,6 +652,7 @@ function with(f::Function, args...; kw...)
oldbackend = CURRENT_BACKEND.sym oldbackend = CURRENT_BACKEND.sym
for arg in args for arg in args
# change backend? # change backend?
if arg in backends() if arg in backends()
backend(arg) backend(arg)
@ -727,7 +713,10 @@ mutable struct DebugMode
end end
const _debugMode = DebugMode(false) const _debugMode = DebugMode(false)
debugplots(on = true) = _debugMode.on = on function debugplots(on = true)
_debugMode.on = on
end
debugshow(io, x) = show(io, x) debugshow(io, x) = show(io, x)
debugshow(io, x::AbstractArray) = print(io, summary(x)) debugshow(io, x::AbstractArray) = print(io, summary(x))
@ -747,7 +736,9 @@ end
DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true) DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix) DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix)
dumpcallstack() = error() # well... you wanted the stacktrace, didn't you?!? function dumpcallstack()
error() # well... you wanted the stacktrace, didn't you?!?
end
# ------------------------------------------------------- # -------------------------------------------------------
# NOTE: backends should implement the following methods to get/set the x/y/z data objects # NOTE: backends should implement the following methods to get/set the x/y/z data objects
@ -779,17 +770,17 @@ function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z}
_series_updated(plt, series) _series_updated(plt, series)
end end
setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix} = function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix}
(setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)) setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)
end
# ------------------------------------------------------- # -------------------------------------------------------
# indexing notation # indexing notation
# Base.getindex(plt::Plot, i::Integer) = getxy(plt, i) # Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
Base.setindex!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} = Base.setindex!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} = (setxy!(plt, xy, i); plt)
(setxy!(plt, xy, i); plt) Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} = (setxyz!(plt, xyz, i); plt)
Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} =
(setxyz!(plt, xyz, i); plt)
# ------------------------------------------------------- # -------------------------------------------------------
# operate on individual series # operate on individual series
@ -820,7 +811,7 @@ end
function extend_series_data!(series::Series, v, letter) function extend_series_data!(series::Series, v, letter)
copy_series!(series, letter) copy_series!(series, letter)
d = extend_by_data!(series[letter], v) d = extend_by_data!(series[letter], v)
expand_extrema!(series[:subplot][get_attr_symbol(letter, :axis)], d) expand_extrema!(series[:subplot][Symbol(letter, :axis)], d)
return d return d
end end
@ -843,8 +834,9 @@ function extend_to_length!(v::AbstractVector, n)
extend_by_data!(v, vmax .+ (1:(n - length(v)))) extend_by_data!(v, vmax .+ (1:(n - length(v))))
end end
extend_by_data!(v::AbstractVector, x) = isimmutable(v) ? vcat(v, x) : push!(v, x) extend_by_data!(v::AbstractVector, x) = isimmutable(v) ? vcat(v, x) : push!(v, x)
extend_by_data!(v::AbstractVector, x::AbstractVector) = function extend_by_data!(v::AbstractVector, x::AbstractVector)
isimmutable(v) ? vcat(v, x) : append!(v, x) isimmutable(v) ? vcat(v, x) : append!(v, x)
end
# ------------------------------------------------------- # -------------------------------------------------------
@ -895,7 +887,7 @@ Base.append!(plt::Plot, i::Integer, t::Tuple) = append!(plt, i, t...)
# push y[i] to the ith series # push y[i] to the ith series
function Base.push!(plt::Plot, y::AVec) function Base.push!(plt::Plot, y::AVec)
ny = length(y) ny = length(y)
for i in 1:(plt.n) for i in 1:plt.n
push!(plt, i, y[mod1(i,ny)]) push!(plt, i, y[mod1(i,ny)])
end end
plt plt
@ -903,13 +895,15 @@ end
# push y[i] to the ith series # push y[i] to the ith series
# same x for each series # same x for each series
Base.push!(plt::Plot, x::Real, y::AVec) = push!(plt, [x], y) function Base.push!(plt::Plot, x::Real, y::AVec)
push!(plt, [x], y)
end
# push (x[i], y[i]) to the ith series # push (x[i], y[i]) to the ith series
function Base.push!(plt::Plot, x::AVec, y::AVec) function Base.push!(plt::Plot, x::AVec, y::AVec)
nx = length(x) nx = length(x)
ny = length(y) ny = length(y)
for i in 1:(plt.n) for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)]) push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)])
end end
plt plt
@ -920,14 +914,18 @@ function Base.push!(plt::Plot, x::AVec, y::AVec, z::AVec)
nx = length(x) nx = length(x)
ny = length(y) ny = length(y)
nz = length(z) nz = length(z)
for i in 1:(plt.n) for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)], z[mod1(i,nz)]) push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)], z[mod1(i,nz)])
end end
plt plt
end end
# --------------------------------------------------------------- # ---------------------------------------------------------------
# Some conversion functions # Some conversion functions
# note: I borrowed these conversion constants from Compose.jl's Measure # note: I borrowed these conversion constants from Compose.jl's Measure
@ -943,18 +941,16 @@ mm2inch(mm::Real) = float(mm / MM_PER_INCH)
px2mm(px::Real) = float(px * MM_PER_PX) px2mm(px::Real) = float(px * MM_PER_PX)
mm2px(mm::Real) = float(mm / MM_PER_PX) mm2px(mm::Real) = float(mm / MM_PER_PX)
"Smallest x in plot" "Smallest x in plot"
xmin(plt::Plot) = ignorenan_minimum([ xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.plotattributes[:x]) for series in plt.series_list])
ignorenan_minimum(series.plotattributes[:x]) for series in plt.series_list
])
"Largest x in plot" "Largest x in plot"
xmax(plt::Plot) = ignorenan_maximum([ xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.plotattributes[:x]) for series in plt.series_list])
ignorenan_maximum(series.plotattributes[:x]) for series in plt.series_list
])
"Extrema of x-values in plot" "Extrema of x-values in plot"
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt)) ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
# --------------------------------------------------------------- # ---------------------------------------------------------------
# get fonts from objects: # get fonts from objects:
@ -986,21 +982,21 @@ titlefont(sp::Subplot) = font(;
) )
legendfont(sp::Subplot) = font(; legendfont(sp::Subplot) = font(;
family = sp[:legend_font_family], family = sp[:legendfontfamily],
pointsize = sp[:legend_font_pointsize], pointsize = sp[:legendfontsize],
valign = sp[:legend_font_valign], valign = sp[:legendfontvalign],
halign = sp[:legend_font_halign], halign = sp[:legendfonthalign],
rotation = sp[:legend_font_rotation], rotation = sp[:legendfontrotation],
color = sp[:legend_font_color], color = sp[:legendfontcolor],
) )
legendtitlefont(sp::Subplot) = font(; legendtitlefont(sp::Subplot) = font(;
family = sp[:legend_title_font_family], family = sp[:legendtitlefontfamily],
pointsize = sp[:legend_title_font_pointsize], pointsize = sp[:legendtitlefontsize],
valign = sp[:legend_title_font_valign], valign = sp[:legendtitlefontvalign],
halign = sp[:legend_title_font_halign], halign = sp[:legendtitlefonthalign],
rotation = sp[:legend_title_font_rotation], rotation = sp[:legendtitlefontrotation],
color = sp[:legend_title_font_color], color = sp[:legendtitlefontcolor],
) )
tickfont(ax::Axis) = font(; tickfont(ax::Axis) = font(;
@ -1073,14 +1069,11 @@ function straightline_data(series, expansion_factor = 1)
xdata, ydata = fill(NaN, n), fill(NaN, n) xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k for i in 1:k
inds = (3 * i - 2):(3 * i - 1) inds = (3 * i - 2):(3 * i - 1)
xdata[inds], ydata[inds] = xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds], expansion_factor)
straightline_data(xl, yl, x[inds], y[inds], expansion_factor)
end end
xdata, ydata xdata, ydata
else else
error( error("Misformed data. `straightline_data` either accepts vectors of length 2 or 3k. The provided series has length $n")
"Misformed data. `straightline_data` either accepts vectors of length 2 or 3k. The provided series has length $n",
)
end end
end end
@ -1102,10 +1095,7 @@ function straightline_data(xl, yl, x, y, expansion_factor = 1)
b = y[1] - (y[1] - y[2]) * x[1] / (x[1] - x[2]) b = y[1] - (y[1] - y[2]) * x[1] / (x[1] - x[2])
a = (y[1] - y[2]) / (x[1] - x[2]) a = (y[1] - y[2]) / (x[1] - x[2])
# get the data values # get the data values
xdata = [ xdata = [clamp(x[1] + (x[1] - x[2]) * (ylim - y[1]) / (y[1] - y[2]), xl...) for ylim in yl]
clamp(x[1] + (x[1] - x[2]) * (ylim - y[1]) / (y[1] - y[2]), xl...) for
ylim in yl
]
xdata, a .* xdata .+ b xdata, a .* xdata .+ b
end end
@ -1146,19 +1136,18 @@ function shape_data(series, expansion_factor = 1)
return x, y return x, y
end end
construct_categorical_data(x::AbstractArray, axis::Axis) = function construct_categorical_data(x::AbstractArray, axis::Axis)
(map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x)) map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x)
end
_fmt_paragraph(paragraph::AbstractString; kwargs...) = _fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(IOBuffer(),paragraph,0;kwargs...)
_fmt_paragraph(IOBuffer(), paragraph, 0; kwargs...)
function _fmt_paragraph( function _fmt_paragraph(io::IOBuffer,
io::IOBuffer,
remaining_text::AbstractString, remaining_text::AbstractString,
column_count::Integer; column_count::Integer;
fillwidth=60, fillwidth=60,
leadingspaces = 0, leadingspaces=0)
)
kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces) kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces)
m = match(r"(.*?) (.*)",remaining_text) m = match(r"(.*?) (.*)",remaining_text)
@ -1181,68 +1170,6 @@ function _fmt_paragraph(
end end
end end
_document_argument(S::AbstractString) = function _document_argument(S::AbstractString)
_fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S)) _fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S))
function mesh3d_triangles(x, y, z, cns::Tuple{Array,Array,Array})
ci, cj, ck = cns
if !(length(ci) == length(cj) == length(ck))
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
end end
X = zeros(eltype(x), 4length(ci))
Y = zeros(eltype(y), 4length(cj))
Z = zeros(eltype(z), 4length(ck))
@inbounds for I in 1:length(ci)
i = ci[I] + 1 # connections are 0-based
j = cj[I] + 1
k = ck[I] + 1
m = 4(I - 1) + 1
n = m + 1
o = m + 2
p = m + 3
X[m] = X[p] = x[i]
Y[m] = Y[p] = y[i]
Z[m] = Z[p] = z[i]
X[n] = x[j]
Y[n] = y[j]
Z[n] = z[j]
X[o] = x[k]
Y[o] = y[k]
Z[o] = z[k]
end
return X, Y, Z
end
function mesh3d_triangles(x, y, z, cns::AbstractVector{NTuple{3,Int}})
X = zeros(eltype(x), 4length(cns))
Y = zeros(eltype(y), 4length(cns))
Z = zeros(eltype(z), 4length(cns))
@inbounds for I in 1:length(cns)
i = cns[I][1] # connections are 1-based
j = cns[I][2]
k = cns[I][3]
m = 4(I - 1) + 1
n = m + 1
o = m + 2
p = m + 3
X[m] = X[p] = x[i]
Y[m] = Y[p] = y[i]
Z[m] = Z[p] = z[i]
X[n] = x[j]
Y[n] = y[j]
Z[n] = z[j]
X[o] = x[k]
Y[o] = y[k]
Z[o] = z[k]
end
return X, Y, Z
end
# cache joined symbols so they can be looked up instead of constructed each time
const _attrsymbolcache = Dict{Symbol,Dict{Symbol,Symbol}}()
get_attr_symbol(letter::Symbol, keyword::String) = get_attr_symbol(letter, Symbol(keyword))
get_attr_symbol(letter::Symbol, keyword::Symbol) = _attrsymbolcache[letter][keyword]
texmath2unicode(s::AbstractString, pat = r"\$([^$]+)\$") =
replace(s, pat => m -> UnicodeFun.to_latex(m[2:(length(m) - 1)]))

View File

@ -6,13 +6,14 @@ 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, :(Plots.fakedata)) if ex.head === :call && ex.args[1] (:rand, :randn)
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(
@ -34,17 +35,13 @@ 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
eval(:(rng = StableRNG(PLOTS_SEED)))
for the_expr in example.exprs
expr = Expr(:block) expr = Expr(:block)
push!(expr.args, the_expr) append!(expr.args, example.exprs)
fix_rand!(expr) fix_rand!(expr)
eval(expr) eval(expr)
end
png(fn) png(fn)
end end
@ -61,7 +58,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 in 1:length(Plots._examples) for i = 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,26 +1,18 @@
using Plots: guidefont, series_annotations, PLOTS_SEED using Plots: guidefont, series_annotations
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 import ImageMagick
using VisualRegressionTests
using Plots
using Random
using StableRNGs
using Test
using TestImages
using FileIO
using Gtk
using LibGit2
import GeometryBasics
using Dates
using RecipesBase
@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()
@ -35,107 +27,179 @@ end
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
include("test_defaults.jl")
include("test_pipeline.jl")
include("test_axes.jl")
include("test_axis_letter.jl")
include("test_components.jl")
include("test_shorthands.jl")
include("integration_dates.jl")
include("test_recipes.jl")
include("test_hdf5plots.jl")
include("test_pgfplotsx.jl")
reference_dir(args...) = joinpath(homedir(), ".julia", "dev", "PlotReferenceImages", args...)
function reference_file(backend, i, version)
refdir = reference_dir("Plots", string(backend))
fn = "ref$i.png"
versions = sort(VersionNumber.(readdir(refdir)), rev=true)
reffn = joinpath(refdir, string(version), fn)
for v in versions
tmpfn = joinpath(refdir, string(v), fn)
if isfile(tmpfn)
reffn = tmpfn
break
end
end end
@testset "Utils" begin return reffn
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.RecipesPipeline.unzip(z)...)), z)
@test isequal(
collect(zip(Plots.RecipesPipeline.unzip(GeometryBasics.Point.(z))...)),
z,
)
end 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)
@test (==)( reference_path(backend, version) = reference_dir("Plots", string(backend), string(version))
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]) if !isdir(reference_dir())
@test !Plots.isvector(nothing) mkpath(reference_dir())
@test Plots.ismatrix([1 2; 3 4]) LibGit2.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git", reference_dir())
@test !Plots.ismatrix(nothing) end
@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 include("imgcomp.jl")
@test_throws ErrorException Plots.notimpl() # don't actually show the plots
Random.seed!(1234)
default(show=false, reuse=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
@test Plots.inch2px(1) isa AbstractFloat ## Uncomment the following lines to update reference images for different backends
@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
# @testset "GR" begin
# image_comparison_facts(:gr, tol=IMG_TOL, skip = Plots._backend_skips[:gr])
# end
#
# plotly()
# @testset "Plotly" begin
# image_comparison_facts(:plotly, tol=IMG_TOL, skip = Plots._backend_skips[:plotlyjs])
# end
#
# pyplot()
# @testset "PyPlot" begin
# image_comparison_facts(:pyplot, tol=IMG_TOL, skip = Plots._backend_skips[:pyplot])
# end
#
# pgfplotsx()
# @testset "PGFPlotsX" begin
# image_comparison_facts(:pgfplotsx, tol=IMG_TOL, skip = Plots._backend_skips[:pgfplotsx])
# end
# 10 Histogram2D
##
@testset "Backends" begin
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@static if haskey(ENV, "APPVEYOR")
@info "Skipping GR image comparison tests on AppVeyor"
else
image_comparison_facts(:gr, tol=IMG_TOL, skip=Plots._backend_skips[:gr])
end
end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = bar(randn(10))
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([1, 2], [3, 4])
annotate!(p, [(1.5, 3.2, Plots.text("Test", :red, :center))])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
hline!(p, [3.1])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, Plots.text("Test", :red, :center))])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
p = plot([Dates.Date(2019, 1, 1), Dates.Date(2019, 2, 1)], [3, 4])
annotate!(p, [(Dates.Date(2019, 1, 15), 3.2, :auto)])
hline!(p, [3.1])
@test isa(p, Plots.Plot) == true
@test isa(display(p), Nothing) == true
end
@testset "PlotlyJS" begin
@test plotlyjs() == Plots.PlotlyJSBackend()
@test backend() == Plots.PlotlyJSBackend()
p = plot(rand(10))
@test isa(p, Plots.Plot) == true
@test_broken isa(display(p), Nothing) == true
end
end
@testset "Axes" begin
p = plot() p = plot()
@test xlims() isa Tuple axis = p.subplots[1][:xaxis]
@test ylims() isa Tuple @test typeof(axis) == Plots.Axis
@test zlims() isa Tuple @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.makekw(foo = 1, bar = 2) isa Dict 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
@test_throws ErrorException Plots.inline() @testset "NoFail" begin
@test_throws ErrorException Plots._do_plot_show(plot(), :inline) #ensure backend with tested display
@test_throws ErrorException Plots.dumpcallstack() @test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
Plots.debugplots(true) @testset "Plot" begin
Plots.debugplots(false) plots = [histogram([1, 0, 0, 0, 0, 0]),
Plots.debugshow(devnull, nothing) plot([missing]),
Plots.debugshow(devnull, [1]) 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])]
for plt in plots
display(plt)
end
@test_nowarn plot(x -> x^2, 0, 2)
end
p = plot(1) @testset "Bar" begin
push!(p, 1.5) p = bar([3,2,1], [1,2,3]);
push!(p, 1, 1.5) @test isa(p, Plots.Plot)
# append!(p, [1., 2.]) @test isa(display(p), Nothing) == true
append!(p, 1, 2.5, 2.5) end
push!(p, (1.5, 2.5)) end
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 @testset "EmptyAnim" begin
@test Plots.get_attr_symbol(:x, :lims) == :xlims anim = @animate for i in []
end
@test_throws ArgumentError gif(anim)
end
@testset "NaN-separated Segments" begin @testset "NaN-separated Segments" begin
segments(args...) = collect(iter_segments(args...)) segments(args...) = collect(iter_segments(args...))
@ -150,334 +214,19 @@ end
@test segments([NaN; 1], 1:10) == [2:2, 4:4, 6:6, 8:8, 10:10] @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] @test segments([nan10; 1:15], [1:15; nan10]) == [11:15]
end 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 end
op1 = Plots.process_clims((1.0, 2.0))
@testset "Axes" begin op2 = Plots.process_clims((1, 2.0))
p = plot() data = randn(100, 100)
axis = p.subplots[1][:xaxis] @test op1(data) == op2(data)
@test typeof(axis) == Plots.Axis @test Plots.process_clims(nothing) == Plots.process_clims(missing) == Plots.process_clims(:auto)
@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)
refdir = reference_dir("Plots", string(backend))
fn = "ref$i.png"
versions = sort(VersionNumber.(readdir(refdir)), rev = true)
reffn = joinpath(refdir, string(version), fn)
for v in versions
tmpfn = joinpath(refdir, string(v), fn)
if isfile(tmpfn)
reffn = tmpfn
break
end
end
return reffn
end
reference_path(backend, version) = reference_dir("Plots", string(backend), string(version))
if !isdir(reference_dir())
mkpath(reference_dir())
LibGit2.clone(
"https://github.com/JuliaPlots/PlotReferenceImages.jl.git",
reference_dir(),
)
end
include("imgcomp.jl")
Random.seed!(PLOTS_SEED)
default(show = false, reuse = true) # don't actually show the plots
is_ci() = get(ENV, "CI", "false") == "true"
const PLOTS_IMG_TOL = parse(
Float64,
get(ENV, "PLOTS_IMG_TOL", is_ci() ? Sys.iswindows() ? "2e-4" : "1e-4" : "1e-5"),
)
## Uncomment the following lines to update reference images for different backends
# @testset "GR" begin
# image_comparison_facts(:gr, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:gr])
# end
#
# plotly()
# @testset "Plotly" begin
# image_comparison_facts(:plotly, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:plotlyjs])
# end
#
# pyplot()
# @testset "PyPlot" begin
# image_comparison_facts(:pyplot, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:pyplot])
# end
#
# pgfplotsx()
# @testset "PGFPlotsX" begin
# image_comparison_facts(:pgfplotsx, tol=PLOTS_IMG_TOL, skip = Plots._backend_skips[:pgfplotsx])
# end
##
@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 "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
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
@static if haskey(ENV, "APPVEYOR")
@info "Skipping GR image comparison tests on AppVeyor"
else
image_comparison_facts(
:gr,
tol = PLOTS_IMG_TOL,
skip = Plots._backend_skips[:gr],
)
end
end
@testset "PlotlyJS" begin
@test plotlyjs() == Plots.PlotlyJSBackend()
@test backend() == Plots.PlotlyJSBackend()
p = plot(rand(10))
@test p isa Plots.Plot
@test_broken display(p) isa Nothing
end
end end

View File

@ -1,61 +0,0 @@
@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

View File

@ -1,27 +0,0 @@
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

@ -63,60 +63,3 @@ end
@test twpl[:top_margin] == 2Plots.cm @test twpl[:top_margin] == 2Plots.cm
@test twpl[:bottom_margin] == 2Plots.cm @test twpl[:bottom_margin] == 2Plots.cm
end 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,15 +9,12 @@ 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], @testset "$f (orientation = $o)" for f in [histogram, barhist, stephist, scatterhist], o in [:vertical, :horizontal]
o in [:vertical, :horizontal] @test f(data, orientation=o).subplots[1].attr[:title] == (o == :vertical ? "x" : "y")
@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

@ -3,9 +3,6 @@ using Plots, Test
@testset "Shapes" begin @testset "Shapes" begin
@testset "Type" begin @testset "Type" begin
square = Shape([(0, 0.0), (1, 0.0), (1, 1.0), (0, 1.0)]) 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 isa(square, Shape{Int64,Float64})
@test coords(square) isa Tuple{Vector{S},Vector{T}} where {T,S} @test coords(square) isa Tuple{Vector{S},Vector{T}} where {T,S}
end end
@ -55,31 +52,12 @@ using Plots, Test
@testset "Plot" begin @testset "Plot" begin
ang = range(0, 2π, length = 60) ang = range(0, 2π, length = 60)
ellipse(x, y, w, h) = Shape(w * sin.(ang) .+ x, h * cos.(ang) .+ y) 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] myshapes = [ellipse(x, rand(), rand(), rand()) for x = 1:4]
@test coords(myshapes) isa Tuple{Vector{Vector{S}},Vector{Vector{T}}} where {T,S} @test coords(myshapes) isa Tuple{Vector{Vector{S}},Vector{Vector{T}}} where {T,S}
local p local p
@test_nowarn p = plot(myshapes) @test_nowarn p = plot(myshapes)
@test p[1][1][:seriestype] == :shape @test p[1][1][:seriestype] == :shape
end 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
@testset "Brush" begin @testset "Brush" begin
@ -104,39 +82,6 @@ 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 = [ sizesToCheck = [
@ -171,7 +116,7 @@ end
end end
@testset "Series Annotations" begin @testset "Series Annotations" begin
square = Shape([(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)]) square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
@test_logs (:warn, "Unused SeriesAnnotations arg: triangle (Symbol)") begin @test_logs (:warn, "Unused SeriesAnnotations arg: triangle (Symbol)") begin
p = plot( p = plot(
[1, 2, 3], [1, 2, 3],
@ -185,7 +130,7 @@ end
), ),
) )
sa = p.series_list[1].plotattributes[:series_annotations] sa = p.series_list[1].plotattributes[:series_annotations]
@test only(sa.strs).str == "a" @test sa.strs == ["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)
@ -198,24 +143,9 @@ end
xlims = (0, 5), xlims = (0, 5),
series_annotations = permutedims([["1/1"],["1/2"],["1/3"],["1/4"],["1/5"]]), series_annotations = permutedims([["1/1"],["1/2"],["1/3"],["1/4"],["1/5"]]),
) )
for i in 1:5 @test spl.series_list[1].plotattributes[:series_annotations].strs == ["1/1"]
@test only(spl.series_list[i].plotattributes[:series_annotations].strs).str == @test spl.series_list[2].plotattributes[:series_annotations].strs == ["1/2"]
"1/$i" @test spl.series_list[3].plotattributes[:series_annotations].strs == ["1/3"]
end @test spl.series_list[4].plotattributes[:series_annotations].strs == ["1/4"]
@test spl.series_list[5].plotattributes[:series_annotations].strs == ["1/5"]
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

View File

@ -1,68 +0,0 @@
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,4 +1,4 @@
using Plots, Test, Plots.Colors using Plots, Test
const PLOTS_DEFAULTS = Dict(:theme => :wong2, :fontfamily => :palantino) const PLOTS_DEFAULTS = Dict(:theme => :wong2, :fontfamily => :palantino)
Plots.__init__() Plots.__init__()
@ -6,96 +6,8 @@ Plots.__init__()
@testset "Loading theme" begin @testset "Loading theme" begin
pl = plot(1:5) pl = plot(1:5)
@test pl[1][1][:seriescolor] == RGBA(colorant"black") @test pl[1][1][:seriescolor] == RGBA(colorant"black")
@test Plots.guidefont(pl[1][:xaxis]).family == "palantino" @test 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,11 +1,12 @@
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:

View File

@ -1,98 +0,0 @@
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

@ -21,19 +21,16 @@ end
@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" ""], arrow = true) legends_plot = plot(rand(5, 2), lab = ["1" ""])
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 length(series) == 5
@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[5].options.dict, "forget plot")
end # testset end # testset
@testset "3D docs example" begin @testset "3D docs example" begin
@ -85,7 +82,8 @@ end
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"] == RGBA{Float64}(colorant"green", 0.8) @test marker.options["mark options"]["color"] ==
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
@ -172,8 +170,8 @@ end
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)
@ -207,9 +205,15 @@ end
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(x, y, marker_z = ((x, y) -> begin p2 = scatter(
x,
y,
marker_z = ((x, y) -> begin
x + y x + y
end), color = :bwr, legend = false) end),
color = :bwr,
legend = false,
)
plot(p1, p2) plot(p1, p2)
end # testset end # testset
@testset "Framestyles" begin @testset "Framestyles" begin
@ -241,8 +245,11 @@ end
end # testset end # testset
@testset "Annotations" begin @testset "Annotations" begin
y = rand(10) y = rand(10)
pgfx_plot = pgfx_plot = plot(
plot(y, annotations = (3, y[3], Plots.text("this is \\#3", :left)), leg = false) y,
annotations = (3, y[3], Plots.text("this is \\#3", :left)),
leg = false,
)
Plots._update_plot_object(pgfx_plot) Plots._update_plot_object(pgfx_plot)
axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents axis_content = Plots.pgfx_axes(pgfx_plot.o)[1].contents
nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content) nodes = filter(x -> !isa(x, PGFPlotsX.Plot), axis_content)
@ -307,7 +314,8 @@ end
bb = rand(10) bb = rand(10)
cc = rand(10) cc = rand(10)
conf = [aa - cc bb - cc] conf = [aa - cc bb - cc]
ribbon_plot = plot(collect(1:10), fill(1, 10), ribbon = (conf[:, 1], conf[:, 2])) ribbon_plot =
plot(collect(1:10), fill(1, 10), ribbon = (conf[:, 1], conf[:, 2]))
Plots._update_plot_object(ribbon_plot) Plots._update_plot_object(ribbon_plot)
axis = Plots.pgfx_axes(ribbon_plot.o)[1] axis = Plots.pgfx_axes(ribbon_plot.o)[1]
plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents) plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents)
@ -334,13 +342,7 @@ end
group = rand(map((i->begin group = rand(map((i->begin
"group $(i)" "group $(i)"
end), 1:4), 100) end), 1:4), 100)
pl = plot( pl = plot(rand(100), layout = @layout([a b; c]), group = group, linetype = [:bar :scatter :steppre], linecolor = :match)
rand(100),
layout = @layout([a b; c]),
group = group,
linetype = [:bar :scatter :steppre],
linecolor = :match,
)
Plots._update_plot_object(pl) Plots._update_plot_object(pl)
axis = Plots.pgfx_axes(pl.o)[1] axis = Plots.pgfx_axes(pl.o)[1]
legend_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis.contents) legend_entries = filter(x -> x isa PGFPlotsX.LegendEntry, axis.contents)
@ -376,8 +378,12 @@ end # testset
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 = pl = plot(
plot(x -> x, -1:1; add = raw"\node at (0,0.5) {\huge hi};", extra_kwargs = :subplot) x -> x,
-1:1;
add = raw"\node at (0,0.5) {\huge hi};",
extra_kwargs = :subplot,
)
@test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};") @test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};")
Plots._update_plot_object(pl) Plots._update_plot_object(pl)
axes = Plots.pgfx_axes(pl.o) axes = Plots.pgfx_axes(pl.o)
@ -404,7 +410,11 @@ end # testset
@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(rand(3, 3), colorbar_title = "Test me", colorbar_titlefont = (12, :right)) pl = heatmap(
rand(3, 3),
colorbar_title = "Test me",
colorbar_titlefont = (12, :right),
)
@test pl[1][:colorbar_title] == "Test me" @test pl[1][:colorbar_title] == "Test me"
@test pl[1][:colorbar_titlefontsize] == 12 @test pl[1][:colorbar_titlefontsize] == 12
@test pl[1][:colorbar_titlefonthalign] == :right @test pl[1][:colorbar_titlefonthalign] == :right

View File

@ -1,5 +1,4 @@
using Plots, Test using Plots, Test
using RecipesPipeline
@testset "plot" begin @testset "plot" begin
pl = plot(1:5) pl = plot(1:5)
@ -9,30 +8,3 @@ using RecipesPipeline
plot!(pl, tex_output_standalone = true) plot!(pl, tex_output_standalone = true)
@test pl[:tex_output_standalone] == true @test pl[:tex_output_standalone] == true
end 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

View File

@ -1,64 +0,0 @@
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,18 +1,6 @@
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)

View File

@ -7,132 +7,42 @@ using Plots, Test
xlims!((1,20)) xlims!((1,20))
@test xlims(p) == (1,20) @test xlims(p) == (1,20)
xlims!(p, (1, 21))
@test xlims(p) == (1, 21)
ylims!((-1,1)) ylims!((-1,1))
@test ylims(p) == (-1,1) @test ylims(p) == (-1,1)
ylims!(p, (-2, 2))
@test ylims(p) == (-2, 2)
zlims!((-1,1)) zlims!((-1,1))
@test zlims(p) == (-1,1) @test zlims(p) == (-1,1)
zlims!(p, (-2, 2))
@test zlims(p) == (-2, 2)
xlims!(-1,11) xlims!(-1,11)
@test xlims(p) == (-1,11) @test xlims(p) == (-1,11)
xlims!(p, -2, 12)
@test xlims(p) == (-2, 12)
ylims!((-10,10)) ylims!((-10,10))
@test ylims(p) == (-10,10) @test ylims(p) == (-10,10)
ylims!(p, (-11, 9))
@test ylims(p) == (-11, 9)
zlims!((-10,10)) zlims!((-10,10))
@test zlims(p) == (-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 sp.attr[:xaxis][:ticks] == xticks @test Plots.get_subplot(current(),1).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 sp.attr[:yaxis][:ticks] == yticks @test Plots.get_subplot(current(),1).attr[:yaxis][:ticks] == yticks
yticks = 0.1:0.5
yticks!(p, yticks)
@test sp.attr[:yaxis][:ticks] == yticks
xticks = [5,6,7.5] xticks = [5,6,7.5]
xlabels = ["a","b","c"] xlabels = ["a","b","c"]
xticks!(xticks, xlabels) xticks!(xticks, xlabels)
@test sp.attr[:xaxis][:ticks] == (xticks, xlabels) @test Plots.get_subplot(current(),1).attr[:xaxis][:ticks] == (xticks, xlabels)
xticks = [5, 2] yticks = [.5,.6,.75]
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"] ylabels = ["z","y","x"]
yticks!(yticks, ylabels) yticks!(yticks, ylabels)
@test sp.attr[:yaxis][:ticks] == (yticks, ylabels) @test Plots.get_subplot(current(),1).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