Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A get API #4783

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8e2959a
basic extraction form Plot
BeastyBlacksmith Jun 23, 2023
e53e7f1
extra_kwargs for Plot
BeastyBlacksmith Jun 23, 2023
ada3455
handle magic arguments for Plot
BeastyBlacksmith Jun 23, 2023
616cf00
factor out
BeastyBlacksmith Jun 23, 2023
a29dffe
tests for axis and subplot
BeastyBlacksmith Jun 23, 2023
9625c76
implement getting from series
BeastyBlacksmith Jun 23, 2023
72dadb3
format and stub for <--
BeastyBlacksmith Jun 23, 2023
cb5dda9
add interpolation and <-- syntax for attribute access
BeastyBlacksmith Jun 26, 2023
a69160c
integrate in Plots
BeastyBlacksmith Jun 26, 2023
62c59d6
use dev versions of Recipe packages in CI
BeastyBlacksmith Jun 27, 2023
f39ae96
disable build, format
BeastyBlacksmith Jun 27, 2023
f679518
fix ci
BeastyBlacksmith Jun 27, 2023
7642c0a
dev Recipe packages on other actions
BeastyBlacksmith Jun 27, 2023
d9a8c38
Remove PyPlot from test env
BeastyBlacksmith Jun 27, 2023
cc4be02
run Plots tests without xvfb
BeastyBlacksmith Jun 27, 2023
1f4c0a5
add prefix to ubuntu runs
BeastyBlacksmith Jun 28, 2023
5414fc4
Merge branch 'master' into bbs/getattr
BeastyBlacksmith Jun 28, 2023
aa234f8
update invalidations.yml
BeastyBlacksmith Jun 28, 2023
516ad83
uodate ci.yml
BeastyBlacksmith Jun 28, 2023
c657a47
take 2
BeastyBlacksmith Jun 28, 2023
2fb98a3
invalidations
BeastyBlacksmith Jun 28, 2023
6543a42
invalidations
BeastyBlacksmith Jun 28, 2023
3a19444
invalidations
BeastyBlacksmith Jun 28, 2023
3962cb5
invalidations
BeastyBlacksmith Jun 28, 2023
1bbf717
invalidations
BeastyBlacksmith Jun 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: benchmarks
on:
pull_request:

concurrency:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

Expand All @@ -14,11 +14,17 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@latest

- name: Ubuntu TESTCMD
run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV
- name: Install Plots dependencies
uses: julia-actions/julia-buildpkg@latest
run: |
julia -e '
using Pkg
foreach(("RecipesBase", "RecipesPipeline")) do name
Pkg.develop(path=name)
end
'
- name: Install Benchmarking dependencies
run: julia -e 'using Pkg; pkg"add PkgBenchmark BenchmarkCI"'

Expand Down
28 changes: 23 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
with:
version: ${{ matrix.version }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@latest
# - uses: julia-actions/julia-buildpkg@latest

- name: Run upstream RecipesBase & RecipesPipeline tests
shell: julia --project=@. --color=yes {0}
Expand Down Expand Up @@ -99,10 +99,28 @@ jobs:
CondaPkg.PkgREPL.add([libgcc..., "matplotlib"])
CondaPkg.status()

- uses: julia-actions/julia-runtest@latest
timeout-minutes: 60
with:
prefix: ${{ matrix.prefix }} # for `xvfb-run`
# - uses: julia-actions/julia-runtest@latest
# timeout-minutes: 60
# with:
# prefix: ${{ matrix.prefix }} # for `xvfb-run`
- name: Run Plots.jl tests
if: startsWith(matrix.os, 'ubuntu')
shell: xvfb-run julia --project=@. --color=yes {0}
run: |
using Pkg
foreach(("RecipesBase", "RecipesPipeline")) do name
Pkg.develop(path=name)
end
Pkg.test(; coverage=true)
- name: Run Plots.jl tests
if: "!startsWith(matrix.os, 'ubuntu')"
shell: julia --project=@. --color=yes {0}
run: |
using Pkg
foreach(("RecipesBase", "RecipesPipeline")) do name
Pkg.develop(path=name)
end
Pkg.test(; coverage=true)

- name: Run downstream tests
if: startsWith(matrix.os, 'ubuntu')
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/format_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
pull_request:
push:
branches: [master]
concurrency:

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

Expand All @@ -22,6 +22,9 @@ jobs:
PackageSpec("JuliaFormatter"),
PackageSpec(url = "https://github.com/tkf/JuliaProjectFormatter.jl.git"),
])
foreach(("RecipesBase", "RecipesPipeline")) do name
Pkg.develop(path=name)
end
shell: julia --color=yes {0}

- name: Format Julia files
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/invalidations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [master]

concurrency:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

Expand All @@ -16,16 +16,20 @@ jobs:
with:
version: '1'
- uses: actions/checkout@v3
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-invalidations@v1
id: invs_pr
with:
test_script: |
"using Pkg; foreach((\"RecipesBase\", \"RecipesPipeline\")) do name; Pkg.develop(path=name); end; using Plots"

- uses: actions/checkout@v3
with:
ref: 'master'
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-invalidations@v1
id: invs_master
with:
test_script: |
"using Pkg; foreach((\"RecipesBase\", \"RecipesPipeline\")) do name; Pkg.develop(path=name); end; using Plots"

- name: Report invalidation counts
run: |
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Preferences = "1"
FFMPEG = "0.2 - 0.4"
Measures = "0.3"
julia = "1.6"
RecipesBase = "1.3.1"
RecipesBase = "1.4"
UnicodeFun = "0.4"
UnicodePlots = "3.4"
PlotThemes = "2, 3"
Expand All @@ -122,7 +122,7 @@ ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"

[targets]
test = ["Aqua", "Colors", "Distributions", "FileIO", "FilePathsBase", "FreeType", "Gaston", "GeometryBasics", "Gtk", "ImageMagick", "Images", "InspectDR", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PyPlot", "PythonPlot", "PlotlyKaleido", "HDF5", "RDatasets", "SentinelArrays", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "Unitful", "VisualRegressionTests"]
test = ["Aqua", "Colors", "Distributions", "FileIO", "FilePathsBase", "FreeType", "Gaston", "GeometryBasics", "Gtk", "ImageMagick", "Images", "InspectDR", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PythonPlot", "PlotlyKaleido", "HDF5", "RDatasets", "SentinelArrays", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "Unitful", "VisualRegressionTests"]

[extensions]
FileIOExt = "FileIO"
Expand Down
2 changes: 1 addition & 1 deletion RecipesBase/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "RecipesBase"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
author = ["Tom Breloff (@tbreloff)"]
version = "1.3.4"
version = "1.4.0"

[deps]
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Expand Down
19 changes: 14 additions & 5 deletions RecipesBase/src/RecipesBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ function animate end
# a placeholder to establish the name so that other packages (Plots.jl for example)
# can add their own definition of RecipesBase.is_key_supported(k::Symbol)
function is_key_supported end
# funciton to determine canonical form of key in presence of aliases
canonical_key(key) = key

function grid end

Expand Down Expand Up @@ -161,17 +163,27 @@ function process_recipe_body!(expr::Expr)
e = e.args[1]
end


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change

# the unused operator `:=` will mean force: `x := 5` is equivalent to `x --> 5, force`
# note: this means "x is defined as 5"
if e.head === :(:=)
force = true
e.head = :(-->)
end

# `$` will be the recommended way to retrieve values
if e.head === :call && e.args[1] === :(<--) # binary use
target, attribute = e.args[2], e.args[3]
expr.args[i] = Expr(:(=), target, :(plotattributes[$RecipesBase.canonical_key($(attribute))]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
expr.args[i] = Expr(:(=), target, :(plotattributes[$RecipesBase.canonical_key($(attribute))]))
expr.args[i] = Expr(
:(=),
target,
:(plotattributes[$RecipesBase.canonical_key($(attribute))]),
)

elseif e.head === :$ # unary use
expr.args[i] = :(plotattributes[$RecipesBase.canonical_key($(QuoteNode(only(e.args))))])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
expr.args[i] = :(plotattributes[$RecipesBase.canonical_key($(QuoteNode(only(e.args))))])
expr.args[i] = :(plotattributes[$RecipesBase.canonical_key(
$(QuoteNode(only(e.args))),
)])

end

# we are going to recursively swap out `a --> b, flags...` commands
# note: this means "x may become 5"
if e.head === :(-->)
k, v = e.args
k = canonical_key(k)
if isa(k, Symbol)
k = QuoteNode(k)
end
Expand Down Expand Up @@ -204,12 +216,9 @@ function process_recipe_body!(expr::Expr)
elseif e.head ≡ :return
# To allow `return` in recipes just extract the returned arguments.
expr.args[i] = first(e.args)

elseif e.head ≢ :call
# we want to recursively replace the arrows, but not inside function calls
# as this might include things like Dict(1=>2)
process_recipe_body!(e)
end

process_recipe_body!(expr.args[i])
end
end
end
Expand Down
18 changes: 12 additions & 6 deletions RecipesBase/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import RecipesBase as RB
using StableRNGs
using Test


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change

const KW = Dict{Symbol,Any}

RB.is_key_supported(k::Symbol) = true
# Reset method table so tests can be rerun (could be more robust)
recipe_methods = methods(RB.apply_recipe)
length(recipe_methods) > 2 && Base.delete_method.(methods(RB.apply_recipe)[setdiff(1:end, [1,8])])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
length(recipe_methods) > 2 && Base.delete_method.(methods(RB.apply_recipe)[setdiff(1:end, [1,8])])
length(recipe_methods) > 2 &&
Base.delete_method.(methods(RB.apply_recipe)[setdiff(1:end, [1, 8])])


for t in map(i -> Symbol(:T, i), 1:5)
@eval struct $t end
Expand Down Expand Up @@ -139,9 +143,11 @@ end
:markershape --> :auto, :require
:markercolor --> customcolor, :force
:xrotation --> 5
:zrotation --> 6, :quiet
plotattributes[:hello] = "hi"
plotattributes[:world] = "world"
:zrotation --> $xrotation, :quiet
var = $markercolor
war <-- :markershape
plotattributes[:hello] = "$var"
plotattributes[:world] = "$war"
rand(StableRNG(1), 10, n)
end
check_apply_recipe(
Expand All @@ -151,9 +157,9 @@ end
:markershape => :auto,
:markercolor => :red,
:xrotation => 5,
:zrotation => 6,
:hello => "hi",
:world => "world",
:zrotation => 5,
:hello => "red",
:world => "auto",
),
)
end
Expand Down
1 change: 1 addition & 0 deletions src/Plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export
BezierCurve,

plotattr,
getattr,
scalefontsize,
scalefontsizes,
resetfontsizes
Expand Down
1 change: 1 addition & 0 deletions src/args.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1520,6 +1520,7 @@ function preprocess_attributes!(plotattributes::AKW)
end
RecipesPipeline.preprocess_attributes!(plt::Plot, plotattributes::AKW) =
Plots.preprocess_attributes!(plotattributes)
RecipesBase.canonical_key(key::Symbol) = get(_keyAliases, key, key)

# -----------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion src/pipeline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ function _add_the_series(plt, sp, plotattributes)
throw(ArgumentError("Unsupported type for extra keyword arguments"))
end
warn_on_unsupported(plt.backend, plotattributes)
series = Series(plotattributes)
series = Series(length(plt.series_list) + 1, sp, plotattributes)
push!(plt.series_list, series)
if (z_order = plotattributes[:z_order]) === :front
push!(sp.series_list, series)
Expand Down
72 changes: 72 additions & 0 deletions src/plotattr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,75 @@ function plotattr(attrtype::Symbol, attribute::Symbol)
def == "" ? "" : ", defaults to `$def`.",
)
end

function getattr(plt::Plot, s::Symbol)
attribute = get(_keyAliases, s, s)
_getattr(plt, plt.subplots, plt.series_list, attribute)
end
function getattr(sp::Subplot, s::Symbol)
attribute = get(_keyAliases, s, s)
_getattr(sp.plt, [sp], sp.series_list, attribute)
end
function getattr(axis::Axis, s::Symbol)
attribute = get(_keyAliases, s, s)
if attribute in _axis_args
attribute = get_attr_symbol(axis[:letter], attribute)
end
_getattr(only(axis.sps).plt, axis.sps, only(axis.sps).series_list, attribute)
end

function getattr(series::Series, s::Symbol)
attribute = get(_keyAliases, s, s)
_getattr(series.subplot.plt, [series.subplot], [series], attribute)
end

function _getattr(
plt::Plot,
subplots::Vector{<:Subplot},
serieses::Vector{<:Series},
attribute::Symbol,
)
if attribute ∈ _all_plot_args
return plt[attribute]
elseif attribute ∈ _all_subplot_args && attribute ∉ _magic_subplot_args
return reduce(hcat, getindex.(subplots, attribute))
elseif (attribute ∈ _all_axis_args || attribute ∈ _lettered_all_axis_args) &&
attribute ∉ _magic_axis_args
if attribute ∈ _lettered_all_axis_args
letters = collect(String(attribute))
letter = Symbol(first(letters))
attribute = Symbol(letters[2:end]...)
axis = get_attr_symbol(letter, :axis)
reduce(hcat, getindex.(getindex.(subplots, axis), attribute))
else
axes = (:xaxis, :yaxis, :zaxis)
return map(subplots) do sp
return NamedTuple(axis => sp[axis][attribute] for axis in axes)
end
end
elseif attribute ∈ _all_series_args && attribute ∉ _magic_series_args
return reduce(hcat, map(serieses) do series
series[attribute]
end)
else
if attribute in _all_magic_args
@info "$attribute is a magic argument. These are not present in the Plot object. Please use the more specific attribute, such as `linestyle` instead of `line`."
return missing
end
extra_kwargs = Dict(
:plot =>
haskey(plt[:extra_plot_kwargs], attribute) ?
plt[:extra_plot_kwargs][attribute] : [],
:subplots => [
i => sp[:extra_kwargs][attribute] for
(i, sp) in enumerate(subplots) if haskey(sp[:extra_kwargs], attribute)
],
:series => [
series.id => series[:extra_kwargs][attribute] for
series in serieses if haskey(series[:extra_kwargs], attribute)
],
)
!all(isempty, values(extra_kwargs)) && return extra_kwargs
throw(ArgumentError("Attribute not found."))
end
end
4 changes: 3 additions & 1 deletion src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ struct InputWrapper{T}
obj::T
end

mutable struct Series
mutable struct Series{S}
id::Int
subplot::S
plotattributes::DefaultsDict
end

Expand Down
16 changes: 10 additions & 6 deletions test/test_args.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,14 @@ end
@test_throws ArgumentError png(plot(1:2; aspect_ratio = :invalid_ar), fn)
end

@testset "aliases" begin
@test :legend in aliases(:legend_position)
Plots.add_non_underscore_aliases!(Plots._typeAliases)
Plots.add_axes_aliases(:ticks, :tick)
end

@userplot MatrixHeatmap

@recipe function f(A::MatrixHeatmap)
mat = A.args[1]
margin --> (0, :mm)
seriestype := :heatmap
c --> :red
foreground_color := $color
x := axes(mat, 2)
y := axes(mat, 1)
z := Surface(mat)
Expand All @@ -113,6 +109,14 @@ end
@test show(devnull, matrixheatmap(reshape(1:12, 3, 4))) isa Nothing
end

@testset "aliases" begin
@test :legend in aliases(:legend_position)
Plots.add_non_underscore_aliases!(Plots._typeAliases)
Plots.add_axes_aliases(:ticks, :tick)
@test getattr(matrixheatmap(reshape(1:12, 3, 4))[1][1], :foreground_color) ==
RGBA(colorant"red")
end

@testset "Formatters" begin
ts = range(DateTime(today()), step = Hour(1), length = 24)
p1 = plot(ts, 100randn(24))
Expand Down