From 19dbc60752df0696b47302b69bae716df96e021b Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 12:21:00 -0400 Subject: [PATCH 001/356] initial empty commit From 350f75f58b992991b675ef301983229f3dcd13f3 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 12:21:01 -0400 Subject: [PATCH 002/356] RecipesBase.jl generated files. license: MIT authors: Thomas Breloff years: 2016 user: Julia Version 0.4.4 [ae683af] --- RecipesBase/.gitignore | 3 +++ RecipesBase/.travis.yml | 14 ++++++++++++++ RecipesBase/LICENSE.md | 22 ++++++++++++++++++++++ RecipesBase/README.md | 1 + RecipesBase/REQUIRE | 1 + RecipesBase/appveyor.yml | 34 ++++++++++++++++++++++++++++++++++ RecipesBase/src/RecipesBase.jl | 5 +++++ RecipesBase/test/runtests.jl | 5 +++++ 8 files changed, 85 insertions(+) create mode 100644 RecipesBase/.gitignore create mode 100644 RecipesBase/.travis.yml create mode 100644 RecipesBase/LICENSE.md create mode 100644 RecipesBase/README.md create mode 100644 RecipesBase/REQUIRE create mode 100644 RecipesBase/appveyor.yml create mode 100644 RecipesBase/src/RecipesBase.jl create mode 100644 RecipesBase/test/runtests.jl diff --git a/RecipesBase/.gitignore b/RecipesBase/.gitignore new file mode 100644 index 000000000..8c960ec80 --- /dev/null +++ b/RecipesBase/.gitignore @@ -0,0 +1,3 @@ +*.jl.cov +*.jl.*.cov +*.jl.mem diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml new file mode 100644 index 000000000..e5c48ff5e --- /dev/null +++ b/RecipesBase/.travis.yml @@ -0,0 +1,14 @@ +# Documentation: http://docs.travis-ci.com/user/languages/julia/ +language: julia +os: + - linux + - osx +julia: + - release + - nightly +notifications: + email: false +# uncomment the following lines to override the default test script +#script: +# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi +# - julia -e 'Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' diff --git a/RecipesBase/LICENSE.md b/RecipesBase/LICENSE.md new file mode 100644 index 000000000..209d1ea4a --- /dev/null +++ b/RecipesBase/LICENSE.md @@ -0,0 +1,22 @@ +The RecipesBase.jl package is licensed under the MIT "Expat" License: + +> Copyright (c) 2016: Thomas Breloff. +> +> Permission is hereby granted, free of charge, to any person obtaining +> a copy of this software and associated documentation files (the +> "Software"), to deal in the Software without restriction, including +> without limitation the rights to use, copy, modify, merge, publish, +> distribute, sublicense, and/or sell copies of the Software, and to +> permit persons to whom the Software is furnished to do so, subject to +> the following conditions: +> +> The above copyright notice and this permission notice shall be +> included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/RecipesBase/README.md b/RecipesBase/README.md new file mode 100644 index 000000000..b097a0467 --- /dev/null +++ b/RecipesBase/README.md @@ -0,0 +1 @@ +# RecipesBase diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE new file mode 100644 index 000000000..d5d646713 --- /dev/null +++ b/RecipesBase/REQUIRE @@ -0,0 +1 @@ +julia 0.4 diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml new file mode 100644 index 000000000..d3309ec80 --- /dev/null +++ b/RecipesBase/appveyor.yml @@ -0,0 +1,34 @@ +environment: + matrix: + - JULIAVERSION: "julialang/bin/winnt/x86/0.4/julia-0.4-latest-win32.exe" + - JULIAVERSION: "julialang/bin/winnt/x64/0.4/julia-0.4-latest-win64.exe" + - JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe" + - JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe" + +branches: + only: + - master + - /release-.*/ + +notifications: + - provider: Email + on_build_success: false + on_build_failure: false + on_build_status_changed: false + +install: +# Download most recent Julia Windows binary + - ps: (new-object net.webclient).DownloadFile( + $("http://s3.amazonaws.com/"+$env:JULIAVERSION), + "C:\projects\julia-binary.exe") +# Run installer silently, output to C:\projects\julia + - C:\projects\julia-binary.exe /S /D=C:\projects\julia + +build_script: +# Need to convert from shallow to complete for Pkg.clone to work + - IF EXIST .git\shallow (git fetch --unshallow) + - C:\projects\julia\bin\julia -e "versioninfo(); + Pkg.clone(pwd(), \"RecipesBase\"); Pkg.build(\"RecipesBase\")" + +test_script: + - C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"RecipesBase\")" diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl new file mode 100644 index 000000000..343ce80f0 --- /dev/null +++ b/RecipesBase/src/RecipesBase.jl @@ -0,0 +1,5 @@ +module RecipesBase + +# package code goes here + +end # module diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl new file mode 100644 index 000000000..6dc8bc156 --- /dev/null +++ b/RecipesBase/test/runtests.jl @@ -0,0 +1,5 @@ +using RecipesBase +using Base.Test + +# write your own tests here +@test 1 == 1 From 4cea2c69d3d32b073b839d02040ac3f2585f46dc Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 13:14:14 -0400 Subject: [PATCH 003/356] copied in the implementation; added tests; added documentation; some fixes --- RecipesBase/README.md | 55 ++++++++++ RecipesBase/src/RecipesBase.jl | 182 ++++++++++++++++++++++++++++++++- RecipesBase/test/runtests.jl | 28 ++++- 3 files changed, 262 insertions(+), 3 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index b097a0467..2cf2d3e88 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -1 +1,56 @@ # RecipesBase + +### Author: Thomas Breloff (@tbreloff) + +This package implements a handy macro `@recipe` which will define a custom transformation +and attach attributes for user types. It's design is an attempt to simplify and generalize +the summary and display of types and data from external packages. With no extra dependencies +and minimal code, package authors can describe visualization routines that can be used +as components in more complex visualizations. + +This functionality is primarily geared to turning user types and settings into the +data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, though it could be used for +other purposes as well. Plots has extensive machinery to uniquely take advantage of the simplified +recipe description you define. + +The `@recipe` macro will process a function definition, replace `-->` commands, and +then add a new version of `apply_recipe` for dispatching on the arguments. + +Set attributes using the `-->` command, and return a comma separated list of arguments that +should replace the current arguments. + +The `is_key_supported` method should likely be overridden... by default everything is considered supported. + +## An example: + +``` + # Plots will be the ultimate consumer of our recipe in this example + using Plot + gr() + + type T end + + @recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10,n) + end + + # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots + # processing pipeline (see the Pipeline section of the Plots documentation). + # It will plot 5 line plots, all with black circles for markers. + # The markershape argument must be supported, and the zrotation argument's warning + # will be suppressed. The user can override all arguments except markercolor. + plot(T(), 5; customcolor = :black, shape=:c) +``` + +In this example, we see lots of the machinery in action. We create a new type `T` which +we will use for dispatch, and an optional argument `n`, which will be used to determine the +number of series to display. User-defined keyword arguments are passed through, and the +`-->` command can be trailed by flags: + +- quiet: Suppress unsupported keyword warnings +- require: Error if keyword is unsupported +- force: Don't allow user override for this keyword diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 343ce80f0..68e4bf253 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -1,5 +1,185 @@ module RecipesBase -# package code goes here +export + @recipe, + apply_recipe, + is_key_supported + +# a placeholder... this should be overridden by the package which uses the recipe (Plots.jl for example) +is_key_supported(k::Symbol) = true + +# this holds the recipe definitions to be dispatched on +apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}) = () + +# if it's not a recipe, just do nothing and return the args +function apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, args...; issubplot=false) + if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout) + # put in a sensible default + d[:n] = maximum(map(num_series, args)) + end + args +end + +macro kw(k, v) + esc(:(get!(d, $k, $v))) +end + +function _is_arrow_tuple(expr::Expr) + expr.head == :tuple && + isa(expr.args[1], Expr) && + expr.args[1].head == :(-->) +end + +function _equals_symbol(arg::Symbol, sym::Symbol) + arg == sym +end +function _equals_symbol(arg::Expr, sym::Symbol) + arg.head == :quote && arg.args[1] == sym +end + +function replace_recipe_arrows!(expr::Expr) + for (i,e) in enumerate(expr.args) + if isa(e,Expr) + + # process trailing flags, like: + # a --> b, :quiet, :force + quiet, require, force = false, false, false + if _is_arrow_tuple(e) + for flag in e.args + if _equals_symbol(flag, :quiet) + quiet = true + elseif _equals_symbol(flag, :require) + require = true + elseif _equals_symbol(flag, :force) + force = true + end + end + e = e.args[1] + end + + # we are going to recursively swap out `a --> b, flags...` commands + if e.head == :(-->) + k, v = e.args + + set_expr = if force + # forced override user settings + :(d[$k] = $v) + else + # if the user has set this keyword, use theirs + :(get!(d, $k, $v)) + end + + expr.args[i] = if quiet + # quietly ignore keywords which are not supported + :(is_key_supported($k) ? $set_expr : nothing) + elseif require + # error when not supported by the backend + :(is_key_supported($k) ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())")) + else + set_expr + end + + # @show quiet, force, expr.args[i] + + 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) + replace_recipe_arrows!(e) + end + end + end +end + + +""" +This handy macro will process a function definition, replace `-->` commands, and +then add a new version of `RecipesBase.apply_recipe` for dispatching on the arguments. + +This functionality is primarily geared to turning user types and settings into the +data and attributes that describe a Plots.jl visualization. + +Set attributes using the `-->` command, and return a comma separated list of arguments that +should replace the current arguments. + +An example: + +``` + # Plots will be the ultimate consumer of our recipe in this example + using Plot + gr() + + type T end + + @recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10,n) + end + + # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots + # processing pipeline (see the Pipeline section of the Plots documentation). + # It will plot 5 line plots, all with black circles for markers. + # The markershape argument must be supported, and the zrotation argument's warning + # will be suppressed. The user can override all arguments except markercolor. + plot(T(), 5; customcolor = :black, shape=:c) +``` + +In this example, we see lots of the machinery in action. We create a new type `T` which +we will use for dispatch, and an optional argument `n`, which will be used to determine the +number of series to display. User-defined keyword arguments are passed through, and the +`-->` command can be trailed by flags: + +- quiet: Suppress unsupported keyword warnings +- require: Error if keyword is unsupported +- force: Don't allow user override for this keyword +""" +macro recipe(funcexpr::Expr) + lhs, body = funcexpr.args + + if !(funcexpr.head in (:(=), :function)) + error("Must wrap a valid function call!") + end + if !(isa(lhs, Expr) && lhs.head == :call) + error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs") + end + + # for parametric definitions, take the "curly" expression and add the func + front = lhs.args[1] + func = :(RecipesBase.apply_recipe) + if isa(front, Expr) && front.head == :curly + front.args[1] = func + func = front + end + + # get the arg list, stripping out any keyword parameters into a + # bunch of get!(kw, key, value) lines + args = lhs.args[2:end] + kw_body = Expr(:block) + if isa(args[1], Expr) && args[1].head == :parameters + for kwpair in args[1].args + k, v = kwpair.args + push!(kw_body.args, :($k = get!(kw, $(QuoteNode(k)), $v))) + end + args = args[2:end] + end + + # replace all the key => value lines with argument setting logic + replace_recipe_arrows!(body) + + # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed + esc(quote + function $func(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, $(args...); issubplot=false) + $kw_body + ret = $body + if typeof(ret) <: Tuple + ret + else + (ret,) + end + end + end) +end end # module diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 6dc8bc156..edd1698a4 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -1,5 +1,29 @@ using RecipesBase using Base.Test -# write your own tests here -@test 1 == 1 +srand(1) + +type T end + +@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10,n) +end + +# this is similar to how Plots would call the method +typealias KW Dict{Symbol,Any} +d = KW() +kw = KW(:customcolor => :red) +args = RecipesBase.apply_recipe(d, kw, T(), 2; issubplot = false) + +# make sure the attribute dictionary was populated correctly, and the returned arguments are as expected +@test args == (srand(1); (rand(10,2),)) +@test d == KW( + :markershape => :auto, + :markercolor => :red, + :xrotation => 5, + :zrotation => 6 +) From 70f1a3a5719532d6664318ac19f88ea0dc93fec8 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 13:26:17 -0400 Subject: [PATCH 004/356] readme --- RecipesBase/README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 2cf2d3e88..28262f6bb 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -23,27 +23,27 @@ The `is_key_supported` method should likely be overridden... by default everythi ## An example: -``` - # Plots will be the ultimate consumer of our recipe in this example - using Plot - gr() - - type T end - - @recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) - :markershape --> :auto, :require - :markercolor --> customcolor, :force - :xrotation --> 5 - :zrotation --> 6, :quiet - rand(10,n) - end - - # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots - # processing pipeline (see the Pipeline section of the Plots documentation). - # It will plot 5 line plots, all with black circles for markers. - # The markershape argument must be supported, and the zrotation argument's warning - # will be suppressed. The user can override all arguments except markercolor. - plot(T(), 5; customcolor = :black, shape=:c) +```julia +# Plots will be the ultimate consumer of our recipe in this example +using Plot +gr() + +type T end + +@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 45 + :zrotation --> 90, :quiet + rand(10,n) +end + +# This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots +# processing pipeline (see the Pipeline section of the Plots documentation). +# It will plot 5 line plots, all with black circles for markers. +# The markershape argument must be supported, and the zrotation argument's warning +# will be suppressed. The user can override all arguments except markercolor. +plot(T(), 5; customcolor = :black, shape=:c) ``` In this example, we see lots of the machinery in action. We create a new type `T` which From 52e20df08ef88704c8f670f1c1d2f53ab5975972 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 13:32:59 -0400 Subject: [PATCH 005/356] readme --- RecipesBase/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 28262f6bb..a3eb1b82b 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -1,5 +1,7 @@ # RecipesBase +[![Build Status](https://travis-ci.org/JuliaPlots/RecipesBase.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/RecipesBase.jl) + ### Author: Thomas Breloff (@tbreloff) This package implements a handy macro `@recipe` which will define a custom transformation @@ -51,6 +53,6 @@ we will use for dispatch, and an optional argument `n`, which will be used to de number of series to display. User-defined keyword arguments are passed through, and the `-->` command can be trailed by flags: -- quiet: Suppress unsupported keyword warnings -- require: Error if keyword is unsupported -- force: Don't allow user override for this keyword +- `quiet`: Suppress unsupported keyword warnings +- `require`: Error if keyword is unsupported +- `force`: Don't allow user override for this keyword From c03244135d495b9de8493466270c92889b37caed Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 13:47:32 -0400 Subject: [PATCH 006/356] removed unused kw macro --- RecipesBase/src/RecipesBase.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 68e4bf253..2f1444fb2 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -20,10 +20,6 @@ function apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, args...; issubp args end -macro kw(k, v) - esc(:(get!(d, $k, $v))) -end - function _is_arrow_tuple(expr::Expr) expr.head == :tuple && isa(expr.args[1], Expr) && From 6b54408a881cbfecdcc803ea398597fb2e9b227e Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 14:38:12 -0400 Subject: [PATCH 007/356] cleanup --- RecipesBase/README.md | 2 +- RecipesBase/src/RecipesBase.jl | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index a3eb1b82b..7c518afd5 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -27,7 +27,7 @@ The `is_key_supported` method should likely be overridden... by default everythi ```julia # Plots will be the ultimate consumer of our recipe in this example -using Plot +using Plots gr() type T end diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 2f1444fb2..bbb644f64 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -11,14 +11,7 @@ is_key_supported(k::Symbol) = true # this holds the recipe definitions to be dispatched on apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}) = () -# if it's not a recipe, just do nothing and return the args -function apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, args...; issubplot=false) - if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout) - # put in a sensible default - d[:n] = maximum(map(num_series, args)) - end - args -end +# -------------------------------------------------------------------------- function _is_arrow_tuple(expr::Expr) expr.head == :tuple && @@ -86,6 +79,7 @@ function replace_recipe_arrows!(expr::Expr) end end +# -------------------------------------------------------------------------- """ This handy macro will process a function definition, replace `-->` commands, and @@ -178,4 +172,6 @@ macro recipe(funcexpr::Expr) end) end +# -------------------------------------------------------------------------- + end # module From 6ef50c5e60d7286808890d436889e682c5999b4d Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 15:17:33 -0400 Subject: [PATCH 008/356] only export macro --- RecipesBase/src/RecipesBase.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index bbb644f64..c85eda47a 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -1,9 +1,9 @@ module RecipesBase export - @recipe, - apply_recipe, - is_key_supported + @recipe + # apply_recipe, + # is_key_supported # a placeholder... this should be overridden by the package which uses the recipe (Plots.jl for example) is_key_supported(k::Symbol) = true @@ -60,10 +60,10 @@ function replace_recipe_arrows!(expr::Expr) expr.args[i] = if quiet # quietly ignore keywords which are not supported - :(is_key_supported($k) ? $set_expr : nothing) + :(RecipesBase.is_key_supported($k) ? $set_expr : nothing) elseif require # error when not supported by the backend - :(is_key_supported($k) ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())")) + :(RecipesBase.is_key_supported($k) ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())")) else set_expr end From d9884aa4bb2e2f2e0c427b15cdfa72f461943ef2 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 15:22:11 -0400 Subject: [PATCH 009/356] readme --- RecipesBase/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 7c518afd5..fd287e328 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -48,6 +48,8 @@ end plot(T(), 5; customcolor = :black, shape=:c) ``` +![](https://cloud.githubusercontent.com/assets/933338/15083906/02a06810-139e-11e6-98a0-dd81c3fb1ad8.png) + In this example, we see lots of the machinery in action. We create a new type `T` which we will use for dispatch, and an optional argument `n`, which will be used to determine the number of series to display. User-defined keyword arguments are passed through, and the From 9e3661a4bbab96069f11efd6ca309e0d342d1b85 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 15:34:17 -0400 Subject: [PATCH 010/356] is_key_supported fix to avoid override warning --- RecipesBase/src/RecipesBase.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index c85eda47a..8aebcdc7c 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -5,8 +5,10 @@ export # apply_recipe, # is_key_supported -# a placeholder... this should be overridden by the package which uses the recipe (Plots.jl for example) -is_key_supported(k::Symbol) = true +# a placeholder... this method should never be called... it's just to establish the +# name so that other packages (Plots.jl for example) can add their own definition +# of RecipesBase.is_key_supported(k::Symbol) +is_key_supported() = true # this holds the recipe definitions to be dispatched on apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}) = () From c360942be38872656c02fde4b147823ee324cc54 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 15:44:42 -0400 Subject: [PATCH 011/356] fix tests; added precompile --- RecipesBase/src/RecipesBase.jl | 3 +++ RecipesBase/test/runtests.jl | 1 + 2 files changed, 4 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 8aebcdc7c..4e72601c8 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -1,3 +1,6 @@ + +__precompile__() + module RecipesBase export diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index edd1698a4..f6f2d7b34 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -2,6 +2,7 @@ using RecipesBase using Base.Test srand(1) +RecipesBase.is_key_supported(k::Symbol) = true type T end From 41284bcf1daf98376ac6d40ad0fbc338ec8c998f Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 21:07:15 -0400 Subject: [PATCH 012/356] readme --- RecipesBase/README.md | 62 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index fd287e328..d2be72fcb 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -15,24 +15,63 @@ data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl other purposes as well. Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. -The `@recipe` macro will process a function definition, replace `-->` commands, and -then add a new version of `apply_recipe` for dispatching on the arguments. +The `@recipe` macro will process a function definition, use `-->` commands to define attributes, and +pass the return value through for further processing (likely by Plots.jl). -Set attributes using the `-->` command, and return a comma separated list of arguments that -should replace the current arguments. +## Why should I care about this package? -The `is_key_supported` method should likely be overridden... by default everything is considered supported. +Many packages have custom types and custom data. There is usually specialized structure, and useful +methods of visualizing that structure and data. This package solves the difficult problem of how to +build generic visualizations of user-defined data types, without adding bulky dependencies on complex +graphics packages. -## An example: +This package is as lightweight as possible. It **exports one macro**, and defines only a few internal methods. +It has **zero dependencies**. + +However, although it is lightweight, it enables a lot. The entirety of the Plots framework becomes available +to any package implementing a recipe. This means that complex plots and subplots can be built with uber-flexibility +using custom combinations of data types. Some examples of applications: + +- Distributions: overlayed density plots for non-normal fitted distributions. +- DataFrames: "Grammar of Graphics"-style inputs using symbols. +- Deep Learning: frameworks for visualization of neural network states and tracking of internal calculations. +- Graphs: flexible, interactive graphs with easily customizable colors, etc. +- Symbolic frameworks: Show sample from complex symbolic distributions + +Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to +create the pictures that are worth a thousand words. + +For more information about Plots, see [the docs](http://plots.readthedocs.io/), and be sure to reference +the [supported keywords](http://plots.readthedocs.io/en/latest/supported/#keyword-arguments). +For additional examples of recipes in the wild, see [MLPlots](https://github.com/JuliaML/MLPlots.jl). +Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. + +## Hello world + +This will build a spiky surface: + +```julia +using Plots; gr() +type T end +@recipe f(::T) = rand(10,10) +surface(T()) +``` + +![](https://cloud.githubusercontent.com/assets/933338/15089193/7a453ec6-13cc-11e6-9ae8-959e98b615dc.png) + +## A real example ```julia # Plots will be the ultimate consumer of our recipe in this example using Plots gr() +# Our user-defined data type type T end -@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) +# This is all we define. It uses a familiar signature, but strips it apart +# in order to add a custom definition to the internal method `RecipesBase.apply_recipe` +@recipe function plot(::T, n = 1; customcolor = :green) :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 45 @@ -42,9 +81,12 @@ end # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots # processing pipeline (see the Pipeline section of the Plots documentation). -# It will plot 5 line plots, all with black circles for markers. -# The markershape argument must be supported, and the zrotation argument's warning -# will be suppressed. The user can override all arguments except markercolor. +# It will plot 5 line plots (a 5-column matrix is returned from the recipe). +# All will have black circles: +# - user override for markershape: :c == :circle +# - customcolor overridden to :black, and markercolor is forced to be customcolor +# If markershape is an unsupported keyword, the call will error. +# By default, a warning will be shown for an unsupported keyword. This will be suppressed for zrotation (:quiet flag). plot(T(), 5; customcolor = :black, shape=:c) ``` From 7ded287080e499404953a807933c2404fb527d71 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 21:09:22 -0400 Subject: [PATCH 013/356] readme --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index d2be72fcb..d4b6aefca 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -36,7 +36,7 @@ using custom combinations of data types. Some examples of applications: - DataFrames: "Grammar of Graphics"-style inputs using symbols. - Deep Learning: frameworks for visualization of neural network states and tracking of internal calculations. - Graphs: flexible, interactive graphs with easily customizable colors, etc. -- Symbolic frameworks: Show sample from complex symbolic distributions +- Symbolic frameworks: sample from complex symbolic distributions. Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. From 31d6f8924a1412c85c29bba2de2ac691b92d07b5 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 6 May 2016 21:13:58 -0400 Subject: [PATCH 014/356] readme --- RecipesBase/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index d4b6aefca..dad7bdced 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -100,3 +100,8 @@ number of series to display. User-defined keyword arguments are passed through, - `quiet`: Suppress unsupported keyword warnings - `require`: Error if keyword is unsupported - `force`: Don't allow user override for this keyword + +### A humble request + +If you build a recipe for your package, please let me know! I'd love to compile both a gallery and +a listing of user-defined recipes, as well as the packages that are available for Plots visualizations. From 6ced3c5e7946d20aaf0ee29f08ac71fd66b0e630 Mon Sep 17 00:00:00 2001 From: Waldir Pimenta Date: Sat, 7 May 2016 18:44:42 +0100 Subject: [PATCH 015/356] readme: various minor fixes & tweaks --- RecipesBase/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index dad7bdced..a7603e778 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -5,15 +5,15 @@ ### Author: Thomas Breloff (@tbreloff) This package implements a handy macro `@recipe` which will define a custom transformation -and attach attributes for user types. It's design is an attempt to simplify and generalize +and attach attributes for user types. Its design is an attempt to simplify and generalize the summary and display of types and data from external packages. With no extra dependencies and minimal code, package authors can describe visualization routines that can be used as components in more complex visualizations. This functionality is primarily geared to turning user types and settings into the -data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, though it could be used for -other purposes as well. Plots has extensive machinery to uniquely take advantage of the simplified -recipe description you define. +data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, +though it could be used for other purposes as well. +Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. The `@recipe` macro will process a function definition, use `-->` commands to define attributes, and pass the return value through for further processing (likely by Plots.jl). @@ -38,8 +38,8 @@ using custom combinations of data types. Some examples of applications: - Graphs: flexible, interactive graphs with easily customizable colors, etc. - Symbolic frameworks: sample from complex symbolic distributions. -Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to -create the pictures that are worth a thousand words. +Really there's very little that *couldn't* be mapped to a useful visualization. +I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://plots.readthedocs.io/), and be sure to reference the [supported keywords](http://plots.readthedocs.io/en/latest/supported/#keyword-arguments). @@ -86,13 +86,14 @@ end # - user override for markershape: :c == :circle # - customcolor overridden to :black, and markercolor is forced to be customcolor # If markershape is an unsupported keyword, the call will error. -# By default, a warning will be shown for an unsupported keyword. This will be suppressed for zrotation (:quiet flag). +# By default, a warning will be shown for an unsupported keyword. +# This will be suppressed for zrotation (:quiet flag). plot(T(), 5; customcolor = :black, shape=:c) ``` ![](https://cloud.githubusercontent.com/assets/933338/15083906/02a06810-139e-11e6-98a0-dd81c3fb1ad8.png) -In this example, we see lots of the machinery in action. We create a new type `T` which +In this example, we see a lot of the machinery in action. We create a new type `T`, which we will use for dispatch, and an optional argument `n`, which will be used to determine the number of series to display. User-defined keyword arguments are passed through, and the `-->` command can be trailed by flags: From 60375e723b0174d9032718d7e4edd491c6ddbd6a Mon Sep 17 00:00:00 2001 From: Tom Breloff Date: Sat, 7 May 2016 14:12:25 -0400 Subject: [PATCH 016/356] Update README.md --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index a7603e778..d6be8664f 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -53,7 +53,7 @@ This will build a spiky surface: ```julia using Plots; gr() type T end -@recipe f(::T) = rand(10,10) +@recipe f(::T) = rand(100,100) surface(T()) ``` From f1847288ae9cda7ac9a3701ba5720c0c8a06ea64 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 11 May 2016 17:56:50 -0400 Subject: [PATCH 017/356] messing around --- RecipesBase/README.md | 18 +++--- RecipesBase/src/RecipesBase.jl | 105 +++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 31 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index d6be8664f..85d66c75f 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -62,9 +62,7 @@ surface(T()) ## A real example ```julia -# Plots will be the ultimate consumer of our recipe in this example -using Plots -gr() +using RecipesBase # Our user-defined data type type T end @@ -72,13 +70,19 @@ type T end # This is all we define. It uses a familiar signature, but strips it apart # in order to add a custom definition to the internal method `RecipesBase.apply_recipe` @recipe function plot(::T, n = 1; customcolor = :green) - :markershape --> :auto, :require - :markercolor --> customcolor, :force - :xrotation --> 45 - :zrotation --> 90, :quiet + markershape --> :auto, :require + markercolor --> customcolor, :force + xrotation --> 45 + zrotation --> 90, :quiet rand(10,n) end +# ---------------------------- + +# Plots will be the ultimate consumer of our recipe in this example +using Plots +gr() + # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots # processing pipeline (see the Pipeline section of the Plots documentation). # It will plot 5 line plots (a 5-column matrix is returned from the recipe). diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 4e72601c8..fbe7f0410 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,18 +6,65 @@ module RecipesBase export @recipe # apply_recipe, + # KW + # PlotData # is_key_supported -# a placeholder... this method should never be called... it's just to establish the -# name so that other packages (Plots.jl for example) can add their own definition -# of RecipesBase.is_key_supported(k::Symbol) -is_key_supported() = true +# 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 # this holds the recipe definitions to be dispatched on -apply_recipe(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}) = () +# the function takes in an attribute dict `d`, a user attributes dict `userkw`, +# and a list of args. +# Our goal is to +apply_recipe(d::Dict{Symbol,Any}, userkw::Dict{Symbol,Any}) = () # -------------------------------------------------------------------------- +# typealias KW Dict{Symbol, Any} + +# immutable PlotData{X,Y,Z} <: Associative{Symbol,Any} +# x::X +# y::Y +# z::Z +# kw::KW +# end +# PlotData(y::) +# # PlotData(data, kw::KW) = PlotData(wrap_tuple(data), kw) +# +# function Base.getindex(d::PlotData, k::Symbol) +# if k == :x +# d.x +# elseif k == :y +# d.y +# elseif k == :z +# d.z +# else +# d.kw[k] +# end +# end +# +# function Base.setindex!(d::PlotData, val, k::Symbol) +# if k == :x +# d.x = val +# elseif k == :y +# d.y = val +# elseif k == :z +# d.z = val +# else +# d.kw[k] = val +# end +# end + +# -------------------------------------------------------------------------- + +@inline to_symbol(s::Symbol) = s +@inline to_symbol(qn::QuoteNode) = qn.value + +# @inline wrap_tuple(tup::Tuple) = tup +# @inline wrap_tuple(v) = (v,) + function _is_arrow_tuple(expr::Expr) expr.head == :tuple && isa(expr.args[1], Expr) && @@ -54,6 +101,9 @@ function replace_recipe_arrows!(expr::Expr) # we are going to recursively swap out `a --> b, flags...` commands if e.head == :(-->) k, v = e.args + if isa(k, Symbol) + k = QuoteNode(k) + end set_expr = if force # forced override user settings @@ -99,26 +149,30 @@ should replace the current arguments. An example: ``` - # Plots will be the ultimate consumer of our recipe in this example - using Plot - gr() - - type T end - - @recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) - :markershape --> :auto, :require - :markercolor --> customcolor, :force - :xrotation --> 5 - :zrotation --> 6, :quiet - rand(10,n) - end +using RecipesBase - # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots - # processing pipeline (see the Pipeline section of the Plots documentation). - # It will plot 5 line plots, all with black circles for markers. - # The markershape argument must be supported, and the zrotation argument's warning - # will be suppressed. The user can override all arguments except markercolor. - plot(T(), 5; customcolor = :black, shape=:c) +# Our custom type that we want to display +type T end + +@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + markershape --> :auto, :require + markercolor --> customcolor, :force + xrotation --> 5 + zrotation --> 6, :quiet + rand(10,n) +end + +# --------------------- + +# Plots will be the ultimate consumer of our recipe in this example +using Plot; gr() + +# This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots +# processing pipeline (see the Pipeline section of the Plots documentation). +# It will plot 5 line plots, all with black circles for markers. +# The markershape argument must be supported, and the zrotation argument's warning +# will be suppressed. The user can override all arguments except markercolor. +plot(T(), 5; customcolor = :black, shape=:c) ``` In this example, we see lots of the machinery in action. We create a new type `T` which @@ -139,6 +193,9 @@ macro recipe(funcexpr::Expr) if !(isa(lhs, Expr) && lhs.head == :call) error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs") end + if length(lhs.args) < 2 + error("Missing function arguments... need something to dispatch on!") + end # for parametric definitions, take the "curly" expression and add the func front = lhs.args[1] From 5228cee874407bcb1a166c5b695a5cea2f45df61 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 11 May 2016 22:10:42 -0400 Subject: [PATCH 018/356] working on overhaul --- RecipesBase/src/RecipesBase.jl | 94 ++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index fbe7f0410..1a32c407b 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -22,6 +22,12 @@ apply_recipe(d::Dict{Symbol,Any}, userkw::Dict{Symbol,Any}) = () # -------------------------------------------------------------------------- +# this holds the data and attributes of one series, and is returned from apply_recipe +immutable Series + d::Dict{Symbol,Any} + args::Tuple +end + # typealias KW Dict{Symbol, Any} # immutable PlotData{X,Y,Z} <: Associative{Symbol,Any} @@ -78,7 +84,42 @@ function _equals_symbol(arg::Expr, sym::Symbol) arg.head == :quote && arg.args[1] == sym end -function replace_recipe_arrows!(expr::Expr) +# build an apply_recipe function header from the recipe function header +function get_function_def(func_signature::Expr) + # for parametric definitions, take the "curly" expression and add the func + front = func_signature.args[1] + func = :(RecipesBase.apply_recipe) + if isa(front, Expr) && front.head == :curly + front.args[1] = func + func = front + end +end + +function create_kw_body(func_signature::Expr) + # get the arg list, stripping out any keyword parameters into a + # bunch of get!(kw, key, value) lines + args = func_signature.args[2:end] + kw_body = Expr(:block) + if isa(args[1], Expr) && args[1].head == :parameters + for kwpair in args[1].args + k, v = kwpair.args + push!(kw_body.args, :($k = get!(kw, $(QuoteNode(k)), $v))) + end + args = args[2:end] + end + args, kw_body +end + +# process the body of the recipe recursively. +# when we see the series macro, we split that block off: + # let + # d2 = copy(d) + # + # Series(d2, block_return) + # end +# and we push this block onto the series_blocks list. +# then at the end we push the main body onto the series list +function process_recipe_body!(expr::Expr, series_blocks::Vector{Expr}) for (i,e) in enumerate(expr.args) if isa(e,Expr) @@ -128,7 +169,7 @@ function replace_recipe_arrows!(expr::Expr) 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) - replace_recipe_arrows!(e) + process_recipe_body!(e) end end end @@ -185,51 +226,40 @@ number of series to display. User-defined keyword arguments are passed through, - force: Don't allow user override for this keyword """ macro recipe(funcexpr::Expr) - lhs, body = funcexpr.args + func_signature, func_body = funcexpr.args if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end - if !(isa(lhs, Expr) && lhs.head == :call) - error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs") + if !(isa(func_signature, Expr) && func_signature.head == :call) + error("Expected `func_signature = ...` with func_signature as a call Expr... got: $func_signature") end - if length(lhs.args) < 2 + if length(func_signature.args) < 2 error("Missing function arguments... need something to dispatch on!") end - # for parametric definitions, take the "curly" expression and add the func - front = lhs.args[1] - func = :(RecipesBase.apply_recipe) - if isa(front, Expr) && front.head == :curly - front.args[1] = func - func = front - end - - # get the arg list, stripping out any keyword parameters into a - # bunch of get!(kw, key, value) lines - args = lhs.args[2:end] - kw_body = Expr(:block) - if isa(args[1], Expr) && args[1].head == :parameters - for kwpair in args[1].args - k, v = kwpair.args - push!(kw_body.args, :($k = get!(kw, $(QuoteNode(k)), $v))) - end - args = args[2:end] - end + func = get_function_def(func_signature) + args, kw_body = create_kw_body(func_signature) + # this is where the receipe func_body is processed # replace all the key => value lines with argument setting logic - replace_recipe_arrows!(body) + # and break up by series. + series_blocks = Expr[] + process_recipe_body!(func_body, series_blocks) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed esc(quote function $func(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, $(args...); issubplot=false) $kw_body - ret = $body - if typeof(ret) <: Tuple - ret - else - (ret,) - end + series = Series[] + $(series_blocks...) + series + # ret = $func_body + # Series(d, if typeof(ret) <: Tuple + # ret + # else + # (ret,) + # end) end end) end From 3dd0f7ea17ebd9b8c215183d62750f9d1c28e62b Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Thu, 12 May 2016 12:31:30 -0400 Subject: [PATCH 019/356] working on recipes overhaul --- RecipesBase/src/RecipesBase.jl | 47 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 1a32c407b..9ac44f9e5 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -4,7 +4,8 @@ __precompile__() module RecipesBase export - @recipe + @recipe, + RecipeData # apply_recipe, # KW # PlotData @@ -23,7 +24,7 @@ apply_recipe(d::Dict{Symbol,Any}, userkw::Dict{Symbol,Any}) = () # -------------------------------------------------------------------------- # this holds the data and attributes of one series, and is returned from apply_recipe -immutable Series +immutable RecipeData d::Dict{Symbol,Any} args::Tuple end @@ -68,11 +69,12 @@ end @inline to_symbol(s::Symbol) = s @inline to_symbol(qn::QuoteNode) = qn.value -# @inline wrap_tuple(tup::Tuple) = tup -# @inline wrap_tuple(v) = (v,) +@inline wrap_tuple(tup::Tuple) = tup +@inline wrap_tuple(v) = (v,) +# check for flags as part of the `-->` expression function _is_arrow_tuple(expr::Expr) - expr.head == :tuple && + expr.head == :tuple && !isempty(expr.args) && isa(expr.args[1], Expr) && expr.args[1].head == :(-->) end @@ -103,7 +105,7 @@ function create_kw_body(func_signature::Expr) if isa(args[1], Expr) && args[1].head == :parameters for kwpair in args[1].args k, v = kwpair.args - push!(kw_body.args, :($k = get!(kw, $(QuoteNode(k)), $v))) + push!(kw_body.args, :($k = get!(d, $(QuoteNode(k)), $v))) end args = args[2:end] end @@ -115,13 +117,15 @@ end # let # d2 = copy(d) # - # Series(d2, block_return) + # RecipeData(d2, block_return) # end # and we push this block onto the series_blocks list. # then at the end we push the main body onto the series list -function process_recipe_body!(expr::Expr, series_blocks::Vector{Expr}) +function process_recipe_body!(expr::Expr) + # @show expr for (i,e) in enumerate(expr.args) if isa(e,Expr) + # @show e # process trailing flags, like: # a --> b, :quiet, :force @@ -136,6 +140,7 @@ function process_recipe_body!(expr::Expr, series_blocks::Vector{Expr}) force = true end end + # @show e e = e.args[1] end @@ -166,6 +171,8 @@ function process_recipe_body!(expr::Expr, series_blocks::Vector{Expr}) # @show quiet, force, expr.args[i] + # TODO elseif it's a @series macrocall, add a series block and push to the `series` list + 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) @@ -244,24 +251,30 @@ macro recipe(funcexpr::Expr) # this is where the receipe func_body is processed # replace all the key => value lines with argument setting logic # and break up by series. - series_blocks = Expr[] - process_recipe_body!(func_body, series_blocks) + # series_blocks = Expr[] + process_recipe_body!(func_body) + + # dump(func_body, 20) + @show func_body - # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed - esc(quote - function $func(d::Dict{Symbol,Any}, kw::Dict{Symbol,Any}, $(args...); issubplot=false) + # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. + # we are creating a vector of RecipeData objects, one per series. + funcdef = esc(quote + function $func(d::Dict{Symbol,Any}, $(args...); issubplot=false) $kw_body - series = Series[] - $(series_blocks...) - series + series_list = RecipeData[] + push!(series_list, RecipeData(d, RecipesBase.wrap_tuple($func_body))) + series_list # ret = $func_body - # Series(d, if typeof(ret) <: Tuple + # RecipeData(d, if typeof(ret) <: Tuple # ret # else # (ret,) # end) end end) + @show funcdef + funcdef end # -------------------------------------------------------------------------- From ad13aae0e8d38b9e8c8fd0446243870315701db5 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Thu, 12 May 2016 14:00:20 -0400 Subject: [PATCH 020/356] working on recipes overhaul --- RecipesBase/src/RecipesBase.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 9ac44f9e5..b3b39fc5b 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -95,6 +95,7 @@ function get_function_def(func_signature::Expr) front.args[1] = func func = front end + func end function create_kw_body(func_signature::Expr) @@ -255,7 +256,7 @@ macro recipe(funcexpr::Expr) process_recipe_body!(func_body) # dump(func_body, 20) - @show func_body + # @show func_body # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. @@ -263,7 +264,10 @@ macro recipe(funcexpr::Expr) function $func(d::Dict{Symbol,Any}, $(args...); issubplot=false) $kw_body series_list = RecipeData[] - push!(series_list, RecipeData(d, RecipesBase.wrap_tuple($func_body))) + func_return = $func_body + if func_return != nothing + push!(series_list, RecipeData(d, RecipesBase.wrap_tuple(func_return))) + end series_list # ret = $func_body # RecipeData(d, if typeof(ret) <: Tuple @@ -273,6 +277,7 @@ macro recipe(funcexpr::Expr) # end) end end) + @show funcdef funcdef end From c3a6173327fc1d68028cd754d07fd4c454707cb7 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 13 May 2016 00:18:26 -0400 Subject: [PATCH 021/356] removed show funcdef --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b3b39fc5b..7bf2ad874 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -278,7 +278,7 @@ macro recipe(funcexpr::Expr) end end) - @show funcdef + # @show funcdef funcdef end From c6d7ffb74debf0a58f9611ebde6b2349b3bb3423 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 13 May 2016 22:53:49 -0400 Subject: [PATCH 022/356] debug --- RecipesBase/src/RecipesBase.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 7bf2ad874..a159fc0a3 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -21,6 +21,11 @@ function is_key_supported end # Our goal is to apply_recipe(d::Dict{Symbol,Any}, userkw::Dict{Symbol,Any}) = () +const _debug_recipes = Bool[false] +function debug(v::Bool = true) + _debug_recipes[1] = v +end + # -------------------------------------------------------------------------- # this holds the data and attributes of one series, and is returned from apply_recipe @@ -262,6 +267,9 @@ macro recipe(funcexpr::Expr) # we are creating a vector of RecipeData objects, one per series. funcdef = esc(quote function $func(d::Dict{Symbol,Any}, $(args...); issubplot=false) + if RecipesBase._debug_recipes[1] + println("apply_recipe args: ", $args) + end $kw_body series_list = RecipeData[] func_return = $func_body From 6614c90b5f9c696a03a8defa0afb90d0d4c09cc7 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Thu, 19 May 2016 11:53:36 -0400 Subject: [PATCH 023/356] cleanup --- RecipesBase/src/RecipesBase.jl | 65 +++------------------------------- 1 file changed, 4 insertions(+), 61 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index a159fc0a3..4066d8084 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,20 +6,15 @@ module RecipesBase export @recipe, RecipeData - # apply_recipe, - # KW - # PlotData - # is_key_supported # 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 -# this holds the recipe definitions to be dispatched on -# the function takes in an attribute dict `d`, a user attributes dict `userkw`, -# and a list of args. -# Our goal is to -apply_recipe(d::Dict{Symbol,Any}, userkw::Dict{Symbol,Any}) = () +# This holds the recipe definitions to be dispatched on +# the function takes in an attribute dict `d` and a list of args. +# This default definition specifies the "no-arg" case. +apply_recipe(d::Dict{Symbol,Any}) = () const _debug_recipes = Bool[false] function debug(v::Bool = true) @@ -34,41 +29,6 @@ immutable RecipeData args::Tuple end -# typealias KW Dict{Symbol, Any} - -# immutable PlotData{X,Y,Z} <: Associative{Symbol,Any} -# x::X -# y::Y -# z::Z -# kw::KW -# end -# PlotData(y::) -# # PlotData(data, kw::KW) = PlotData(wrap_tuple(data), kw) -# -# function Base.getindex(d::PlotData, k::Symbol) -# if k == :x -# d.x -# elseif k == :y -# d.y -# elseif k == :z -# d.z -# else -# d.kw[k] -# end -# end -# -# function Base.setindex!(d::PlotData, val, k::Symbol) -# if k == :x -# d.x = val -# elseif k == :y -# d.y = val -# elseif k == :z -# d.z = val -# else -# d.kw[k] = val -# end -# end - # -------------------------------------------------------------------------- @inline to_symbol(s::Symbol) = s @@ -128,10 +88,8 @@ end # and we push this block onto the series_blocks list. # then at the end we push the main body onto the series list function process_recipe_body!(expr::Expr) - # @show expr for (i,e) in enumerate(expr.args) if isa(e,Expr) - # @show e # process trailing flags, like: # a --> b, :quiet, :force @@ -146,7 +104,6 @@ function process_recipe_body!(expr::Expr) force = true end end - # @show e e = e.args[1] end @@ -175,8 +132,6 @@ function process_recipe_body!(expr::Expr) set_expr end - # @show quiet, force, expr.args[i] - # TODO elseif it's a @series macrocall, add a series block and push to the `series` list elseif e.head != :call @@ -257,12 +212,8 @@ macro recipe(funcexpr::Expr) # this is where the receipe func_body is processed # replace all the key => value lines with argument setting logic # and break up by series. - # series_blocks = Expr[] process_recipe_body!(func_body) - # dump(func_body, 20) - # @show func_body - # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. funcdef = esc(quote @@ -277,16 +228,8 @@ macro recipe(funcexpr::Expr) push!(series_list, RecipeData(d, RecipesBase.wrap_tuple(func_return))) end series_list - # ret = $func_body - # RecipeData(d, if typeof(ret) <: Tuple - # ret - # else - # (ret,) - # end) end end) - - # @show funcdef funcdef end From 36e33a8673629bed3f80b6377ac81ace6d6eb3fe Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Thu, 26 May 2016 23:47:43 -0400 Subject: [PATCH 024/356] added force operator --- RecipesBase/src/RecipesBase.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 4066d8084..2a4b7b905 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -107,7 +107,15 @@ function process_recipe_body!(expr::Expr) e = e.args[1] end + # 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 + # 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 if isa(k, Symbol) From 269375edf143f6b6bce59018bd8edade4ab06ede Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 27 May 2016 12:54:52 -0400 Subject: [PATCH 025/356] series macro --- RecipesBase/src/RecipesBase.jl | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 2a4b7b905..42750f6ac 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -5,6 +5,7 @@ module RecipesBase export @recipe, + @series, RecipeData # a placeholder to establish the name so that other packages (Plots.jl for example) @@ -241,6 +242,41 @@ macro recipe(funcexpr::Expr) funcdef end + +# -------------------------------------------------------------------------- + +""" +Meant to be used inside a recipe to add additional RecipeData objects to the list: + +``` +@recipe function f(::T) + # everything get this setting + linecolor --> :red + + @series begin + # this setting is only for this series + fillcolor := :green + + # return the args, just like in recipes + rand(10) + end + + # this is the main series... though it can be skipped by returning nothing. + # note: a @series block returns nothing + rand(100) +end +``` +""" +macro series(expr::Expr) + esc(quote + let d = copy(d) + args = $expr + push!(series_list, RecipeData(d, RecipesBase.wrap_tuple(args))) + nothing + end + end) +end + # -------------------------------------------------------------------------- end # module From 4ad2d94faa1a6c5f54a77f2891d7d9882bfe4057 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Thu, 9 Jun 2016 08:59:41 -0400 Subject: [PATCH 026/356] make tests pass --- RecipesBase/test/runtests.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index f6f2d7b34..2a695dc21 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -16,13 +16,13 @@ end # this is similar to how Plots would call the method typealias KW Dict{Symbol,Any} -d = KW() -kw = KW(:customcolor => :red) -args = RecipesBase.apply_recipe(d, kw, T(), 2; issubplot = false) +d = KW(:customcolor => :red) +data_list = RecipesBase.apply_recipe(d, T(), 2) # make sure the attribute dictionary was populated correctly, and the returned arguments are as expected -@test args == (srand(1); (rand(10,2),)) +@test data_list[1].args == (srand(1); (rand(10,2),)) @test d == KW( + :customcolor => :red, :markershape => :auto, :markercolor => :red, :xrotation => 5, From b27cb26b66b0fb003da970a3af8c4b226c808462 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 10 Jun 2016 15:46:25 -0400 Subject: [PATCH 027/356] fix RecipeData not defined; closes #7 --- RecipesBase/src/RecipesBase.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 42750f6ac..ccf457e33 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -231,10 +231,10 @@ macro recipe(funcexpr::Expr) println("apply_recipe args: ", $args) end $kw_body - series_list = RecipeData[] + series_list = RecipesBase.RecipeData[] func_return = $func_body if func_return != nothing - push!(series_list, RecipeData(d, RecipesBase.wrap_tuple(func_return))) + push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) end series_list end @@ -271,7 +271,7 @@ macro series(expr::Expr) esc(quote let d = copy(d) args = $expr - push!(series_list, RecipeData(d, RecipesBase.wrap_tuple(args))) + push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(args))) nothing end end) From 0c40e1e3b866a32c752bd29e65ebb3b4a027a05a Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Mon, 27 Jun 2016 13:41:54 -0400 Subject: [PATCH 028/356] cleanup_body and readme updates --- RecipesBase/README.md | 52 ++++++++++++++++++++++++++++------ RecipesBase/src/RecipesBase.jl | 9 ++++-- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 85d66c75f..eb47f946f 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -4,7 +4,7 @@ ### Author: Thomas Breloff (@tbreloff) -This package implements a handy macro `@recipe` which will define a custom transformation +This package implements handy macros `@recipe` and `@series` which will define a custom transformation and attach attributes for user types. Its design is an attempt to simplify and generalize the summary and display of types and data from external packages. With no extra dependencies and minimal code, package authors can describe visualization routines that can be used @@ -13,7 +13,7 @@ as components in more complex visualizations. This functionality is primarily geared to turning user types and settings into the data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, though it could be used for other purposes as well. -Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. +Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. See the [Plots documentation on recipes](http://plots.readthedocs.io/en/latest/recipes/) for more information. The `@recipe` macro will process a function definition, use `-->` commands to define attributes, and pass the return value through for further processing (likely by Plots.jl). @@ -25,7 +25,7 @@ methods of visualizing that structure and data. This package solves the difficu build generic visualizations of user-defined data types, without adding bulky dependencies on complex graphics packages. -This package is as lightweight as possible. It **exports one macro**, and defines only a few internal methods. +This package is as lightweight as possible. It exports two macros, and defines only a few internal methods. It has **zero dependencies**. However, although it is lightweight, it enables a lot. The entirety of the Plots framework becomes available @@ -43,7 +43,7 @@ I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://plots.readthedocs.io/), and be sure to reference the [supported keywords](http://plots.readthedocs.io/en/latest/supported/#keyword-arguments). -For additional examples of recipes in the wild, see [MLPlots](https://github.com/JuliaML/MLPlots.jl). +For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. ## Hello world @@ -70,11 +70,11 @@ type T end # This is all we define. It uses a familiar signature, but strips it apart # in order to add a custom definition to the internal method `RecipesBase.apply_recipe` @recipe function plot(::T, n = 1; customcolor = :green) - markershape --> :auto, :require - markercolor --> customcolor, :force - xrotation --> 45 - zrotation --> 90, :quiet - rand(10,n) + markershape --> :auto # if markershape is unset, make it :auto + markercolor := customcolor # force markercolor to be customcolor + xrotation --> 45 # if xrotation is unset, make it 45 + zrotation --> 90 # if zrotation is unset, make it 90 + rand(10,n) # return the arguments (input data) for the next recipe end # ---------------------------- @@ -106,6 +106,40 @@ number of series to display. User-defined keyword arguments are passed through, - `require`: Error if keyword is unsupported - `force`: Don't allow user override for this keyword +### Series + +For complex visualizations, it can be beneficial to create many series inside a single recipe. The `@series` macro will make a copy of the attribute dictionary `d`, and add a new RecipeData object to the returned list. See the [case studies](http://plots.readthedocs.io/en/latest/recipes/#case-studies) for more details. + +### Generated code + +For the example above, the following code is generated. In it, you can see the managing of the scope of the keyword args, creation of a definition for `RecipesBase.apply_recipe`, setting attributes, and creating the list of `RecipeData` objects: + +```julia +function RecipesBase.apply_recipe(d::Dict{Symbol,Any},::T,n=1) + if RecipesBase._debug_recipes[1] + println("apply_recipe args: ",Any[:(::T),:(n=1)]) + end + begin + customcolor = get!(d,:customcolor,:green) + end + series_list = RecipesBase.RecipeData[] + func_return = begin + get!(d,:markershape,:auto) + d[:markercolor] = customcolor + get!(d,:xrotation,45) + get!(d,:zrotation,90) + rand(10,n) + end + if func_return != nothing + push!(series_list,RecipesBase.RecipeData(d,RecipesBase.wrap_tuple(func_return))) + end + begin + RecipesBase.is_key_supported(:customcolor) || delete!(d,:customcolor) + end + series_list +end +``` + ### A humble request If you build a recipe for your package, please let me know! I'd love to compile both a gallery and diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index ccf457e33..fe6218a41 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -69,14 +69,16 @@ function create_kw_body(func_signature::Expr) # bunch of get!(kw, key, value) lines args = func_signature.args[2:end] kw_body = Expr(:block) + cleanup_body = Expr(:block) if isa(args[1], Expr) && args[1].head == :parameters for kwpair in args[1].args k, v = kwpair.args push!(kw_body.args, :($k = get!(d, $(QuoteNode(k)), $v))) + push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!(d, $(QuoteNode(k))))) end args = args[2:end] end - args, kw_body + args, kw_body, cleanup_body end # process the body of the recipe recursively. @@ -216,7 +218,7 @@ macro recipe(funcexpr::Expr) end func = get_function_def(func_signature) - args, kw_body = create_kw_body(func_signature) + args, kw_body, cleanup_body = create_kw_body(func_signature) # this is where the receipe func_body is processed # replace all the key => value lines with argument setting logic @@ -226,7 +228,7 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. funcdef = esc(quote - function $func(d::Dict{Symbol,Any}, $(args...); issubplot=false) + function $func(d::Dict{Symbol,Any}, $(args...)) if RecipesBase._debug_recipes[1] println("apply_recipe args: ", $args) end @@ -236,6 +238,7 @@ macro recipe(funcexpr::Expr) if func_return != nothing push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) end + $cleanup_body series_list end end) From 22ecf174ee5526bc69efac0f42bf17df1a7188ff Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Mon, 27 Jun 2016 22:21:24 -0400 Subject: [PATCH 029/356] move cleanup_body earlier --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index fe6218a41..7c3c1f5fb 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -233,12 +233,12 @@ macro recipe(funcexpr::Expr) println("apply_recipe args: ", $args) end $kw_body + $cleanup_body series_list = RecipesBase.RecipeData[] func_return = $func_body if func_return != nothing push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) end - $cleanup_body series_list end end) From 42d97321c061c2f2cec7575c317811cb7ca829c6 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 29 Jun 2016 12:23:19 -0400 Subject: [PATCH 030/356] readme --- RecipesBase/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index eb47f946f..8b1fe72de 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -13,7 +13,7 @@ as components in more complex visualizations. This functionality is primarily geared to turning user types and settings into the data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, though it could be used for other purposes as well. -Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. See the [Plots documentation on recipes](http://plots.readthedocs.io/en/latest/recipes/) for more information. +Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. See the [Plots documentation on recipes](http://juliaplots.github.io/recipes/) for more information. The `@recipe` macro will process a function definition, use `-->` commands to define attributes, and pass the return value through for further processing (likely by Plots.jl). @@ -42,7 +42,7 @@ Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://plots.readthedocs.io/), and be sure to reference -the [supported keywords](http://plots.readthedocs.io/en/latest/supported/#keyword-arguments). +the [supported keywords](http://juliaplots.github.io/supported/#keyword-arguments). For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. @@ -108,7 +108,7 @@ number of series to display. User-defined keyword arguments are passed through, ### Series -For complex visualizations, it can be beneficial to create many series inside a single recipe. The `@series` macro will make a copy of the attribute dictionary `d`, and add a new RecipeData object to the returned list. See the [case studies](http://plots.readthedocs.io/en/latest/recipes/#case-studies) for more details. +For complex visualizations, it can be beneficial to create many series inside a single recipe. The `@series` macro will make a copy of the attribute dictionary `d`, and add a new RecipeData object to the returned list. See the [case studies](http://juliaplots.github.io/recipes/#case-studies) for more details. ### Generated code From 2397a590feb9aedb3bef081fc094679d5db0b132 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 29 Jun 2016 12:30:51 -0400 Subject: [PATCH 031/356] readme --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 8b1fe72de..24d12dcb9 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -41,7 +41,7 @@ using custom combinations of data types. Some examples of applications: Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. -For more information about Plots, see [the docs](http://plots.readthedocs.io/), and be sure to reference +For more information about Plots, see [the docs](http://juliaplots.github.io/), and be sure to reference the [supported keywords](http://juliaplots.github.io/supported/#keyword-arguments). For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. From e351f783542e290391e426ff4c2997f227c2abb1 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 20 Jul 2016 09:38:13 -0400 Subject: [PATCH 032/356] require 0.5 --- RecipesBase/REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index d5d646713..70e314a25 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.4 +julia 0.5- From ba38d748fef5149bb219ae412e0887dda1d421d2 Mon Sep 17 00:00:00 2001 From: Scott Thomas Date: Thu, 13 Oct 2016 17:15:54 +0100 Subject: [PATCH 033/356] Fix typo in recipe macro docstring example `using Plot` -> `using Plots` --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 7c3c1f5fb..2b965b443 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -185,7 +185,7 @@ end # --------------------- # Plots will be the ultimate consumer of our recipe in this example -using Plot; gr() +using Plots; gr() # This call will implicitly call `RecipesBase.apply_recipe` as part of the Plots # processing pipeline (see the Pipeline section of the Plots documentation). From 0f5692f683c054d0b09bda085ec79227664adcd5 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 16 May 2017 17:29:20 -0700 Subject: [PATCH 034/356] Update CI URLs to point to new caching infrastructure --- RecipesBase/appveyor.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml index d3309ec80..e6297f310 100644 --- a/RecipesBase/appveyor.yml +++ b/RecipesBase/appveyor.yml @@ -1,9 +1,9 @@ environment: matrix: - - JULIAVERSION: "julialang/bin/winnt/x86/0.4/julia-0.4-latest-win32.exe" - - JULIAVERSION: "julialang/bin/winnt/x64/0.4/julia-0.4-latest-win64.exe" - - JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe" - - JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.4/julia-0.4-latest-win32.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.4/julia-0.4-latest-win64.exe" + - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" + - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" branches: only: @@ -17,9 +17,10 @@ notifications: on_build_status_changed: false install: + - ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" # Download most recent Julia Windows binary - ps: (new-object net.webclient).DownloadFile( - $("http://s3.amazonaws.com/"+$env:JULIAVERSION), + $env:JULIA_URL, "C:\projects\julia-binary.exe") # Run installer silently, output to C:\projects\julia - C:\projects\julia-binary.exe /S /D=C:\projects\julia From 5b5d5089a9c4351d11bb215c6bf51240f7ee1e81 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 22 May 2017 22:56:00 -0400 Subject: [PATCH 035/356] use version number instead of release in .travis.yml release will change over time, but your REQUIRE file says this package supports julia 0.5 so it should continue to be tested --- RecipesBase/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index e5c48ff5e..df52a8fb4 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - release + - 0.5 - nightly notifications: email: false From d2fec2c8645e99bf096d34da65149fe368921bf1 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Fri, 28 Apr 2017 22:42:10 -0700 Subject: [PATCH 036/356] Move @userplot to RecipesBase It makes sense. It's used in libraries which use recipes but don't want to depend directly on Plots.jl. For example: PlotRecipes.jl. --- RecipesBase/src/RecipesBase.jl | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 2b965b443..024c70382 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -282,4 +282,45 @@ end # -------------------------------------------------------------------------- +""" +You can easily define your own plotting recipes with convenience methods: +``` +@userplot type GroupHist + args +end +@recipe function f(gh::GroupHist) + # set some attributes, add some series, using gh.args as input +end +# now you can plot like: +grouphist(rand(1000,4)) +``` +""" +macro userplot(expr) + _userplot(expr) +end + +function _userplot(expr::Expr) + if expr.head != :type + errror("Must call userplot on a type/immutable expression. Got: $expr") + end + + typename = expr.args[2] + funcname = Symbol(lowercase(string(typename))) + funcname2 = Symbol(funcname, "!") + + # return a code block with the type definition and convenience plotting methods + esc(quote + $expr + export $funcname, $funcname2 + $funcname(args...; kw...) = plot($typename(args); kw...) + $funcname2(args...; kw...) = plot!($typename(args); kw...) + end) +end + +function _userplot(sym::Symbol) + _userplot(:(type $sym + args + end)) +end + end # module From edc7b4f083c8cab93831417f8b0b83b225c7e809 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 30 Apr 2017 16:57:21 -0700 Subject: [PATCH 037/356] Update RecipesBase.jl --- RecipesBase/src/RecipesBase.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 024c70382..f9ea2d8b5 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -8,6 +8,11 @@ export @series, RecipeData +# a placeholder to establish the name so that other packages (Plots.jl for example) +# can add their own definition of RecipesBase.plot since RecipesBase is the common +# dependency of the Plots ecosystem +function plot 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 From 4b71d0a3be73207fe528e0903a25ca11a34a4fa2 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 05:47:03 -0700 Subject: [PATCH 038/356] export `@userplot` --- RecipesBase/src/RecipesBase.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index f9ea2d8b5..dac61bdd9 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,6 +6,7 @@ module RecipesBase export @recipe, @series, + @userplot, RecipeData # a placeholder to establish the name so that other packages (Plots.jl for example) From 38d97d4dae9530bf52016fb3a80b408f6a94c04c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 06:27:14 -0700 Subject: [PATCH 039/356] add abstract types --- RecipesBase/src/RecipesBase.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index dac61bdd9..55497be44 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -7,7 +7,15 @@ export @recipe, @series, @userplot, - RecipeData + RecipeData, + AbstractBackend, + AbstractPlot, + AbstractLayout + +# Common abstract types for the Plots ecosystem +abstract AbstractBackend +abstract AbstractPlot{T<:AbstractBackend} +abstract AbstractLayout # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.plot since RecipesBase is the common From 63b51401ac53ac6484c06a9fcdf9f0e94e155789 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 16:43:32 -0700 Subject: [PATCH 040/356] define _cycle --- RecipesBase/src/RecipesBase.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 55497be44..9afbf84ef 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -26,6 +26,10 @@ function plot end # can add their own definition of RecipesBase.is_key_supported(k::Symbol) function is_key_supported end +# a commonly used function in recipes, thus defined here for Plots.jl to extend +# not related to Base.cycle +function _cycle end + # This holds the recipe definitions to be dispatched on # the function takes in an attribute dict `d` and a list of args. # This default definition specifies the "no-arg" case. From 544a80e015ad4bf5c55d6a21563d766a10e0c669 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 16:47:46 -0700 Subject: [PATCH 041/356] compat the abstract type --- RecipesBase/REQUIRE | 1 + RecipesBase/src/RecipesBase.jl | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 70e314a25..8ceed1789 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1,2 @@ julia 0.5- +compat 0.17.0 diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 9afbf84ef..0dbc15282 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -3,6 +3,8 @@ __precompile__() module RecipesBase +using Compat + export @recipe, @series, @@ -13,9 +15,9 @@ export AbstractLayout # Common abstract types for the Plots ecosystem -abstract AbstractBackend -abstract AbstractPlot{T<:AbstractBackend} -abstract AbstractLayout +@compat abstract type AbstractBackend end +@compat abstract type AbstractPlot{T<:AbstractBackend} end +@compat abstract type AbstractLayout end # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.plot since RecipesBase is the common From 27ab37883d8cf232d1cb5c7cf8a2503448822bd1 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 16:56:14 -0700 Subject: [PATCH 042/356] add `@shorthands` --- RecipesBase/src/RecipesBase.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 0dbc15282..e90522e11 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -9,6 +9,7 @@ export @recipe, @series, @userplot, + @shorthands, RecipeData, AbstractBackend, AbstractPlot, @@ -343,4 +344,16 @@ function _userplot(sym::Symbol) end)) end +#---------------------------------------------------------------------------- + +# define and export shorthand plotting method definitions +macro shorthands(funcname::Symbol) + funcname2 = Symbol(funcname, "!") + esc(quote + export $funcname, $funcname2 + $funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname))) + $funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname))) + end) +end + end # module From 76b8df01e7c7f9290da22e8088a8edbd39c49e9c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 16:57:04 -0700 Subject: [PATCH 043/356] fix Compat --- RecipesBase/REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 8ceed1789..8dd2b2ec7 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1,2 +1,2 @@ julia 0.5- -compat 0.17.0 +Compat 0.17.0 From f26f8258665d03b8e0b7e86265d724236f989974 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 1 May 2017 17:03:10 -0700 Subject: [PATCH 044/356] Meta.quot --- RecipesBase/src/RecipesBase.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e90522e11..b7f6b3bb9 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -351,8 +351,8 @@ macro shorthands(funcname::Symbol) funcname2 = Symbol(funcname, "!") esc(quote export $funcname, $funcname2 - $funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname))) - $funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname))) + $funcname(args...; kw...) = plot(args...; kw..., seriestype = $(Meta.quot(funcname))) + $funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(Meta.quot(funcname))) end) end From 716d8d975aeaacbcc736f60ecc210f0a90227c90 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 8 May 2017 06:44:14 -0700 Subject: [PATCH 045/356] no _cycle in RecipesBase --- RecipesBase/src/RecipesBase.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b7f6b3bb9..47352a5da 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -29,10 +29,6 @@ function plot end # can add their own definition of RecipesBase.is_key_supported(k::Symbol) function is_key_supported end -# a commonly used function in recipes, thus defined here for Plots.jl to extend -# not related to Base.cycle -function _cycle end - # This holds the recipe definitions to be dispatched on # the function takes in an attribute dict `d` and a list of args. # This default definition specifies the "no-arg" case. From ab2adb97ccec3fdd99cec5bff50065ba9af252a6 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 8 May 2017 15:46:34 -0700 Subject: [PATCH 046/356] no compat, require 0.6 --- RecipesBase/REQUIRE | 3 +-- RecipesBase/src/RecipesBase.jl | 8 +++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 8dd2b2ec7..137767a42 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1,2 +1 @@ -julia 0.5- -Compat 0.17.0 +julia 0.6 diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 47352a5da..4da95ca3f 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -3,8 +3,6 @@ __precompile__() module RecipesBase -using Compat - export @recipe, @series, @@ -16,9 +14,9 @@ export AbstractLayout # Common abstract types for the Plots ecosystem -@compat abstract type AbstractBackend end -@compat abstract type AbstractPlot{T<:AbstractBackend} end -@compat abstract type AbstractLayout end +abstract type AbstractBackend end +abstract type AbstractPlot{T<:AbstractBackend} end +abstract type AbstractLayout end # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.plot since RecipesBase is the common From 6175503e38df05490ae6d9cbebed3cbb0cbbc96b Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sun, 14 May 2017 13:54:58 -0700 Subject: [PATCH 047/356] animate --- RecipesBase/src/RecipesBase.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 4da95ca3f..faa6731d0 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -23,6 +23,11 @@ abstract type AbstractLayout end # dependency of the Plots ecosystem function plot end +# a placeholder to establish the name so that other packages (Plots.jl for example) +# can add their own definition of RecipesBase.animate since RecipesBase is the common +# dependency of the Plots ecosystem +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 From 21006caa48a37bbe9fecceda9d560b9e1e07f5bb Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sun, 14 May 2017 13:57:21 -0700 Subject: [PATCH 048/356] add to animate comment --- RecipesBase/src/RecipesBase.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index faa6731d0..1265aa6b6 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -25,7 +25,8 @@ function plot end # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.animate since RecipesBase is the common -# dependency of the Plots ecosystem +# dependency of the Plots ecosystem. Plots.jl will handle the basic cases, while +# other packages can now extend for their types function animate end # a placeholder to establish the name so that other packages (Plots.jl for example) From 6c2412d33ba1fa0d2832f5e8b14c73681012af58 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Fri, 9 Jun 2017 09:15:27 -0700 Subject: [PATCH 049/356] update test versions --- RecipesBase/.travis.yml | 2 +- RecipesBase/appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index df52a8fb4..e11c7f163 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - 0.5 + - 0.6 - nightly notifications: email: false diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml index e6297f310..19479ef9b 100644 --- a/RecipesBase/appveyor.yml +++ b/RecipesBase/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.4/julia-0.4-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.4/julia-0.4-latest-win64.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.4/julia-0.6-latest-win32.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.4/julia-0.6-latest-win64.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" From 97876649037f876bea09a3822118a13be740403d Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Fri, 9 Jun 2017 09:29:32 -0700 Subject: [PATCH 050/356] make @tkelman version updates --- RecipesBase/REQUIRE | 2 +- RecipesBase/appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 137767a42..e773e5c55 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.6 +julia 0.6-pre diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml index 19479ef9b..b038c7696 100644 --- a/RecipesBase/appveyor.yml +++ b/RecipesBase/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.4/julia-0.6-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.4/julia-0.6-latest-win64.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" From 123b003df076e1e45f3b4cc5d557870fe74bb191 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 28 Jul 2017 14:51:38 +0200 Subject: [PATCH 051/356] allow where syntax --- RecipesBase/src/RecipesBase.jl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 1265aa6b6..777d6767c 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -74,20 +74,23 @@ function _equals_symbol(arg::Expr, sym::Symbol) end # build an apply_recipe function header from the recipe function header -function get_function_def(func_signature::Expr) +function get_where_args(func_signature::Expr) # for parametric definitions, take the "curly" expression and add the func front = func_signature.args[1] - func = :(RecipesBase.apply_recipe) - if isa(front, Expr) && front.head == :curly - front.args[1] = func - func = front + where_args = if isa(front, Expr) && front.head == :curly + front.args[2:end] + elseif func_signature.head == :where + func_signature.args[2:end] + else + [] end - func + where_args end function create_kw_body(func_signature::Expr) # get the arg list, stripping out any keyword parameters into a # bunch of get!(kw, key, value) lines + func_signature.head == :where && return create_kw_body(func_signature.args[1]) args = func_signature.args[2:end] kw_body = Expr(:block) cleanup_body = Expr(:block) @@ -231,14 +234,14 @@ macro recipe(funcexpr::Expr) if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end - if !(isa(func_signature, Expr) && func_signature.head == :call) + if !(isa(func_signature, Expr) && (func_signature.head == :call || (func_signature.head == :where && func_signature.args[1].head == :call))) error("Expected `func_signature = ...` with func_signature as a call Expr... got: $func_signature") end if length(func_signature.args) < 2 error("Missing function arguments... need something to dispatch on!") end - func = get_function_def(func_signature) + where_args = get_where_args(func_signature) args, kw_body, cleanup_body = create_kw_body(func_signature) # this is where the receipe func_body is processed @@ -249,7 +252,7 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. funcdef = esc(quote - function $func(d::Dict{Symbol,Any}, $(args...)) + function RecipesBase.apply_recipe(d::Dict{Symbol, Any}, $(args...)) where $(where_args...) if RecipesBase._debug_recipes[1] println("apply_recipe args: ", $args) end From 090f4c531f1080eb120bfe43242e33627a3079d5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 29 Jul 2017 15:45:40 +0200 Subject: [PATCH 052/356] recursively apply nested where syntax --- RecipesBase/src/RecipesBase.jl | 50 ++++++++++++++++------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 777d6767c..cbfbd8342 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -74,17 +74,20 @@ function _equals_symbol(arg::Expr, sym::Symbol) end # build an apply_recipe function header from the recipe function header -function get_where_args(func_signature::Expr) - # for parametric definitions, take the "curly" expression and add the func +function get_function_def(func_signature::Expr, args::Vector) front = func_signature.args[1] - where_args = if isa(front, Expr) && front.head == :curly - front.args[2:end] - elseif func_signature.head == :where - func_signature.args[2:end] + if func_signature.head == :where + Expr(:where, get_function_def(front, args), func_signature.args[2:end]...) + elseif func_signature.head == :call + func = Expr(:call, :(RecipesBase.apply_recipe), :(d::Dict{Symbol, Any}), args...) + if isa(front, Expr) && front.head == :curly + Expr(:where, func, front.args[2:end]...) + else + func + end else - [] + error("Expected `func_signature = ...` with func_signature as a call Expr... got: $func_signature") end - where_args end function create_kw_body(func_signature::Expr) @@ -234,15 +237,12 @@ macro recipe(funcexpr::Expr) if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end - if !(isa(func_signature, Expr) && (func_signature.head == :call || (func_signature.head == :where && func_signature.args[1].head == :call))) - error("Expected `func_signature = ...` with func_signature as a call Expr... got: $func_signature") - end if length(func_signature.args) < 2 error("Missing function arguments... need something to dispatch on!") end - where_args = get_where_args(func_signature) args, kw_body, cleanup_body = create_kw_body(func_signature) + func = get_function_def(func_signature, args) # this is where the receipe func_body is processed # replace all the key => value lines with argument setting logic @@ -251,21 +251,19 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. - funcdef = esc(quote - function RecipesBase.apply_recipe(d::Dict{Symbol, Any}, $(args...)) where $(where_args...) - if RecipesBase._debug_recipes[1] - println("apply_recipe args: ", $args) - end - $kw_body - $cleanup_body - series_list = RecipesBase.RecipeData[] - func_return = $func_body - if func_return != nothing - push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) - end - series_list + funcdef = Expr(:function, func, esc(quote + if RecipesBase._debug_recipes[1] + println("apply_recipe args: ", $args) end - end) + $kw_body + $cleanup_body + series_list = RecipesBase.RecipeData[] + func_return = $func_body + if func_return != nothing + push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) + end + series_list + end)) funcdef end From 4afb862609c06f75753c3f0dc169bc244ab20377 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 30 Jul 2017 08:41:08 +0200 Subject: [PATCH 053/356] fix (esc) args --- RecipesBase/src/RecipesBase.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index cbfbd8342..ccc567201 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -77,16 +77,16 @@ end function get_function_def(func_signature::Expr, args::Vector) front = func_signature.args[1] if func_signature.head == :where - Expr(:where, get_function_def(front, args), func_signature.args[2:end]...) + Expr(:where, get_function_def(front, args), [esc(arg) for arg in func_signature.args[2:end]]...) elseif func_signature.head == :call - func = Expr(:call, :(RecipesBase.apply_recipe), :(d::Dict{Symbol, Any}), args...) + func = Expr(:call, :(RecipesBase.apply_recipe), [esc(arg) for arg in [:(d::Dict{Symbol, Any}); args]]...) if isa(front, Expr) && front.head == :curly - Expr(:where, func, front.args[2:end]...) + Expr(:where, func, [esc(arg) for arg in front.args[2:end]]...) else func end else - error("Expected `func_signature = ...` with func_signature as a call Expr... got: $func_signature") + error("Expected `func_signature = ...` with func_signature as a call or where Expr... got: $func_signature") end end From 649d64cee27f533efd5e53d5400762870712b08f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 30 Jul 2017 09:48:13 +0200 Subject: [PATCH 054/356] dots for esc() --- RecipesBase/src/RecipesBase.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index ccc567201..c0e337fac 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -77,11 +77,12 @@ end function get_function_def(func_signature::Expr, args::Vector) front = func_signature.args[1] if func_signature.head == :where - Expr(:where, get_function_def(front, args), [esc(arg) for arg in func_signature.args[2:end]]...) + Expr(:where, get_function_def(front, args), esc.(func_signature.args[2:end])...) elseif func_signature.head == :call - func = Expr(:call, :(RecipesBase.apply_recipe), [esc(arg) for arg in [:(d::Dict{Symbol, Any}); args]]...) + func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(d::Dict{Symbol, Any}); args])...) if isa(front, Expr) && front.head == :curly - Expr(:where, func, [esc(arg) for arg in front.args[2:end]]...) + # Expr(:where, func, [esc(arg) for arg in front.args[2:end]]...) + Expr(:where, func, esc.(front.args[2:end])...) else func end From edb47cdcc7504ac89900458ba48c039a5deeb8d1 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 30 Jul 2017 09:51:07 +0200 Subject: [PATCH 055/356] remove commented line --- RecipesBase/src/RecipesBase.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index c0e337fac..911cdf440 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -81,7 +81,6 @@ function get_function_def(func_signature::Expr, args::Vector) elseif func_signature.head == :call func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(d::Dict{Symbol, Any}); args])...) if isa(front, Expr) && front.head == :curly - # Expr(:where, func, [esc(arg) for arg in front.args[2:end]]...) Expr(:where, func, esc.(front.args[2:end])...) else func From 879ce00a1378ba7c4b2c16b286e14ad3da0758ee Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 30 Jul 2017 10:00:19 +0200 Subject: [PATCH 056/356] re-add func_signature head check --- RecipesBase/src/RecipesBase.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 911cdf440..13c85a789 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -237,6 +237,9 @@ macro recipe(funcexpr::Expr) if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end + if !(isa(func_signature, Expr) && func_signature.head in (:call, :where)) + error("Expected `func_signature = ...` with func_signature as a call or where Expr... got: $func_signature") + end if length(func_signature.args) < 2 error("Missing function arguments... need something to dispatch on!") end From 515164f1f4f24cafd82674622375d56e53811016 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 30 Jul 2017 17:31:40 +0800 Subject: [PATCH 057/356] Add test cases for #22 - update README, using `struct` in julia 0.6+ --- RecipesBase/README.md | 20 +++---- RecipesBase/REQUIRE | 2 +- RecipesBase/test/runtests.jl | 108 ++++++++++++++++++++++++++++------- 3 files changed, 97 insertions(+), 33 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 24d12dcb9..03b511fcf 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -52,7 +52,7 @@ This will build a spiky surface: ```julia using Plots; gr() -type T end +struct T end @recipe f(::T) = rand(100,100) surface(T()) ``` @@ -65,16 +65,16 @@ surface(T()) using RecipesBase # Our user-defined data type -type T end +struct T end # This is all we define. It uses a familiar signature, but strips it apart # in order to add a custom definition to the internal method `RecipesBase.apply_recipe` @recipe function plot(::T, n = 1; customcolor = :green) - markershape --> :auto # if markershape is unset, make it :auto - markercolor := customcolor # force markercolor to be customcolor - xrotation --> 45 # if xrotation is unset, make it 45 - zrotation --> 90 # if zrotation is unset, make it 90 - rand(10,n) # return the arguments (input data) for the next recipe + markershape --> :auto # if markershape is unset, make it :auto + markercolor := customcolor # force markercolor to be customcolor + xrotation --> 45 # if xrotation is unset, make it 45 + zrotation --> 90 # if zrotation is unset, make it 90 + rand(10,n) # return the arguments (input data) for the next recipe end # ---------------------------- @@ -119,11 +119,11 @@ function RecipesBase.apply_recipe(d::Dict{Symbol,Any},::T,n=1) if RecipesBase._debug_recipes[1] println("apply_recipe args: ",Any[:(::T),:(n=1)]) end - begin + begin customcolor = get!(d,:customcolor,:green) end series_list = RecipesBase.RecipeData[] - func_return = begin + func_return = begin get!(d,:markershape,:auto) d[:markercolor] = customcolor get!(d,:xrotation,45) @@ -133,7 +133,7 @@ function RecipesBase.apply_recipe(d::Dict{Symbol,Any},::T,n=1) if func_return != nothing push!(series_list,RecipesBase.RecipeData(d,RecipesBase.wrap_tuple(func_return))) end - begin + begin RecipesBase.is_key_supported(:customcolor) || delete!(d,:customcolor) end series_list diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index e773e5c55..137767a42 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.6-pre +julia 0.6 diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 2a695dc21..c00b3ed97 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -1,30 +1,94 @@ using RecipesBase using Base.Test -srand(1) +const KW = Dict{Symbol, Any} + RecipesBase.is_key_supported(k::Symbol) = true -type T end +for t in [Symbol(:T, i) for i in 1:3] + @eval struct $t end +end + + +@testset "@recipe" begin + + +""" +make sure the attribute dictionary was populated correctly, +and the returned arguments are as expected +""" +function check_apply_recipe(T::DataType, expect) + # this is similar to how Plots would call the method + d = KW(:customcolor => :red) + + data_list = RecipesBase.apply_recipe(d, T(), 2) + @test data_list[1].args == (srand(1); (rand(10,2),)) + @test d == expect +end + + +@testset "simple parametric type" begin + @test_throws MethodError RecipesBase.apply_recipe(KW(), T1()) + + @recipe function plot{N <: Integer}(t::T1, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10, n) + end -@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) - :markershape --> :auto, :require - :markercolor --> customcolor, :force - :xrotation --> 5 - :zrotation --> 6, :quiet - rand(10,n) + srand(1) + check_apply_recipe(T1, KW( + :customcolor => :red, + :markershape => :auto, + :markercolor => :red, + :xrotation => 5, + :zrotation => 6)) end -# this is similar to how Plots would call the method -typealias KW Dict{Symbol,Any} -d = KW(:customcolor => :red) -data_list = RecipesBase.apply_recipe(d, T(), 2) - -# make sure the attribute dictionary was populated correctly, and the returned arguments are as expected -@test data_list[1].args == (srand(1); (rand(10,2),)) -@test d == KW( - :customcolor => :red, - :markershape => :auto, - :markercolor => :red, - :xrotation => 5, - :zrotation => 6 -) + +@testset "parametric type with where" begin + @test_throws MethodError RecipesBase.apply_recipe(KW(), T2()) + + @recipe function plot(t::T2, n::N = 1; customcolor = :green) where {N <: Integer} + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10, n) + end + + srand(1) + check_apply_recipe(T2, KW( + :customcolor => :red, + :markershape => :auto, + :markercolor => :red, + :xrotation => 5, + :zrotation => 6)) +end + + +@testset "parametric type with double where" begin + @test_throws MethodError RecipesBase.apply_recipe(KW(), T3()) + + @recipe function plot(t::T3, n::N = 1, m::M = 0.0; + customcolor = :green) where {N <: Integer} where {M <: Float64} + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + rand(10, n) + end + + srand(1) + check_apply_recipe(T3, KW( + :customcolor => :red, + :markershape => :auto, + :markercolor => :red, + :xrotation => 5, + :zrotation => 6)) +end + + +end # @testset "@recipe" From 867b56293f6a4c78ed5c417ed34421a2afa0e2f4 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Fri, 11 Aug 2017 15:58:58 -0700 Subject: [PATCH 058/356] Add `RecipesBase.` in front of `plot` commands After the move we cannot expect that the plot command has actually been exported yet. But by doing this it'll always use the one from RecipesBase, which is the one Plots.jl extends. --- RecipesBase/src/RecipesBase.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 13c85a789..e046614f4 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -337,8 +337,8 @@ function _userplot(expr::Expr) esc(quote $expr export $funcname, $funcname2 - $funcname(args...; kw...) = plot($typename(args); kw...) - $funcname2(args...; kw...) = plot!($typename(args); kw...) + $funcname(args...; kw...) = RecipesBase.plot($typename(args); kw...) + $funcname2(args...; kw...) = RecipesBase.plot!($typename(args); kw...) end) end @@ -355,8 +355,8 @@ macro shorthands(funcname::Symbol) funcname2 = Symbol(funcname, "!") esc(quote export $funcname, $funcname2 - $funcname(args...; kw...) = plot(args...; kw..., seriestype = $(Meta.quot(funcname))) - $funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(Meta.quot(funcname))) + $funcname(args...; kw...) = RecipesBase.plot(args...; kw..., seriestype = $(Meta.quot(funcname))) + $funcname2(args...; kw...) = RecipesBase.plot!(args...; kw..., seriestype = $(Meta.quot(funcname))) end) end From e1ab222185da4921a880a9407de64f6d41f36ec4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 16 Aug 2017 21:10:20 +0200 Subject: [PATCH 059/356] add inplace plot function definition --- RecipesBase/src/RecipesBase.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e046614f4..e7e56dd61 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -22,6 +22,7 @@ abstract type AbstractLayout end # can add their own definition of RecipesBase.plot since RecipesBase is the common # dependency of the Plots ecosystem function plot end +function plot! end # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.animate since RecipesBase is the common From bcff8c7955d0f0fbc86801510a36d3404170704b Mon Sep 17 00:00:00 2001 From: "femtocleaner[bot]" Date: Tue, 22 Aug 2017 22:27:25 +0000 Subject: [PATCH 060/356] Fix deprecations --- RecipesBase/src/RecipesBase.jl | 2 +- RecipesBase/test/runtests.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e7e56dd61..cfec05555 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -47,7 +47,7 @@ end # -------------------------------------------------------------------------- # this holds the data and attributes of one series, and is returned from apply_recipe -immutable RecipeData +struct RecipeData d::Dict{Symbol,Any} args::Tuple end diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index c00b3ed97..40cb76fe2 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -30,7 +30,7 @@ end @testset "simple parametric type" begin @test_throws MethodError RecipesBase.apply_recipe(KW(), T1()) - @recipe function plot{N <: Integer}(t::T1, n::N = 1; customcolor = :green) + @recipe function plot(t::T1, n::N = 1; customcolor = :green) where N <: Integer :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 5 From 037dd6677def46e663614052b55c6d10a812176c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Mon, 12 Jun 2017 23:03:30 +0200 Subject: [PATCH 061/356] replace d by plotattribues --- RecipesBase/src/RecipesBase.jl | 52 ++++++++++++++++++++++++++++++---- RecipesBase/test/runtests.jl | 27 ++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index cfec05555..0ae350eb7 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -101,8 +101,8 @@ function create_kw_body(func_signature::Expr) if isa(args[1], Expr) && args[1].head == :parameters for kwpair in args[1].args k, v = kwpair.args - push!(kw_body.args, :($k = get!(d, $(QuoteNode(k)), $v))) - push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!(d, $(QuoteNode(k))))) + push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) + push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) end args = args[2:end] end @@ -155,10 +155,10 @@ function process_recipe_body!(expr::Expr) set_expr = if force # forced override user settings - :(d[$k] = $v) + :($PLOTATTRIBUTES[$k] = $v) else # if the user has set this keyword, use theirs - :(get!(d, $k, $v)) + :(get!($PLOTATTRIBUTES, $k, $v)) end expr.args[i] = if quiet @@ -182,6 +182,20 @@ function process_recipe_body!(expr::Expr) end end +# PLOTATTRIBUTES_OLD and_replace can be removed after d for accessing plot attributes is +# is not supported anymore +const PLOTATTRIBUTES = :plotattributes +const PLOTATTRIBUTES_OLD = :d +_replace(ex, old, new) = _replace(ex, 0, old, new) +_replace(ex, n, old, new) = (ex == old) ? (new, n+1) : (ex, n) +function _replace(ex::Expr, n, old, new) + new_args = [] + for old_arg in ex.args + new_arg, n = _replace(old_arg, n, old, new) + push!(new_args, new_arg) + end + Expr(ex.head, new_args...), n +end # -------------------------------------------------------------------------- """ @@ -233,8 +247,15 @@ number of series to display. User-defined keyword arguments are passed through, - force: Don't allow user override for this keyword """ macro recipe(funcexpr::Expr) + funcexpr, n_depr = _replace(funcexpr, PLOTATTRIBUTES_OLD, PLOTATTRIBUTES) func_signature, func_body = funcexpr.args + if n_depr > 0 + msg = "Usage of `$PLOTATTRIBUTES_OLD` for accessing plot attributes is deprecated. Found $n_depr usages of `$PLOTATTRIBUTES_OLD` inside `@recipe`. Use `$PLOTATTRIBUTES` instead.\n" + deprecation_body = :(Base.depwarn($msg, :d)) + else + deprecation_body = :() + end if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end @@ -255,6 +276,7 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. +<<<<<<< HEAD funcdef = Expr(:function, func, esc(quote if RecipesBase._debug_recipes[1] println("apply_recipe args: ", $args) @@ -269,6 +291,24 @@ macro recipe(funcexpr::Expr) series_list end)) funcdef +======= + funcdef = esc(quote + $deprecation_body + function $func($PLOTATTRIBUTES::Dict{Symbol,Any}, $(args...)) + if RecipesBase._debug_recipes[1] + println("apply_recipe args: ", $args) + end + $kw_body + $cleanup_body + series_list = RecipesBase.RecipeData[] + func_return = $func_body + if func_return != nothing + push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(func_return))) + end + series_list + end + end) +>>>>>>> 4b4a501... replace d by plotattribues end @@ -298,9 +338,9 @@ end """ macro series(expr::Expr) esc(quote - let d = copy(d) + let $PLOTATTRIBUTES = copy($PLOTATTRIBUTES) args = $expr - push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(args))) + push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(args))) nothing end end) diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 40cb76fe2..ee5e58426 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -38,6 +38,7 @@ end rand(10, n) end +<<<<<<< HEAD srand(1) check_apply_recipe(T1, KW( :customcolor => :red, @@ -92,3 +93,29 @@ end end # @testset "@recipe" +======= +@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + plotattributes[:hello] = "hi" + rand(10,n) +end + +# this is similar to how Plots would call the method +typealias KW Dict{Symbol,Any} +d = KW(:customcolor => :red) +data_list = RecipesBase.apply_recipe(d, T(), 2) + +# make sure the attribute dictionary was populated correctly, and the returned arguments are as expected +@test data_list[1].args == (srand(1); (rand(10,2),)) +@test d == KW( + :customcolor => :red, + :markershape => :auto, + :markercolor => :red, + :xrotation => 5, + :zrotation => 6, + :hello => "hi" +) +>>>>>>> 4b4a501... replace d by plotattribues From 4491a1ef57d30c64e9468d113403450597d2bfc5 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 23 Sep 2017 15:28:58 +0200 Subject: [PATCH 062/356] fix --- RecipesBase/src/RecipesBase.jl | 23 ++------------------ RecipesBase/test/runtests.jl | 39 ++++++++++++++-------------------- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 0ae350eb7..b956437ce 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -80,7 +80,7 @@ function get_function_def(func_signature::Expr, args::Vector) if func_signature.head == :where Expr(:where, get_function_def(front, args), esc.(func_signature.args[2:end])...) elseif func_signature.head == :call - func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(d::Dict{Symbol, Any}); args])...) + func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:($PLOTATTRIBUTES::Dict{Symbol, Any}); args])...) if isa(front, Expr) && front.head == :curly Expr(:where, func, esc.(front.args[2:end])...) else @@ -276,7 +276,6 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. -<<<<<<< HEAD funcdef = Expr(:function, func, esc(quote if RecipesBase._debug_recipes[1] println("apply_recipe args: ", $args) @@ -286,29 +285,11 @@ macro recipe(funcexpr::Expr) series_list = RecipesBase.RecipeData[] func_return = $func_body if func_return != nothing - push!(series_list, RecipesBase.RecipeData(d, RecipesBase.wrap_tuple(func_return))) + push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(func_return))) end series_list end)) funcdef -======= - funcdef = esc(quote - $deprecation_body - function $func($PLOTATTRIBUTES::Dict{Symbol,Any}, $(args...)) - if RecipesBase._debug_recipes[1] - println("apply_recipe args: ", $args) - end - $kw_body - $cleanup_body - series_list = RecipesBase.RecipeData[] - func_return = $func_body - if func_return != nothing - push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(func_return))) - end - series_list - end - end) ->>>>>>> 4b4a501... replace d by plotattribues end diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index ee5e58426..978e7f21b 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -5,7 +5,7 @@ const KW = Dict{Symbol, Any} RecipesBase.is_key_supported(k::Symbol) = true -for t in [Symbol(:T, i) for i in 1:3] +for t in [Symbol(:T, i) for i in 1:4] @eval struct $t end end @@ -38,7 +38,6 @@ end rand(10, n) end -<<<<<<< HEAD srand(1) check_apply_recipe(T1, KW( :customcolor => :red, @@ -92,30 +91,24 @@ end end -end # @testset "@recipe" -======= -@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) - :markershape --> :auto, :require - :markercolor --> customcolor, :force - :xrotation --> 5 - :zrotation --> 6, :quiet - plotattributes[:hello] = "hi" - rand(10,n) -end - -# this is similar to how Plots would call the method -typealias KW Dict{Symbol,Any} -d = KW(:customcolor => :red) -data_list = RecipesBase.apply_recipe(d, T(), 2) - -# make sure the attribute dictionary was populated correctly, and the returned arguments are as expected -@test data_list[1].args == (srand(1); (rand(10,2),)) -@test d == KW( +@testset "manual access of plotattributes" begin + @recipe function plot(t::T4, n = 1; customcolor = :green) + :markershape --> :auto, :require + :markercolor --> customcolor, :force + :xrotation --> 5 + :zrotation --> 6, :quiet + plotattributes[:hello] = "hi" + rand(10,n) + end + srand(1) + check_apply_recipe(T4, KW( :customcolor => :red, :markershape => :auto, :markercolor => :red, :xrotation => 5, :zrotation => 6, :hello => "hi" -) ->>>>>>> 4b4a501... replace d by plotattribues + )) +end + +end # @testset "@recipe" From 6be7f27b6796b6758ba332c7fad339f93d33d238 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 23 Sep 2017 15:30:13 +0200 Subject: [PATCH 063/356] fix --- RecipesBase/test/runtests.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 978e7f21b..3a0ebd03a 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -98,6 +98,7 @@ end :xrotation --> 5 :zrotation --> 6, :quiet plotattributes[:hello] = "hi" + d[:world] = "world" rand(10,n) end srand(1) @@ -107,7 +108,8 @@ end :markercolor => :red, :xrotation => 5, :zrotation => 6, - :hello => "hi" + :hello => "hi", + :world => "world" )) end From e71f429a7259ce28297a9d144ea3e0d22227afd3 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 26 Sep 2017 20:15:44 +0200 Subject: [PATCH 064/356] fix nightly --- RecipesBase/src/RecipesBase.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b956437ce..e898f872c 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -73,6 +73,7 @@ end function _equals_symbol(arg::Expr, sym::Symbol) arg.head == :quote && arg.args[1] == sym end +_equals_symbol(x, sym::Symbol) = false # build an apply_recipe function header from the recipe function header function get_function_def(func_signature::Expr, args::Vector) @@ -365,7 +366,7 @@ function _userplot(expr::Expr) end function _userplot(sym::Symbol) - _userplot(:(type $sym + _userplot(:(mutable struct $sym args end)) end From 100a44353c94e0d6cc805817a119e502088d5317 Mon Sep 17 00:00:00 2001 From: Kevin Cheng Date: Tue, 3 Oct 2017 16:36:14 -0400 Subject: [PATCH 065/356] Typo on line 352 ```errror``` is a typo RecipesBase still does not compile on v0.7, get the following error stacktrace: ``` ERROR: LoadError: LoadError: LoadError: Must call userplot on a type/immutable expression. Got: mutable struct Spy #= /Users/kevin/.julia/v0.7/RecipesBase/src/RecipesBase.jl:370 =# args end Stacktrace: [1] _userplot(::Expr) at /Users/kevin/.julia/v0.7/RecipesBase/src/RecipesBase.jl:352 [2] _userplot(::Symbol) at /Users/kevin/.julia/v0.7/RecipesBase/src/RecipesBase.jl:369 [3] @userplot(::LineNumberNode, ::Module, ::Any) at /Users/kevin/.julia/v0.7/RecipesBase/src/RecipesBase.jl:347 [4] include_relative(::Module, ::String) at ./loading.jl:526 [5] include at ./sysimg.jl:14 [inlined] [6] include(::String) at /Users/kevin/.julia/v0.7/Plots/src/Plots.jl:3 [7] include_relative(::Module, ::String) at ./loading.jl:526 [8] _require(::Symbol) at ./loading.jl:461 [9] require(::Symbol) at ./loading.jl:320 in expression starting at /Users/kevin/.julia/v0.7/Plots/src/recipes.jl:930 in expression starting at /Users/kevin/.julia/v0.7/Plots/src/recipes.jl:930 in expression starting at /Users/kevin/.julia/v0.7/Plots/src/Plots.jl:154 --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e898f872c..86243ec0d 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -349,7 +349,7 @@ end function _userplot(expr::Expr) if expr.head != :type - errror("Must call userplot on a type/immutable expression. Got: $expr") + error("Must call userplot on a type/immutable expression. Got: $expr") end typename = expr.args[2] From 71ceb4a9dc82a242822ab8e308a6c566803474db Mon Sep 17 00:00:00 2001 From: Darwin Darakananda Date: Mon, 16 Oct 2017 09:06:18 -0700 Subject: [PATCH 066/356] Attach docstrings to `userplot` and `shorthand` macros --- RecipesBase/src/RecipesBase.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e898f872c..a96e456aa 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -360,8 +360,8 @@ function _userplot(expr::Expr) esc(quote $expr export $funcname, $funcname2 - $funcname(args...; kw...) = RecipesBase.plot($typename(args); kw...) - $funcname2(args...; kw...) = RecipesBase.plot!($typename(args); kw...) + Core.@__doc__ $funcname(args...; kw...) = RecipesBase.plot($typename(args); kw...) + Core.@__doc__ $funcname2(args...; kw...) = RecipesBase.plot!($typename(args); kw...) end) end @@ -378,8 +378,8 @@ macro shorthands(funcname::Symbol) funcname2 = Symbol(funcname, "!") esc(quote export $funcname, $funcname2 - $funcname(args...; kw...) = RecipesBase.plot(args...; kw..., seriestype = $(Meta.quot(funcname))) - $funcname2(args...; kw...) = RecipesBase.plot!(args...; kw..., seriestype = $(Meta.quot(funcname))) + Core.@__doc__ $funcname(args...; kw...) = RecipesBase.plot(args...; kw..., seriestype = $(Meta.quot(funcname))) + Core.@__doc__ $funcname2(args...; kw...) = RecipesBase.plot!(args...; kw..., seriestype = $(Meta.quot(funcname))) end) end From 8207104519673c3235282a6b31e41ca917ce85d2 Mon Sep 17 00:00:00 2001 From: Will Kearney Date: Thu, 7 Dec 2017 15:27:54 -0500 Subject: [PATCH 067/356] Check if k is a type annotation --- RecipesBase/src/RecipesBase.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 86243ec0d..a01a3c959 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -102,6 +102,9 @@ function create_kw_body(func_signature::Expr) if isa(args[1], Expr) && args[1].head == :parameters for kwpair in args[1].args k, v = kwpair.args + if isa(k, Expr) && k.head == :(::) + k = k.args[1] + end push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) end From 4879eb074458045fea2e625a407d4f8e8a25b018 Mon Sep 17 00:00:00 2001 From: Will Kearney Date: Fri, 8 Dec 2017 11:20:21 -0500 Subject: [PATCH 068/356] Add warning about dropping type annotations --- RecipesBase/src/RecipesBase.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index a01a3c959..0fa98fcfe 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -104,6 +104,7 @@ function create_kw_body(func_signature::Expr) k, v = kwpair.args if isa(k, Expr) && k.head == :(::) k = k.args[1] + warn("Type annotations on keyword arguments not currently supported. Type information has been discarded") end push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) From b195b8b363967dce5037f8a29f09baade0918465 Mon Sep 17 00:00:00 2001 From: Will Kearney Date: Fri, 8 Dec 2017 11:28:03 -0500 Subject: [PATCH 069/356] Clarify that this is only true for recipes --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 0fa98fcfe..39975f0c2 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -104,7 +104,7 @@ function create_kw_body(func_signature::Expr) k, v = kwpair.args if isa(k, Expr) && k.head == :(::) k = k.args[1] - warn("Type annotations on keyword arguments not currently supported. Type information has been discarded") + warn("Type annotations on keyword arguments not currently supported in recipes. Type information has been discarded") end push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) From f95fa1c892b859fe99c2b9692b0066ffd7ba28e3 Mon Sep 17 00:00:00 2001 From: Art Gower Date: Mon, 11 Dec 2017 14:38:21 +0000 Subject: [PATCH 070/356] Correcting broken links The following broken links were replaced: "http://juliaplots.github.io/recipes/" replaced with "http://docs.juliaplots.org/latest/recipes/" "http://juliaplots.github.io/supported/#keyword-arguments" replaced with "http://docs.juliaplots.org/latest/attributes/" --- RecipesBase/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 03b511fcf..76cd3db32 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -13,7 +13,7 @@ as components in more complex visualizations. This functionality is primarily geared to turning user types and settings into the data and attributes that describe a [Plots](https://github.com/tbreloff/Plots.jl) visualization, though it could be used for other purposes as well. -Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. See the [Plots documentation on recipes](http://juliaplots.github.io/recipes/) for more information. +Plots has extensive machinery to uniquely take advantage of the simplified recipe description you define. See the [Plots documentation on recipes](http://docs.juliaplots.org/latest/recipes/) for more information. The `@recipe` macro will process a function definition, use `-->` commands to define attributes, and pass the return value through for further processing (likely by Plots.jl). @@ -42,7 +42,7 @@ Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://juliaplots.github.io/), and be sure to reference -the [supported keywords](http://juliaplots.github.io/supported/#keyword-arguments). +the [supported keywords](http://docs.juliaplots.org/latest/attributes/). For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. From 99daf222d846da1a758d6cbd87a4db42c556d6e0 Mon Sep 17 00:00:00 2001 From: Art Gower Date: Mon, 11 Dec 2017 16:08:53 +0000 Subject: [PATCH 071/356] Corrected #keyword link --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 76cd3db32..ed71ead1d 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -42,7 +42,7 @@ Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://juliaplots.github.io/), and be sure to reference -the [supported keywords](http://docs.juliaplots.org/latest/attributes/). +the [supported keywords](http://docs.juliaplots.org/latest/supported/#keyword-arguments). For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. From aac0f9ec69b50c39e25ca52901fd7df2d3a0cb75 Mon Sep 17 00:00:00 2001 From: Gustavo Goretkin Date: Wed, 13 Dec 2017 21:30:05 -0500 Subject: [PATCH 072/356] Update link for case studies --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index ed71ead1d..5f8754095 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -108,7 +108,7 @@ number of series to display. User-defined keyword arguments are passed through, ### Series -For complex visualizations, it can be beneficial to create many series inside a single recipe. The `@series` macro will make a copy of the attribute dictionary `d`, and add a new RecipeData object to the returned list. See the [case studies](http://juliaplots.github.io/recipes/#case-studies) for more details. +For complex visualizations, it can be beneficial to create many series inside a single recipe. The `@series` macro will make a copy of the attribute dictionary `d`, and add a new RecipeData object to the returned list. See the [case studies](http://docs.juliaplots.org/latest/recipes/#case-studies) for more details. ### Generated code From 164290ed9c1ffe2bd56bb38c3f4a79f08a6003df Mon Sep 17 00:00:00 2001 From: Christian Kurz Date: Fri, 13 Oct 2017 19:50:32 +0200 Subject: [PATCH 073/356] changed `type` to new struct keyword i ran into this issue trying to use plots on 0.7.0: the expression head of types is no longe `type` but `struct`. Also fixed the error message. I fixed the typo in `errror` in an earlier PR - these should be merged, but i don't really know what would be the expected way to handle this. --- RecipesBase/src/RecipesBase.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 5d3ecb727..d60090305 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -354,6 +354,8 @@ end function _userplot(expr::Expr) if expr.head != :type error("Must call userplot on a type/immutable expression. Got: $expr") + if expr.head != :struct + errror("Must call userplot on a [mutable] struct expression. Got: $expr") end typename = expr.args[2] From 11f69828416f491525c012ae4dc93ce09a751033 Mon Sep 17 00:00:00 2001 From: Christian Kurz Date: Sat, 14 Oct 2017 12:34:23 +0200 Subject: [PATCH 074/356] updated docstring `type` -> `struct` --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index d60090305..7d0eafa1d 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -337,7 +337,7 @@ end """ You can easily define your own plotting recipes with convenience methods: ``` -@userplot type GroupHist +@userplot struct GroupHist args end @recipe function f(gh::GroupHist) From d71237a0b9b807fd23ce31da17eb56d5dd0b5808 Mon Sep 17 00:00:00 2001 From: Christian Kurz Date: Sat, 14 Oct 2017 12:52:11 +0200 Subject: [PATCH 075/356] changed docs to use `_userplot(sym::Symbol)` If i understand this correctly, the my last proposed docstring would have resulted in a call to `_userplot(:expr)` while this new docstring points to `_userplot(sym::Symbol)` through the macro and saves the user some typing. --- RecipesBase/src/RecipesBase.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 7d0eafa1d..82094abc3 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -337,9 +337,8 @@ end """ You can easily define your own plotting recipes with convenience methods: ``` -@userplot struct GroupHist - args -end +@userplot GroupHist + @recipe function f(gh::GroupHist) # set some attributes, add some series, using gh.args as input end From 9d485dd7d8368c3e900f0b90526ae19cb3ff76f6 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Sat, 14 Oct 2017 13:20:41 +0200 Subject: [PATCH 076/356] require julia 0.7-pre --- RecipesBase/REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 137767a42..670c48170 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.6 +julia 0.7-pre From 80715a03a142f39f1c2e65b798b63e214d6ebc94 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 1 May 2018 12:44:21 +0200 Subject: [PATCH 077/356] Fix typo --- RecipesBase/src/RecipesBase.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 82094abc3..b5d7211f9 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -351,10 +351,8 @@ macro userplot(expr) end function _userplot(expr::Expr) - if expr.head != :type - error("Must call userplot on a type/immutable expression. Got: $expr") if expr.head != :struct - errror("Must call userplot on a [mutable] struct expression. Got: $expr") + error("Must call userplot on a [mutable] struct expression. Got: $expr") end typename = expr.args[2] From 784ffe58c7241e3c1d00ed73218ebee0901ec3ca Mon Sep 17 00:00:00 2001 From: "femtocleaner[bot]" Date: Sat, 30 Jun 2018 23:15:27 +0000 Subject: [PATCH 078/356] Fix deprecations --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b5d7211f9..94994eefd 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -104,7 +104,7 @@ function create_kw_body(func_signature::Expr) k, v = kwpair.args if isa(k, Expr) && k.head == :(::) k = k.args[1] - warn("Type annotations on keyword arguments not currently supported in recipes. Type information has been discarded") + @warn("Type annotations on keyword arguments not currently supported in recipes. Type information has been discarded") end push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) From 227cac6d2c4f8c5d6b0823e11c4e72b1e3d2117e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 1 Jul 2018 18:02:02 +0200 Subject: [PATCH 079/356] update to 0.7 --- RecipesBase/.travis.yml | 2 +- RecipesBase/REQUIRE | 2 +- RecipesBase/test/runtests.jl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index e11c7f163..fe2014b14 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - 0.6 + - 0.7 - nightly notifications: email: false diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 670c48170..cdbb2dc1e 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.7-pre +julia 0.7-alpha diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 3a0ebd03a..1fa7de2a8 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -1,5 +1,5 @@ using RecipesBase -using Base.Test +using Test, Random const KW = Dict{Symbol, Any} From 99643f7414aad5472e64cf697f0ca57b35382dde Mon Sep 17 00:00:00 2001 From: Josh Day Date: Tue, 7 Aug 2018 14:13:49 +0100 Subject: [PATCH 080/356] update build script to work on 1.0, remove deprecations --- RecipesBase/.travis.yml | 6 +++--- RecipesBase/src/RecipesBase.jl | 2 -- RecipesBase/test/runtests.jl | 10 +++++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index fe2014b14..0e61dbb63 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -9,6 +9,6 @@ julia: notifications: email: false # uncomment the following lines to override the default test script -#script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' +script: + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - julia -e 'import Pkg; Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 94994eefd..05f10ef5b 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -1,6 +1,4 @@ -__precompile__() - module RecipesBase export diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 1fa7de2a8..913d81fb0 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -22,7 +22,7 @@ function check_apply_recipe(T::DataType, expect) d = KW(:customcolor => :red) data_list = RecipesBase.apply_recipe(d, T(), 2) - @test data_list[1].args == (srand(1); (rand(10,2),)) + @test data_list[1].args == (Random.seed!(1); (rand(10,2),)) @test d == expect end @@ -38,7 +38,7 @@ end rand(10, n) end - srand(1) + Random.seed!(1) check_apply_recipe(T1, KW( :customcolor => :red, :markershape => :auto, @@ -59,7 +59,7 @@ end rand(10, n) end - srand(1) + Random.seed!(1) check_apply_recipe(T2, KW( :customcolor => :red, :markershape => :auto, @@ -81,7 +81,7 @@ end rand(10, n) end - srand(1) + Random.seed!(1) check_apply_recipe(T3, KW( :customcolor => :red, :markershape => :auto, @@ -101,7 +101,7 @@ end d[:world] = "world" rand(10,n) end - srand(1) + Random.seed!(1) check_apply_recipe(T4, KW( :customcolor => :red, :markershape => :auto, From 7791ac07a0ad157ffa811090afb6d1bf3c1513c0 Mon Sep 17 00:00:00 2001 From: Josh Day Date: Tue, 7 Aug 2018 14:15:37 +0100 Subject: [PATCH 081/356] update appveyor --- RecipesBase/appveyor.yml | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml index b038c7696..831beb78f 100644 --- a/RecipesBase/appveyor.yml +++ b/RecipesBase/appveyor.yml @@ -1,9 +1,17 @@ environment: matrix: - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe" - - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" + - julia_version: 0.7 + - julia_version: latest + +platform: + - x86 # 32-bit + - x64 # 64-bit + +## uncomment the following lines to allow failures on nightly julia +## (tests will run but not make your overall status red) +#matrix: +# allow_failures: +# - julia_version: latest branches: only: @@ -17,19 +25,12 @@ notifications: on_build_status_changed: false install: - - ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" -# Download most recent Julia Windows binary - - ps: (new-object net.webclient).DownloadFile( - $env:JULIA_URL, - "C:\projects\julia-binary.exe") -# Run installer silently, output to C:\projects\julia - - C:\projects\julia-binary.exe /S /D=C:\projects\julia + - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) build_script: -# Need to convert from shallow to complete for Pkg.clone to work - - IF EXIST .git\shallow (git fetch --unshallow) - - C:\projects\julia\bin\julia -e "versioninfo(); - Pkg.clone(pwd(), \"RecipesBase\"); Pkg.build(\"RecipesBase\")" + - echo "%JL_BUILD_SCRIPT%" + - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" test_script: - - C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"RecipesBase\")" + - echo "%JL_TEST_SCRIPT%" + - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" From b694e1a5738f5428bafd9927231ad6376fdbb85d Mon Sep 17 00:00:00 2001 From: Pietro Vertechi Date: Sat, 11 Aug 2018 13:32:34 +0100 Subject: [PATCH 082/356] Define recipetype to use groupedbar without StatPlots dependency (#42) --- RecipesBase/src/RecipesBase.jl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 05f10ef5b..01c5b6798 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -32,6 +32,10 @@ function animate end # can add their own definition of RecipesBase.is_key_supported(k::Symbol) function is_key_supported end +# a placeholder to establish the name so that other packages (Plots.jl for example) +# can add their own definition of RecipesBase.group_as_matrix(t) +group_as_matrix(t) = false + # This holds the recipe definitions to be dispatched on # the function takes in an attribute dict `d` and a list of args. # This default definition specifies the "no-arg" case. @@ -384,4 +388,34 @@ macro shorthands(funcname::Symbol) end) end +#---------------------------------------------------------------------------- + +# allow usage of type recipes without depending on StatPlots + +""" +`recipetype(s, args...)` + +Use this function to refer to type recipes by their symbol, without taking a dependency. + +# Example + +```julia +import RecipesBase: recipetype +recipetype(:groupedbar, 1:10, rand(10, 2)) +``` + +instead of + +```julia +import StatPlots: GroupedBar +GroupedBar((1:10, rand(10, 2))) +``` +""" +recipetype(s, args...) = recipetype(Val(s), args...) + +function recipetype(s::Val{T}, args...) where T + error("No type recipe defined for type $T. You may need to load StatPlots") +end + + end # module From c7f6b00cae9c9e709cc7311e85e8cd392264275a Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 11 Aug 2018 13:52:17 +0100 Subject: [PATCH 083/356] Update REQUIRE --- RecipesBase/REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index cdbb2dc1e..859ad4616 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.7-alpha +julia 0.7 From c2da4ba615ceb7638686a82cf2841ae34acf3613 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 12 Aug 2018 14:18:07 +0100 Subject: [PATCH 084/356] Deal differently with quoted symbols in 1.0 --- RecipesBase/src/RecipesBase.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 01c5b6798..ba32b1547 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -72,9 +72,12 @@ end function _equals_symbol(arg::Symbol, sym::Symbol) arg == sym end -function _equals_symbol(arg::Expr, sym::Symbol) +function _equals_symbol(arg::Expr, sym::Symbol) #not sure this method is necessary anymore on 0.7 arg.head == :quote && arg.args[1] == sym end +function _equals_symbol(arg::QuoteNode, sym::Symbol) + rg.value == sym +end _equals_symbol(x, sym::Symbol) = false # build an apply_recipe function header from the recipe function header From 12c3d1b0475cdd22df8a887222ee57163d8e6325 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 16 Aug 2018 11:33:17 +0200 Subject: [PATCH 085/356] fix typo --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index ba32b1547..b8110d36e 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -76,7 +76,7 @@ function _equals_symbol(arg::Expr, sym::Symbol) #not sure this method is necessa arg.head == :quote && arg.args[1] == sym end function _equals_symbol(arg::QuoteNode, sym::Symbol) - rg.value == sym + arg.value == sym end _equals_symbol(x, sym::Symbol) = false From 3f5f3e7d13469fd6f00574ab5f770e7fdc46c378 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 19 Aug 2018 22:40:59 +0200 Subject: [PATCH 086/356] remove last vestiges of `d` --- RecipesBase/src/RecipesBase.jl | 41 +++++++++------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b8110d36e..551c37ebf 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -39,7 +39,7 @@ group_as_matrix(t) = false # This holds the recipe definitions to be dispatched on # the function takes in an attribute dict `d` and a list of args. # This default definition specifies the "no-arg" case. -apply_recipe(d::Dict{Symbol,Any}) = () +apply_recipe(plotattributes::Dict{Symbol,Any}) = () const _debug_recipes = Bool[false] function debug(v::Bool = true) @@ -50,7 +50,7 @@ end # this holds the data and attributes of one series, and is returned from apply_recipe struct RecipeData - d::Dict{Symbol,Any} + plotattributes::Dict{Symbol,Any} args::Tuple end @@ -86,7 +86,7 @@ function get_function_def(func_signature::Expr, args::Vector) if func_signature.head == :where Expr(:where, get_function_def(front, args), esc.(func_signature.args[2:end])...) elseif func_signature.head == :call - func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:($PLOTATTRIBUTES::Dict{Symbol, Any}); args])...) + func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(plotattributes::Dict{Symbol, Any}); args])...) if isa(front, Expr) && front.head == :curly Expr(:where, func, esc.(front.args[2:end])...) else @@ -111,8 +111,8 @@ function create_kw_body(func_signature::Expr) k = k.args[1] @warn("Type annotations on keyword arguments not currently supported in recipes. Type information has been discarded") end - push!(kw_body.args, :($k = get!($PLOTATTRIBUTES, $(QuoteNode(k)), $v))) - push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!($PLOTATTRIBUTES, $(QuoteNode(k))))) + push!(kw_body.args, :($k = get!(plotattributes, $(QuoteNode(k)), $v))) + push!(cleanup_body.args, :(RecipesBase.is_key_supported($(QuoteNode(k))) || delete!(plotattributes, $(QuoteNode(k))))) end args = args[2:end] end @@ -165,10 +165,10 @@ function process_recipe_body!(expr::Expr) set_expr = if force # forced override user settings - :($PLOTATTRIBUTES[$k] = $v) + :(plotattributes[$k] = $v) else # if the user has set this keyword, use theirs - :(get!($PLOTATTRIBUTES, $k, $v)) + :(get!(plotattributes, $k, $v)) end expr.args[i] = if quiet @@ -192,20 +192,6 @@ function process_recipe_body!(expr::Expr) end end -# PLOTATTRIBUTES_OLD and_replace can be removed after d for accessing plot attributes is -# is not supported anymore -const PLOTATTRIBUTES = :plotattributes -const PLOTATTRIBUTES_OLD = :d -_replace(ex, old, new) = _replace(ex, 0, old, new) -_replace(ex, n, old, new) = (ex == old) ? (new, n+1) : (ex, n) -function _replace(ex::Expr, n, old, new) - new_args = [] - for old_arg in ex.args - new_arg, n = _replace(old_arg, n, old, new) - push!(new_args, new_arg) - end - Expr(ex.head, new_args...), n -end # -------------------------------------------------------------------------- """ @@ -257,15 +243,8 @@ number of series to display. User-defined keyword arguments are passed through, - force: Don't allow user override for this keyword """ macro recipe(funcexpr::Expr) - funcexpr, n_depr = _replace(funcexpr, PLOTATTRIBUTES_OLD, PLOTATTRIBUTES) func_signature, func_body = funcexpr.args - if n_depr > 0 - msg = "Usage of `$PLOTATTRIBUTES_OLD` for accessing plot attributes is deprecated. Found $n_depr usages of `$PLOTATTRIBUTES_OLD` inside `@recipe`. Use `$PLOTATTRIBUTES` instead.\n" - deprecation_body = :(Base.depwarn($msg, :d)) - else - deprecation_body = :() - end if !(funcexpr.head in (:(=), :function)) error("Must wrap a valid function call!") end @@ -295,7 +274,7 @@ macro recipe(funcexpr::Expr) series_list = RecipesBase.RecipeData[] func_return = $func_body if func_return != nothing - push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(func_return))) + push!(series_list, RecipesBase.RecipeData(plotattributes, RecipesBase.wrap_tuple(func_return))) end series_list end)) @@ -329,9 +308,9 @@ end """ macro series(expr::Expr) esc(quote - let $PLOTATTRIBUTES = copy($PLOTATTRIBUTES) + let plotattributes = copy(plotattributes) args = $expr - push!(series_list, RecipesBase.RecipeData($PLOTATTRIBUTES, RecipesBase.wrap_tuple(args))) + push!(series_list, RecipesBase.RecipeData(plotattributes, RecipesBase.wrap_tuple(args))) nothing end end) From 03cde6c9c116627817440c81239d4cf58f8e63e8 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Mon, 20 Aug 2018 13:54:53 +0200 Subject: [PATCH 087/356] fix tests --- RecipesBase/test/runtests.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 913d81fb0..cac6e4fb0 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -19,11 +19,11 @@ and the returned arguments are as expected """ function check_apply_recipe(T::DataType, expect) # this is similar to how Plots would call the method - d = KW(:customcolor => :red) + plotattributes = KW(:customcolor => :red) - data_list = RecipesBase.apply_recipe(d, T(), 2) + data_list = RecipesBase.apply_recipe(plotattributes, T(), 2) @test data_list[1].args == (Random.seed!(1); (rand(10,2),)) - @test d == expect + @test plotattributes == expect end @@ -98,7 +98,7 @@ end :xrotation --> 5 :zrotation --> 6, :quiet plotattributes[:hello] = "hi" - d[:world] = "world" + plotattributes[:world] = "world" rand(10,n) end Random.seed!(1) From 37ddbcf5d9bde42e77448254dae6cc9becd6f23b Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Tue, 28 Aug 2018 14:37:21 +0200 Subject: [PATCH 088/356] minimum 0.7 --- RecipesBase/REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE index 859ad4616..05b5ab4c7 100644 --- a/RecipesBase/REQUIRE +++ b/RecipesBase/REQUIRE @@ -1 +1 @@ -julia 0.7 +julia 1.0 From a8e0d181313e90599c0589a8d1cba0de5fd72dc7 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 24 Jan 2019 23:20:14 +0100 Subject: [PATCH 089/356] StatPlots-->StatsPlots in examples --- RecipesBase/src/RecipesBase.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 551c37ebf..f6625d52d 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -372,7 +372,7 @@ end #---------------------------------------------------------------------------- -# allow usage of type recipes without depending on StatPlots +# allow usage of type recipes without depending on StatsPlots """ `recipetype(s, args...)` @@ -389,14 +389,14 @@ recipetype(:groupedbar, 1:10, rand(10, 2)) instead of ```julia -import StatPlots: GroupedBar +import StatsPlots: GroupedBar GroupedBar((1:10, rand(10, 2))) ``` """ recipetype(s, args...) = recipetype(Val(s), args...) function recipetype(s::Val{T}, args...) where T - error("No type recipe defined for type $T. You may need to load StatPlots") + error("No type recipe defined for type $T. You may need to load StatsPlots") end From 35f98a48137bc9f5de964dd08515b3dd467f5b49 Mon Sep 17 00:00:00 2001 From: David Widmann Date: Fri, 17 May 2019 13:20:04 +0200 Subject: [PATCH 090/356] Add specialized in-place method for user plots --- RecipesBase/src/RecipesBase.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index f6625d52d..b7b0bac80 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -349,6 +349,7 @@ function _userplot(expr::Expr) export $funcname, $funcname2 Core.@__doc__ $funcname(args...; kw...) = RecipesBase.plot($typename(args); kw...) Core.@__doc__ $funcname2(args...; kw...) = RecipesBase.plot!($typename(args); kw...) + Core.@__doc__ $funcname2(plt::AbstractPlot, args...; kw...) = RecipesBase.plot!(plt, $typename(args); kw...) end) end From 99e273e59be90b53b319f3f3922bbdc9887a4ce5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 4 Jun 2019 20:13:40 +0200 Subject: [PATCH 091/356] switch to Project.toml --- RecipesBase/.gitignore | 1 + RecipesBase/.travis.yml | 2 +- RecipesBase/Project.toml | 14 ++++++++++++++ RecipesBase/REQUIRE | 1 - RecipesBase/appveyor.yml | 2 +- 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 RecipesBase/Project.toml delete mode 100644 RecipesBase/REQUIRE diff --git a/RecipesBase/.gitignore b/RecipesBase/.gitignore index 8c960ec80..3f02ca741 100644 --- a/RecipesBase/.gitignore +++ b/RecipesBase/.gitignore @@ -1,3 +1,4 @@ *.jl.cov *.jl.*.cov *.jl.mem +Manifest.toml diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index 0e61dbb63..678e0739d 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - 0.7 + - 1.1 - nightly notifications: email: false diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml new file mode 100644 index 000000000..b2d2987ea --- /dev/null +++ b/RecipesBase/Project.toml @@ -0,0 +1,14 @@ +name = "RecipesBase" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +author = ["Tom Breloff (@tbreloff)"] +version = "0.7.0" + +[compat] +julia = "≥ 1.0.0" + +[extras] +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test", "Random"] diff --git a/RecipesBase/REQUIRE b/RecipesBase/REQUIRE deleted file mode 100644 index 05b5ab4c7..000000000 --- a/RecipesBase/REQUIRE +++ /dev/null @@ -1 +0,0 @@ -julia 1.0 diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml index 831beb78f..cc15d5721 100644 --- a/RecipesBase/appveyor.yml +++ b/RecipesBase/appveyor.yml @@ -1,6 +1,6 @@ environment: matrix: - - julia_version: 0.7 + - julia_version: 1.1 - julia_version: latest platform: From 39fa2e3fb07865a106683c34fdb2593d62ba49b3 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 4 Jun 2019 20:34:29 +0200 Subject: [PATCH 092/356] use default travis script --- RecipesBase/.travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index 678e0739d..3b5f71c6f 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -9,6 +9,6 @@ julia: notifications: email: false # uncomment the following lines to override the default test script -script: - - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - - julia -e 'import Pkg; Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' +# script: +# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi +# - julia -e 'import Pkg; Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' From eeb30640bf5f9a89ebab2e5cd54dd74c4c02d727 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 13 Jun 2019 09:39:22 -0500 Subject: [PATCH 093/356] Fix missing RecipesBase. prefix in @userplot. --- RecipesBase/src/RecipesBase.jl | 2 +- RecipesBase/test/runtests.jl | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b7b0bac80..eabd492d5 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -349,7 +349,7 @@ function _userplot(expr::Expr) export $funcname, $funcname2 Core.@__doc__ $funcname(args...; kw...) = RecipesBase.plot($typename(args); kw...) Core.@__doc__ $funcname2(args...; kw...) = RecipesBase.plot!($typename(args); kw...) - Core.@__doc__ $funcname2(plt::AbstractPlot, args...; kw...) = RecipesBase.plot!(plt, $typename(args); kw...) + Core.@__doc__ $funcname2(plt::RecipesBase.AbstractPlot, args...; kw...) = RecipesBase.plot!(plt, $typename(args); kw...) end) end diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index cac6e4fb0..905432da1 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -1,4 +1,7 @@ -using RecipesBase +# Run tests with `import RecipesBase` instead of `using RecipesBase` to test +# that objects like `AbstractPlot` are properly prefixed with `RecipesBase.` in +# the macros. +import RecipesBase using Test, Random const KW = Dict{Symbol, Any} @@ -30,7 +33,7 @@ end @testset "simple parametric type" begin @test_throws MethodError RecipesBase.apply_recipe(KW(), T1()) - @recipe function plot(t::T1, n::N = 1; customcolor = :green) where N <: Integer + RecipesBase.@recipe function plot(t::T1, n::N = 1; customcolor = :green) where N <: Integer :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 5 @@ -51,7 +54,7 @@ end @testset "parametric type with where" begin @test_throws MethodError RecipesBase.apply_recipe(KW(), T2()) - @recipe function plot(t::T2, n::N = 1; customcolor = :green) where {N <: Integer} + RecipesBase.@recipe function plot(t::T2, n::N = 1; customcolor = :green) where {N <: Integer} :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 5 @@ -72,8 +75,9 @@ end @testset "parametric type with double where" begin @test_throws MethodError RecipesBase.apply_recipe(KW(), T3()) - @recipe function plot(t::T3, n::N = 1, m::M = 0.0; - customcolor = :green) where {N <: Integer} where {M <: Float64} + RecipesBase.@recipe function plot( + t::T3, n::N = 1, m::M = 0.0; customcolor = :green + ) where {N <: Integer} where {M <: Float64} :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 5 @@ -92,7 +96,7 @@ end @testset "manual access of plotattributes" begin - @recipe function plot(t::T4, n = 1; customcolor = :green) + RecipesBase.@recipe function plot(t::T4, n = 1; customcolor = :green) :markershape --> :auto, :require :markercolor --> customcolor, :force :xrotation --> 5 @@ -114,3 +118,15 @@ end end end # @testset "@recipe" + +# Can't do this inside a test-set, because it creates a struct. +RecipesBase.@userplot MyPlot + +@testset "@userplot" begin + @test typeof(myplot) <: Function + @test length(methods(myplot)) == 1 + @test typeof(myplot!) <: Function + @test length(methods(myplot!)) == 2 + m = MyPlot(:my_arg) + @test m.args == :my_arg +end From 62d4eb6ea0e4475fa5f628d203a46dc59fe13fc8 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sat, 5 Oct 2019 14:35:51 -0400 Subject: [PATCH 094/356] Document the `@shorthands` macro (#56) * Update RecipesBase.jl * properly escape string this isn't markdown, after all * properly escape dollar signs --- RecipesBase/src/RecipesBase.jl | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index eabd492d5..ceb0754fd 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -361,7 +361,27 @@ end #---------------------------------------------------------------------------- -# define and export shorthand plotting method definitions +""" + @shorthands(funcname::Symbol) + +Defines and exports shorthand plotting method definitions (`\$funcname` and `\$funcname!`). +Pass the series type (as a symbol) to the macro. + +## Examples + +```julia +# define some series type +@recipe function f(::Type{Val{:myseriestype}}, x, y) + # some implementation here +end +# docstrings are forwarded +\"\"\" + myseriestype(x, y) +Plot my series type! +\"\"\" +@shorthands myseriestype +``` +""" macro shorthands(funcname::Symbol) funcname2 = Symbol(funcname, "!") esc(quote From 62132f70fe0c0ddfd10bab6b8b7897ef0ab98b23 Mon Sep 17 00:00:00 2001 From: yha Date: Wed, 29 Jan 2020 00:29:39 +0200 Subject: [PATCH 095/356] Fix "-->" by distinguishing explicit and default attributes. --- RecipesBase/src/RecipesBase.jl | 12 ++++++++---- RecipesBase/test/runtests.jl | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index ceb0754fd..2317f4fad 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -39,7 +39,11 @@ group_as_matrix(t) = false # This holds the recipe definitions to be dispatched on # the function takes in an attribute dict `d` and a list of args. # This default definition specifies the "no-arg" case. -apply_recipe(plotattributes::Dict{Symbol,Any}) = () +apply_recipe(plotattributes::AbstractDict{Symbol,Any}) = () + +# Is a key explicitly provided by the user? +# Should be overridden for subtypes representing plot attributes. +is_explicit(d::AbstractDict{Symbol,Any}, k) = haskey(d, k) const _debug_recipes = Bool[false] function debug(v::Bool = true) @@ -50,7 +54,7 @@ end # this holds the data and attributes of one series, and is returned from apply_recipe struct RecipeData - plotattributes::Dict{Symbol,Any} + plotattributes::AbstractDict{Symbol,Any} args::Tuple end @@ -86,7 +90,7 @@ function get_function_def(func_signature::Expr, args::Vector) if func_signature.head == :where Expr(:where, get_function_def(front, args), esc.(func_signature.args[2:end])...) elseif func_signature.head == :call - func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(plotattributes::Dict{Symbol, Any}); args])...) + func = Expr(:call, :(RecipesBase.apply_recipe), esc.([:(plotattributes::AbstractDict{Symbol, Any}); args])...) if isa(front, Expr) && front.head == :curly Expr(:where, func, esc.(front.args[2:end])...) else @@ -168,7 +172,7 @@ function process_recipe_body!(expr::Expr) :(plotattributes[$k] = $v) else # if the user has set this keyword, use theirs - :(get!(plotattributes, $k, $v)) + :(RecipesBase.is_explicit(plotattributes, $k) || (plotattributes[$k] = $v)) end expr.args[i] = if quiet diff --git a/RecipesBase/test/runtests.jl b/RecipesBase/test/runtests.jl index 905432da1..9ba9272f0 100644 --- a/RecipesBase/test/runtests.jl +++ b/RecipesBase/test/runtests.jl @@ -8,7 +8,7 @@ const KW = Dict{Symbol, Any} RecipesBase.is_key_supported(k::Symbol) = true -for t in [Symbol(:T, i) for i in 1:4] +for t in [Symbol(:T, i) for i in 1:5] @eval struct $t end end @@ -96,6 +96,8 @@ end @testset "manual access of plotattributes" begin + @test_throws MethodError RecipesBase.apply_recipe(KW(), T4()) + RecipesBase.@recipe function plot(t::T4, n = 1; customcolor = :green) :markershape --> :auto, :require :markercolor --> customcolor, :force @@ -117,6 +119,19 @@ end )) end +@testset "no force" begin + @test_throws MethodError RecipesBase.apply_recipe(KW(), T5()) + + RecipesBase.@recipe function plot(t::T5, n::Integer = 1) + customcolor --> :notred + rand(10, n) + end + + Random.seed!(1) + check_apply_recipe(T5, KW(:customcolor => :red)) +end + + end # @testset "@recipe" # Can't do this inside a test-set, because it creates a struct. From 804964818ba74d785b261d9f4a0e338d6a8f8b0a Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 6 Feb 2020 12:05:07 +0100 Subject: [PATCH 096/356] up version for release --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index b2d2987ea..6f644b647 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "0.7.0" +version = "0.8.0" [compat] julia = "≥ 1.0.0" From 86a02cd097884072a45cbb88bec02a057b0ecac7 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 6 Feb 2020 12:07:22 +0100 Subject: [PATCH 097/356] Create CompatHelper.yml --- .../.github/workflows/CompatHelper.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 RecipesBase/.github/workflows/CompatHelper.yml diff --git a/RecipesBase/.github/workflows/CompatHelper.yml b/RecipesBase/.github/workflows/CompatHelper.yml new file mode 100644 index 000000000..dd821e683 --- /dev/null +++ b/RecipesBase/.github/workflows/CompatHelper.yml @@ -0,0 +1,19 @@ +name: CompatHelper + +on: + schedule: + - cron: '00 00 * * *' + +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@latest + with: + version: 1.3 + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: julia -e 'using CompatHelper; CompatHelper.main()' From 7222fe377a99863dedf4746c9b552638824caf4c Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Thu, 6 Feb 2020 12:13:09 +0100 Subject: [PATCH 098/356] julia version consistent with guidelines --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index 6f644b647..9b2cd0758 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -4,7 +4,7 @@ author = ["Tom Breloff (@tbreloff)"] version = "0.8.0" [compat] -julia = "≥ 1.0.0" +julia = "1" [extras] Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" From 42d770d23caea9bf753d4244310193d4abcbfeb2 Mon Sep 17 00:00:00 2001 From: Julia TagBot <50554310+JuliaTagBot@users.noreply.github.com> Date: Sat, 8 Feb 2020 20:36:23 +0700 Subject: [PATCH 099/356] Install TagBot as a GitHub Action --- RecipesBase/.github/workflows/TagBot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 RecipesBase/.github/workflows/TagBot.yml diff --git a/RecipesBase/.github/workflows/TagBot.yml b/RecipesBase/.github/workflows/TagBot.yml new file mode 100644 index 000000000..d77d3a0c3 --- /dev/null +++ b/RecipesBase/.github/workflows/TagBot.yml @@ -0,0 +1,11 @@ +name: TagBot +on: + schedule: + - cron: 0 * * * * +jobs: + TagBot: + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} From 9c7b5eb7858ff2cc79f9c148919d3c0a9b9f4809 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 13:36:45 +0100 Subject: [PATCH 100/356] Initial commit From 61c632a12f3817df8e5543f913c45644a9126aca Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 13:37:06 +0100 Subject: [PATCH 101/356] Files generated by PkgTemplates --- RecipesPipeline/.gitignore | 6 ++++++ RecipesPipeline/.travis.yml | 16 ++++++++++++++++ RecipesPipeline/LICENSE | 19 +++++++++++++++++++ RecipesPipeline/Project.toml | 13 +++++++++++++ RecipesPipeline/README.md | 4 ++++ RecipesPipeline/src/RecipeUtils.jl | 5 +++++ RecipesPipeline/test/runtests.jl | 6 ++++++ 7 files changed, 69 insertions(+) create mode 100644 RecipesPipeline/.gitignore create mode 100644 RecipesPipeline/.travis.yml create mode 100644 RecipesPipeline/LICENSE create mode 100644 RecipesPipeline/Project.toml create mode 100644 RecipesPipeline/README.md create mode 100644 RecipesPipeline/src/RecipeUtils.jl create mode 100644 RecipesPipeline/test/runtests.jl diff --git a/RecipesPipeline/.gitignore b/RecipesPipeline/.gitignore new file mode 100644 index 000000000..1388e96ac --- /dev/null +++ b/RecipesPipeline/.gitignore @@ -0,0 +1,6 @@ +*.jl.*.cov +*.jl.cov +*.jl.mem +.DS_Store +/Manifest.toml +/dev/ diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml new file mode 100644 index 000000000..7a372f8ff --- /dev/null +++ b/RecipesPipeline/.travis.yml @@ -0,0 +1,16 @@ +# Documentation: http://docs.travis-ci.com/user/languages/julia/ +language: julia +os: + - linux + - osx +julia: + - 1.0 + - nightly +notifications: + email: false +after_success: + - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' +jobs: + allow_failures: + - julia: nightly + fast_finish: true diff --git a/RecipesPipeline/LICENSE b/RecipesPipeline/LICENSE new file mode 100644 index 000000000..40d57c76f --- /dev/null +++ b/RecipesPipeline/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Michael Krabbe Borregaard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml new file mode 100644 index 000000000..5de6827a4 --- /dev/null +++ b/RecipesPipeline/Project.toml @@ -0,0 +1,13 @@ +name = "RecipeUtils" +uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" +authors = ["Michael Krabbe Borregaard "] +version = "0.1.0" + +[compat] +julia = "1" + +[extras] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test"] diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md new file mode 100644 index 000000000..a68ad847f --- /dev/null +++ b/RecipesPipeline/README.md @@ -0,0 +1,4 @@ +# RecipeUtils + +[![Build Status](https://travis-ci.com/mkborregaard/RecipeUtils.jl.svg?branch=master)](https://travis-ci.com/mkborregaard/RecipeUtils.jl) +[![Codecov](https://codecov.io/gh/mkborregaard/RecipeUtils.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/mkborregaard/RecipeUtils.jl) diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipeUtils.jl new file mode 100644 index 000000000..8e7306ac7 --- /dev/null +++ b/RecipesPipeline/src/RecipeUtils.jl @@ -0,0 +1,5 @@ +module RecipeUtils + +greet() = print("Hello World!") + +end # module diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl new file mode 100644 index 000000000..d62153096 --- /dev/null +++ b/RecipesPipeline/test/runtests.jl @@ -0,0 +1,6 @@ +using RecipeUtils +using Test + +@testset "RecipeUtils.jl" begin + # Write your own tests here. +end From 85d5acd57422f8b5558dc48a1fd394c6e5eaccf5 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 13:53:42 +0100 Subject: [PATCH 102/356] Create pipeline.jl --- RecipesPipeline/src/pipeline.jl | 1 + 1 file changed, 1 insertion(+) create mode 100644 RecipesPipeline/src/pipeline.jl diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/RecipesPipeline/src/pipeline.jl @@ -0,0 +1 @@ + From 05a8f4044c46a579fd2a22ef54a362256de26ebe Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 13:53:56 +0100 Subject: [PATCH 103/356] move in three functions --- RecipesPipeline/src/RecipeUtils.jl | 2 +- RecipesPipeline/src/pipeline.jl | 110 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 RecipesPipeline/src/pipeline.jl diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipeUtils.jl index 8e7306ac7..185f66c03 100644 --- a/RecipesPipeline/src/RecipeUtils.jl +++ b/RecipesPipeline/src/RecipeUtils.jl @@ -1,5 +1,5 @@ module RecipeUtils -greet() = print("Hello World!") +include("pipeline.jl") end # module diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl new file mode 100644 index 000000000..c6758222f --- /dev/null +++ b/RecipesPipeline/src/pipeline.jl @@ -0,0 +1,110 @@ + +function _process_userrecipes(plt::Plot, plotattributes::AKW, args) + still_to_process = RecipeData[] + args = _preprocess_args(plotattributes, args, still_to_process) + + # for plotting recipes, swap out the args and update the parameter dictionary + # we are keeping a stack of series that still need to be processed. + # each pass through the loop, we pop one off and apply the recipe. + # the recipe will return a list a Series objects... the ones that are + # finished (no more args) get added to the kw_list, the ones that are not + # are placed on top of the stack and are then processed further. + kw_list = KW[] + while !isempty(still_to_process) + # grab the first in line to be processed and either add it to the kw_list or + # pass it through apply_recipe to generate a list of RecipeData objects (data + attributes) + # for further processing. + next_series = popfirst!(still_to_process) + # recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes + if !(typeof(next_series) <: RecipeData) + error("Inputs couldn't be processed... expected RecipeData but got: $next_series") + end + if isempty(next_series.args) + _process_userrecipe(plt, kw_list, next_series) + else + rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) + prepend!(still_to_process,rd_list) + end + end + + # don't allow something else to handle it + plotattributes[:smooth] = false + kw_list +end + +# plot recipes + +# Grab the first in line to be processed and pass it through apply_recipe +# to generate a list of RecipeData objects (data + attributes). +# If we applied a "plot recipe" without error, then add the returned datalist's KWs, +# otherwise we just add the original KW. +function _process_plotrecipe(plt::Plot, kw::AKW, kw_list::Vector{KW}, still_to_process::Vector{KW}) + if !isa(get(kw, :seriestype, nothing), Symbol) + # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe + push!(kw_list, kw) + return + end + try + st = kw[:seriestype] + st = kw[:seriestype] = get(_typeAliases, st, st) + datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) + for data in datalist + preprocessArgs!(data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + end + push!(still_to_process, data.plotattributes) + end + catch err + if isa(err, MethodError) + push!(kw_list, kw) + else + rethrow() + end + end + return +end + +# ------------------------------------------------------------------------------- + +# this method recursively applies series recipes when the seriestype is not supported +# natively by the backend +function _process_seriesrecipe(plt::Plot, plotattributes::AKW) + #println("process $(typeof(plotattributes))") + # replace seriestype aliases + st = Symbol(plotattributes[:seriestype]) + st = plotattributes[:seriestype] = get(_typeAliases, st, st) + + # shapes shouldn't have fillrange set + if plotattributes[:seriestype] == :shape + plotattributes[:fillrange] = nothing + end + + # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse + if is_seriestype_supported(st) + sp = _prepare_subplot(plt, plotattributes) + _prepare_annotations(sp, plotattributes) + _expand_subplot_extrema(sp, plotattributes, st) + _update_series_attributes!(plotattributes, plt, sp) + _add_the_series(plt, sp, plotattributes) + + else + # get a sub list of series for this seriestype + datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, plotattributes[:x], plotattributes[:y], plotattributes[:z]) + + # assuming there was no error, recursively apply the series recipes + for data in datalist + if isa(data, RecipeData) + preprocessArgs!(data.plotattributes) + if data.plotattributes[:seriestype] == st + error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") + end + _process_seriesrecipe(plt, data.plotattributes) + else + @warn("Unhandled recipe: $(data)") + break + end + end + end + nothing +end From 6362d49a0a12b9b9a5900f1724181fb79c7a7f09 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:10:30 +0100 Subject: [PATCH 104/356] duck type for `Plot` --- RecipesPipeline/src/pipeline.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index c6758222f..18838d388 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -1,5 +1,5 @@ -function _process_userrecipes(plt::Plot, plotattributes::AKW, args) +function _process_userrecipes(plt, plotattributes::AKW, args) still_to_process = RecipeData[] args = _preprocess_args(plotattributes, args, still_to_process) From 88981c5aa2354a8d20ad58986b599274845fc6c8 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:14:10 +0100 Subject: [PATCH 105/356] replace KW and AKW --- RecipesPipeline/src/pipeline.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 18838d388..5a8d02900 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -1,6 +1,8 @@ +_preprocess_args(p, args, s) = args + function _process_userrecipes(plt, plotattributes::AKW, args) - still_to_process = RecipeData[] + still_to_process = RecipesBase.RecipeData[] args = _preprocess_args(plotattributes, args, still_to_process) # for plotting recipes, swap out the args and update the parameter dictionary @@ -16,7 +18,7 @@ function _process_userrecipes(plt, plotattributes::AKW, args) # for further processing. next_series = popfirst!(still_to_process) # recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes - if !(typeof(next_series) <: RecipeData) + if !(typeof(next_series) <: RecipesBase.RecipeData) error("Inputs couldn't be processed... expected RecipeData but got: $next_series") end if isempty(next_series.args) @@ -94,7 +96,7 @@ function _process_seriesrecipe(plt::Plot, plotattributes::AKW) # assuming there was no error, recursively apply the series recipes for data in datalist - if isa(data, RecipeData) + if isa(data, RecipesBase.RecipeData) preprocessArgs!(data.plotattributes) if data.plotattributes[:seriestype] == st error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") From 31281c87e7b28b4c9ef5edd7bff2e260582cc3ae Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 14:15:56 +0100 Subject: [PATCH 106/356] sketch --- RecipesPipeline/src/pipeline.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 8b1378917..4256370bb 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -1 +1,19 @@ +# Here comes the specification of when which recipe is processed. +# It contains functions before and after every stage for interaction with the plotting package. + +function recipe_pipeline(plt, # frontend specific representation of a plot + plotattributes, # current state of recipe keywords + args, # set of arguments passed by the user + ) + _recipe_init(plt, plotattributes, args) + kw_list = _process_userrecipes(plt, plotattributes, args) + _recipe_after_user(plt, plotattributes, args) + kw_list = _process_plotrecipes(plt, plotattributes, args) + _recipe_after_plot(plt, plotattributes, args) + for (series_ind, series) in enumerate(series_list) + kw_list = _process_seriesrecipe(plt, plotattributes) + _recipe_after_series(plt, plotattributes, series_ind) + end + _recipe +end From 3442853a0e17c70bacd11dd461bbcf26a1205928 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 14:16:40 +0100 Subject: [PATCH 107/356] Update pipeline.jl --- RecipesPipeline/src/pipeline.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 4256370bb..794393a3f 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -15,5 +15,5 @@ function recipe_pipeline(plt, # frontend specific representation of kw_list = _process_seriesrecipe(plt, plotattributes) _recipe_after_series(plt, plotattributes, series_ind) end - _recipe + _recipe_finish((plt, plotattributes, args) end From 8ed3ac56c4e419eb7d49bbaed0050d7c976e4cd4 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:22:56 +0100 Subject: [PATCH 108/356] rename file --- RecipesPipeline/src/RecipeUtils.jl | 2 +- RecipesPipeline/src/{pipeline.jl => process_recipes.jl} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename RecipesPipeline/src/{pipeline.jl => process_recipes.jl} (92%) diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipeUtils.jl index 185f66c03..009d4908c 100644 --- a/RecipesPipeline/src/RecipeUtils.jl +++ b/RecipesPipeline/src/RecipeUtils.jl @@ -1,5 +1,5 @@ module RecipeUtils -include("pipeline.jl") +include("process_recipes.jl") end # module diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/process_recipes.jl similarity index 92% rename from RecipesPipeline/src/pipeline.jl rename to RecipesPipeline/src/process_recipes.jl index 5a8d02900..a5605688b 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -1,7 +1,7 @@ _preprocess_args(p, args, s) = args -function _process_userrecipes(plt, plotattributes::AKW, args) +function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) still_to_process = RecipesBase.RecipeData[] args = _preprocess_args(plotattributes, args, still_to_process) @@ -11,7 +11,7 @@ function _process_userrecipes(plt, plotattributes::AKW, args) # the recipe will return a list a Series objects... the ones that are # finished (no more args) get added to the kw_list, the ones that are not # are placed on top of the stack and are then processed further. - kw_list = KW[] + kw_list = Dict{Symbol,Any}[] while !isempty(still_to_process) # grab the first in line to be processed and either add it to the kw_list or # pass it through apply_recipe to generate a list of RecipeData objects (data + attributes) @@ -40,7 +40,7 @@ end # to generate a list of RecipeData objects (data + attributes). # If we applied a "plot recipe" without error, then add the returned datalist's KWs, # otherwise we just add the original KW. -function _process_plotrecipe(plt::Plot, kw::AKW, kw_list::Vector{KW}, still_to_process::Vector{KW}) +function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}) if !isa(get(kw, :seriestype, nothing), Symbol) # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe push!(kw_list, kw) @@ -71,7 +71,7 @@ end # this method recursively applies series recipes when the seriestype is not supported # natively by the backend -function _process_seriesrecipe(plt::Plot, plotattributes::AKW) +function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}) #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) From e74e2f158140b41f9c7bc8a9d9dfd3ee5188c04f Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:28:49 +0100 Subject: [PATCH 109/356] stub functions --- RecipesPipeline/src/process_recipes.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index a5605688b..4fd9746fc 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -1,5 +1,7 @@ -_preprocess_args(p, args, s) = args +_preprocess_args(p, args, s) = args #needs to modify still_to_process +preprocessArgs!(p) = p +is_seriestype_supported(st) = true function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) still_to_process = RecipesBase.RecipeData[] @@ -48,7 +50,7 @@ function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{ end try st = kw[:seriestype] - st = kw[:seriestype] = get(_typeAliases, st, st) + st = kw[:seriestype] = get(_typeAliases, st, st) #TODO this requires access to the const_typeAliases datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) for data in datalist preprocessArgs!(data.plotattributes) @@ -75,7 +77,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}) #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) - st = plotattributes[:seriestype] = get(_typeAliases, st, st) + st = plotattributes[:seriestype] = get(_typeAliases, st, st) #TODO here again # shapes shouldn't have fillrange set if plotattributes[:seriestype] == :shape From a7c241f1df737f5c1a1a2b8f31dcd507abf82b1c Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:41:27 +0100 Subject: [PATCH 110/356] move finalize_subplot! to plots --- RecipesPipeline/src/process_recipes.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 4fd9746fc..e20096944 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -2,6 +2,7 @@ _preprocess_args(p, args, s) = args #needs to modify still_to_process preprocessArgs!(p) = p is_seriestype_supported(st) = true +finalize_subplot!(plt, att) = nothing function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) still_to_process = RecipesBase.RecipeData[] @@ -86,11 +87,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}) # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse if is_seriestype_supported(st) - sp = _prepare_subplot(plt, plotattributes) - _prepare_annotations(sp, plotattributes) - _expand_subplot_extrema(sp, plotattributes, st) - _update_series_attributes!(plotattributes, plt, sp) - _add_the_series(plt, sp, plotattributes) + finalize_subplot!(plt, plotattributes) else # get a sub list of series for this seriestype From 3aa4250b54aa4d814f681490b444f5ce1e072667 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:48:47 +0100 Subject: [PATCH 111/356] avoid overwriting method --- RecipesPipeline/src/process_recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index e20096944..1a8b78c9a 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -1,7 +1,7 @@ _preprocess_args(p, args, s) = args #needs to modify still_to_process preprocessArgs!(p) = p -is_seriestype_supported(st) = true +is_st_supported(st) = true finalize_subplot!(plt, att) = nothing function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) From 69eb0e3c5dd85691a48c742836b93b0c3d187556 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 14:55:06 +0100 Subject: [PATCH 112/356] make _typeAliases local --- RecipesPipeline/src/process_recipes.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 1a8b78c9a..61c113d71 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -43,7 +43,7 @@ end # to generate a list of RecipeData objects (data + attributes). # If we applied a "plot recipe" without error, then add the returned datalist's KWs, # otherwise we just add the original KW. -function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}) +function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; _typeAliases::AbstractDict{Symbol,Symbol}=Dict()) if !isa(get(kw, :seriestype, nothing), Symbol) # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe push!(kw_list, kw) @@ -51,7 +51,7 @@ function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{ end try st = kw[:seriestype] - st = kw[:seriestype] = get(_typeAliases, st, st) #TODO this requires access to the const_typeAliases + st = kw[:seriestype] = get(_typeAliases, st, st) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) for data in datalist preprocessArgs!(data.plotattributes) @@ -74,11 +74,11 @@ end # this method recursively applies series recipes when the seriestype is not supported # natively by the backend -function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}) +function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; _typeAliases::AbstractDict{Symbol,Symbol}=Dict()) #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) - st = plotattributes[:seriestype] = get(_typeAliases, st, st) #TODO here again + st = plotattributes[:seriestype] = get(_typeAliases, st, st) # shapes shouldn't have fillrange set if plotattributes[:seriestype] == :shape From 43057007544b8201093f9165d20862d54979caf6 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sat, 14 Mar 2020 14:55:49 +0100 Subject: [PATCH 113/356] import recipesbase --- RecipesPipeline/src/RecipeUtils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipeUtils.jl index 009d4908c..ac4d91248 100644 --- a/RecipesPipeline/src/RecipeUtils.jl +++ b/RecipesPipeline/src/RecipeUtils.jl @@ -1,5 +1,6 @@ module RecipeUtils +import RecipesBase include("process_recipes.jl") end # module From f4ffb36d12745517ef5578b4813a78fdbbc50489 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 14 Mar 2020 15:11:22 +0100 Subject: [PATCH 114/356] add RecipesBase dependency --- RecipesPipeline/Project.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 5de6827a4..66c01e158 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -3,6 +3,9 @@ uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] version = "0.1.0" +[deps] +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + [compat] julia = "1" From ac27da095861b4fde2221b0b07757e840bad050b Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 15:33:10 +0100 Subject: [PATCH 115/356] remove :smooth handling --- RecipesPipeline/src/process_recipes.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 61c113d71..59f4db947 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -32,8 +32,6 @@ function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, arg end end - # don't allow something else to handle it - plotattributes[:smooth] = false kw_list end From 4b9cf60759360b9cc810dd708330d445c6d2cb7f Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sat, 14 Mar 2020 17:55:06 +0100 Subject: [PATCH 116/356] add _recipe function stubs (#8) * add _recipe function stubs * add bangs --- RecipesPipeline/src/pipeline.jl | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 794393a3f..0aae274c8 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -1,19 +1,25 @@ - +## Stubs +function _recipe_init!(plt, plotattributes, args) end +function _recipe_after_user!(plt, plotattributes, args) end +function _recipe_after_plot!(plt, plotattributes, args) end +function _recipe_after_series!(plt, plotattributes, args, series_ind) end +function _recipe_finish!(plt, plotattributes, args) end +## # Here comes the specification of when which recipe is processed. # It contains functions before and after every stage for interaction with the plotting package. -function recipe_pipeline(plt, # frontend specific representation of a plot +function recipe_pipeline!(plt, # frontend specific representation of a plot plotattributes, # current state of recipe keywords args, # set of arguments passed by the user ) - _recipe_init(plt, plotattributes, args) + _recipe_init!(plt, plotattributes, args) kw_list = _process_userrecipes(plt, plotattributes, args) - _recipe_after_user(plt, plotattributes, args) + _recipe_after_user!(plt, plotattributes, args) kw_list = _process_plotrecipes(plt, plotattributes, args) - _recipe_after_plot(plt, plotattributes, args) + _recipe_after_plot!(plt, plotattributes, args) for (series_ind, series) in enumerate(series_list) kw_list = _process_seriesrecipe(plt, plotattributes) - _recipe_after_series(plt, plotattributes, series_ind) + _recipe_after_series!(plt, plotattributes, series_ind) end - _recipe_finish((plt, plotattributes, args) + _recipe_finish!((plt, plotattributes, args) end From a15273ce091f34aa11bdc10674ed3e8cfbe48627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sat, 14 Mar 2020 21:19:08 +0200 Subject: [PATCH 117/356] Copy more stuff from Plots._plot Copy _process_seriesrecipe handling from _plot Rename `_recipe_after_series!` to `_recipe_before_series` Copy comments over --- RecipesPipeline/src/pipeline.jl | 63 ++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 0aae274c8..e7e2e0a1e 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -1,25 +1,56 @@ ## Stubs function _recipe_init!(plt, plotattributes, args) end function _recipe_after_user!(plt, plotattributes, args) end -function _recipe_after_plot!(plt, plotattributes, args) end -function _recipe_after_series!(plt, plotattributes, args, series_ind) end +function _recipe_after_plot!(plt, plotattributes, kw_list) end +function _recipe_before_series!(plt, kw, kw_list) end function _recipe_finish!(plt, plotattributes, args) end + ## # Here comes the specification of when which recipe is processed. # It contains functions before and after every stage for interaction with the plotting package. -function recipe_pipeline!(plt, # frontend specific representation of a plot - plotattributes, # current state of recipe keywords - args, # set of arguments passed by the user - ) - _recipe_init!(plt, plotattributes, args) - kw_list = _process_userrecipes(plt, plotattributes, args) - _recipe_after_user!(plt, plotattributes, args) - kw_list = _process_plotrecipes(plt, plotattributes, args) - _recipe_after_plot!(plt, plotattributes, args) - for (series_ind, series) in enumerate(series_list) - kw_list = _process_seriesrecipe(plt, plotattributes) - _recipe_after_series!(plt, plotattributes, series_ind) - end - _recipe_finish!((plt, plotattributes, args) +function recipe_pipeline!(plt, # frontend specific representation of a plot + plotattributes, # current state of recipe keywords + args; # set of arguments passed by the user + _typeAliases=Dict()) + + _recipe_init!(plt, plotattributes, args) + + # -------------------------------- + # "USER RECIPES" + # -------------------------------- + + kw_list = _process_userrecipes(plt, plotattributes, args) + _recipe_after_user!(plt, plotattributes, args) + + # -------------------------------- + # "PLOT RECIPES" + # -------------------------------- + + # "plot recipe", which acts like a series type, and is processed before + # the plot layout is created, which allows for setting layouts and other plot-wide attributes. + # we get inputs which have been fully processed by "user recipes" and "type recipes", + # so we can expect standard vectors, surfaces, etc. No defaults have been set yet. + still_to_process = kw_list + kw_list = Dict{Symbol,Any}[] + while !isempty(still_to_process) + next_kw = popfirst!(still_to_process) + _process_plotrecipe(plt, next_kw, kw_list, still_to_process; _typeAliases=_typeAliases) + end + + _recipe_after_plot!(plt, plotattributes, kw_list) + + # !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!! + # !!! The next step is to recursively apply series recipes until the backend supports that series type !!! + + # -------------------------------- + # "SERIES RECIPES" + # -------------------------------- + + for kw in kw_list + series_attr = _recipe_before_series!(plt, kw, kw_list) + kw_list = _process_seriesrecipe(plt, series_attr) + end + + _recipe_finish!(plt, plotattributes, args) end From 7d3ec83e0e9559f757d14d85842ad9f9e49218ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sat, 14 Mar 2020 21:19:39 +0200 Subject: [PATCH 118/356] Use the pipeline.jl interface --- RecipesPipeline/src/RecipeUtils.jl | 1 + RecipesPipeline/src/process_recipes.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipeUtils.jl index ac4d91248..fd2abac44 100644 --- a/RecipesPipeline/src/RecipeUtils.jl +++ b/RecipesPipeline/src/RecipeUtils.jl @@ -1,6 +1,7 @@ module RecipeUtils import RecipesBase +include("pipeline.jl") include("process_recipes.jl") end # module diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 59f4db947..41c8cc614 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -1,5 +1,6 @@ _preprocess_args(p, args, s) = args #needs to modify still_to_process +_process_userrecipe(plt, kw_list, next_series) = nothing preprocessArgs!(p) = p is_st_supported(st) = true finalize_subplot!(plt, att) = nothing From 6c6a22cc233c1ad76be1f172e48a64803534d946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sat, 14 Mar 2020 22:27:12 +0200 Subject: [PATCH 119/356] Rename _typeAliases to type_aliases --- RecipesPipeline/src/pipeline.jl | 4 ++-- RecipesPipeline/src/process_recipes.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index e7e2e0a1e..c89e08542 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -12,7 +12,7 @@ function _recipe_finish!(plt, plotattributes, args) end function recipe_pipeline!(plt, # frontend specific representation of a plot plotattributes, # current state of recipe keywords args; # set of arguments passed by the user - _typeAliases=Dict()) + type_aliases) _recipe_init!(plt, plotattributes, args) @@ -35,7 +35,7 @@ function recipe_pipeline!(plt, # frontend specific representation o kw_list = Dict{Symbol,Any}[] while !isempty(still_to_process) next_kw = popfirst!(still_to_process) - _process_plotrecipe(plt, next_kw, kw_list, still_to_process; _typeAliases=_typeAliases) + _process_plotrecipe(plt, next_kw, kw_list, still_to_process; type_aliases=type_aliases) end _recipe_after_plot!(plt, plotattributes, kw_list) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 41c8cc614..9d51ebb9e 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -73,7 +73,7 @@ end # this method recursively applies series recipes when the seriestype is not supported # natively by the backend -function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; _typeAliases::AbstractDict{Symbol,Symbol}=Dict()) +function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; type_aliases::AbstractDict{Symbol,Symbol}) #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) From 9580d06429be971ce337ea3e07559b1502bd6876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sat, 14 Mar 2020 23:34:14 +0200 Subject: [PATCH 120/356] Rename --- RecipesPipeline/Project.toml | 2 +- RecipesPipeline/src/{RecipeUtils.jl => RecipePipeline.jl} | 2 +- RecipesPipeline/test/runtests.jl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename RecipesPipeline/src/{RecipeUtils.jl => RecipePipeline.jl} (79%) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 66c01e158..918c2877a 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,4 +1,4 @@ -name = "RecipeUtils" +name = "RecipePipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] version = "0.1.0" diff --git a/RecipesPipeline/src/RecipeUtils.jl b/RecipesPipeline/src/RecipePipeline.jl similarity index 79% rename from RecipesPipeline/src/RecipeUtils.jl rename to RecipesPipeline/src/RecipePipeline.jl index fd2abac44..ceda55c57 100644 --- a/RecipesPipeline/src/RecipeUtils.jl +++ b/RecipesPipeline/src/RecipePipeline.jl @@ -1,4 +1,4 @@ -module RecipeUtils +module RecipePipeline import RecipesBase include("pipeline.jl") diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index d62153096..bee6d15f9 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -1,6 +1,6 @@ -using RecipeUtils +using RecipePipeline using Test -@testset "RecipeUtils.jl" begin +@testset "RecipePipeline.jl" begin # Write your own tests here. end From e97e861baec8e6f6f9024e952f5fa392d64133de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 15 Mar 2020 00:49:50 +0200 Subject: [PATCH 121/356] Fix _process_userrecipes --- RecipesPipeline/src/pipeline.jl | 2 +- RecipesPipeline/src/process_recipes.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index c89e08542..98520dc53 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -49,7 +49,7 @@ function recipe_pipeline!(plt, # frontend specific representation o for kw in kw_list series_attr = _recipe_before_series!(plt, kw, kw_list) - kw_list = _process_seriesrecipe(plt, series_attr) + kw_list = _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) end _recipe_finish!(plt, plotattributes, args) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 9d51ebb9e..313411960 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -42,7 +42,7 @@ end # to generate a list of RecipeData objects (data + attributes). # If we applied a "plot recipe" without error, then add the returned datalist's KWs, # otherwise we just add the original KW. -function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; _typeAliases::AbstractDict{Symbol,Symbol}=Dict()) +function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; type_aliases::AbstractDict{Symbol,Symbol}=Dict()) if !isa(get(kw, :seriestype, nothing), Symbol) # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe push!(kw_list, kw) @@ -77,7 +77,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) - st = plotattributes[:seriestype] = get(_typeAliases, st, st) + st = plotattributes[:seriestype] = get(type_aliases, st, st) # shapes shouldn't have fillrange set if plotattributes[:seriestype] == :shape @@ -85,7 +85,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty end # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse - if is_seriestype_supported(st) + if is_st_supported(st) finalize_subplot!(plt, plotattributes) else From 8ea9b4d1fb5ce525909b27686176807914c5f4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 15 Mar 2020 01:38:26 +0200 Subject: [PATCH 122/356] Don't modify kw_list while iterating it --- RecipesPipeline/src/pipeline.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 98520dc53..8a0729b93 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -49,7 +49,7 @@ function recipe_pipeline!(plt, # frontend specific representation o for kw in kw_list series_attr = _recipe_before_series!(plt, kw, kw_list) - kw_list = _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) + _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) end _recipe_finish!(plt, plotattributes, args) From a0d729a0e825d926edfe335d64102294328e38fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 15 Mar 2020 01:38:49 +0200 Subject: [PATCH 123/356] Fix finalize_subplot! --- RecipesPipeline/src/process_recipes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 313411960..88c2eb418 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -3,7 +3,7 @@ _preprocess_args(p, args, s) = args #needs to modify still_to_process _process_userrecipe(plt, kw_list, next_series) = nothing preprocessArgs!(p) = p is_st_supported(st) = true -finalize_subplot!(plt, att) = nothing +finalize_subplot!(plt, st, att) = nothing function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) still_to_process = RecipesBase.RecipeData[] @@ -50,7 +50,7 @@ function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{ end try st = kw[:seriestype] - st = kw[:seriestype] = get(_typeAliases, st, st) + st = kw[:seriestype] = get(type_aliases, st, st) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) for data in datalist preprocessArgs!(data.plotattributes) @@ -86,7 +86,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse if is_st_supported(st) - finalize_subplot!(plt, plotattributes) + finalize_subplot!(plt, st, plotattributes) else # get a sub list of series for this seriestype From 185f68c264c0fc6bebfacd320b92932f4a365ff0 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 12:38:57 +0100 Subject: [PATCH 124/356] return the plot object by default --- RecipesPipeline/src/pipeline.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index c89e08542..adcea64e3 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -3,7 +3,7 @@ function _recipe_init!(plt, plotattributes, args) end function _recipe_after_user!(plt, plotattributes, args) end function _recipe_after_plot!(plt, plotattributes, kw_list) end function _recipe_before_series!(plt, kw, kw_list) end -function _recipe_finish!(plt, plotattributes, args) end +function _recipe_finish!(plt, plotattributes, args) plt end ## # Here comes the specification of when which recipe is processed. From 8afa7a1314dd10ebaee0f44b6261dd5b0963e4ca Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sun, 15 Mar 2020 17:36:52 +0530 Subject: [PATCH 125/356] Change the dispatch for `is_st_supported` (#18) * add debug and error stuff * fix docstring * Update src/pipeline.jl --- RecipesPipeline/src/pipeline.jl | 5 +++- RecipesPipeline/src/process_recipes.jl | 39 ++++++++++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 8a0729b93..8830048f8 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -19,10 +19,11 @@ function recipe_pipeline!(plt, # frontend specific representation o # -------------------------------- # "USER RECIPES" # -------------------------------- - kw_list = _process_userrecipes(plt, plotattributes, args) _recipe_after_user!(plt, plotattributes, args) + # @show kw_list + # -------------------------------- # "PLOT RECIPES" # -------------------------------- @@ -36,6 +37,7 @@ function recipe_pipeline!(plt, # frontend specific representation o while !isempty(still_to_process) next_kw = popfirst!(still_to_process) _process_plotrecipe(plt, next_kw, kw_list, still_to_process; type_aliases=type_aliases) + # @show kw_list end _recipe_after_plot!(plt, plotattributes, kw_list) @@ -50,6 +52,7 @@ function recipe_pipeline!(plt, # frontend specific representation o for kw in kw_list series_attr = _recipe_before_series!(plt, kw, kw_list) _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) + @show series_attr end _recipe_finish!(plt, plotattributes, args) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 88c2eb418..1eefebca5 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -1,8 +1,31 @@ +# # The Recipe Consumer Interface +# To consume RecipesBase recipes, we allow plotting packages to overload the following +# hooks into the main Recipe pipeline. The docstrings should eventually describe all +# necessary functionality. +# All these methods have the first parameter as the plot object which is being acted on. +# This allows for a dispatch overload by any consumer of these recipes. -_preprocess_args(p, args, s) = args #needs to modify still_to_process +""" + _preprocess_args(p, args, s) + +Take in a Vector of RecipeData (`s`) and fill in default attributes. +""" +_preprocess_args(p, args, s) = args # needs to modify still_to_process + +""" +""" _process_userrecipe(plt, kw_list, next_series) = nothing + +""" +""" preprocessArgs!(p) = p -is_st_supported(st) = true + +""" +""" +is_st_supported(plt, st) = true + +""" +""" finalize_subplot!(plt, st, att) = nothing function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) @@ -23,7 +46,7 @@ function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, arg next_series = popfirst!(still_to_process) # recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes if !(typeof(next_series) <: RecipesBase.RecipeData) - error("Inputs couldn't be processed... expected RecipeData but got: $next_series") + @error("Inputs couldn't be processed. Expected RecipeData but got: $next_series") end if isempty(next_series.args) _process_userrecipe(plt, kw_list, next_series) @@ -55,7 +78,7 @@ function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{ for data in datalist preprocessArgs!(data.plotattributes) if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + @error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") end push!(still_to_process, data.plotattributes) end @@ -73,7 +96,7 @@ end # this method recursively applies series recipes when the seriestype is not supported # natively by the backend -function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; type_aliases::AbstractDict{Symbol,Symbol}) +function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; type_aliases::AbstractDict{Symbol,Symbol} = Dict{Symbol,Symbol}()) #println("process $(typeof(plotattributes))") # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) @@ -85,7 +108,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty end # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse - if is_st_supported(st) + if is_st_supported(plt, st) finalize_subplot!(plt, st, plotattributes) else @@ -97,7 +120,7 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty if isa(data, RecipesBase.RecipeData) preprocessArgs!(data.plotattributes) if data.plotattributes[:seriestype] == st - error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") + @error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") end _process_seriesrecipe(plt, data.plotattributes) else @@ -106,5 +129,5 @@ function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; ty end end end - nothing + return nothing end From f9b038d45b0a65c1d8c15bc55f8c8cdecae26ab4 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sun, 15 Mar 2020 20:09:17 +0530 Subject: [PATCH 126/356] Tune the defaults (#20) * comment out debug shows * fix defaults a bit * remove shows * remove shows * remove shows Co-authored-by: Simon Christ --- RecipesPipeline/src/pipeline.jl | 11 +++-------- RecipesPipeline/src/process_recipes.jl | 17 ++++++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 3a8b677f9..11489ac04 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -2,7 +2,7 @@ function _recipe_init!(plt, plotattributes, args) end function _recipe_after_user!(plt, plotattributes, args) end function _recipe_after_plot!(plt, plotattributes, kw_list) end -function _recipe_before_series!(plt, kw, kw_list) end +function _recipe_before_series!(plt, kw, kw_list) kw end # this must always return the kwargs function _recipe_finish!(plt, plotattributes, args) plt end ## @@ -12,7 +12,7 @@ function _recipe_finish!(plt, plotattributes, args) plt end function recipe_pipeline!(plt, # frontend specific representation of a plot plotattributes, # current state of recipe keywords args; # set of arguments passed by the user - type_aliases) + type_aliases = Dict{Symbol, Symbol}()) _recipe_init!(plt, plotattributes, args) @@ -22,8 +22,6 @@ function recipe_pipeline!(plt, # frontend specific representation o kw_list = _process_userrecipes(plt, plotattributes, args) _recipe_after_user!(plt, plotattributes, args) - # @show kw_list - # -------------------------------- # "PLOT RECIPES" # -------------------------------- @@ -37,9 +35,8 @@ function recipe_pipeline!(plt, # frontend specific representation o while !isempty(still_to_process) next_kw = popfirst!(still_to_process) _process_plotrecipe(plt, next_kw, kw_list, still_to_process; type_aliases=type_aliases) - # @show kw_list end - + _recipe_after_plot!(plt, plotattributes, kw_list) # !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!! @@ -48,11 +45,9 @@ function recipe_pipeline!(plt, # frontend specific representation o # -------------------------------- # "SERIES RECIPES" # -------------------------------- - for kw in kw_list series_attr = _recipe_before_series!(plt, kw, kw_list) _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) - @show series_attr end _recipe_finish!(plt, plotattributes, args) diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl index 1eefebca5..630bda1dc 100644 --- a/RecipesPipeline/src/process_recipes.jl +++ b/RecipesPipeline/src/process_recipes.jl @@ -10,8 +10,8 @@ Take in a Vector of RecipeData (`s`) and fill in default attributes. """ -_preprocess_args(p, args, s) = args # needs to modify still_to_process - +_preprocess_args(p, args, s) = append!(s, RecipesBase.RecipeData[RecipesBase.RecipeData(convert(Dict{Symbol, Any}, copy(p)), args)]) # needs to modify still_to_process +# TODO define RecipesBase constructor better """ """ _process_userrecipe(plt, kw_list, next_series) = nothing @@ -28,9 +28,10 @@ is_st_supported(plt, st) = true """ finalize_subplot!(plt, st, att) = nothing -function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, args) +function _process_userrecipes(plt, plotattributes::T, args) where T <: AbstractDict{Symbol, <: Any} still_to_process = RecipesBase.RecipeData[] - args = _preprocess_args(plotattributes, args, still_to_process) + # This should modify `still_to_process`! + _preprocess_args(plotattributes, args, still_to_process) # for plotting recipes, swap out the args and update the parameter dictionary # we are keeping a stack of series that still need to be processed. @@ -49,6 +50,8 @@ function _process_userrecipes(plt, plotattributes::AbstractDict{Symbol,Any}, arg @error("Inputs couldn't be processed. Expected RecipeData but got: $next_series") end if isempty(next_series.args) + # WARNING: you need to define this on your + # custom plot type! _process_userrecipe(plt, kw_list, next_series) else rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) @@ -65,7 +68,7 @@ end # to generate a list of RecipeData objects (data + attributes). # If we applied a "plot recipe" without error, then add the returned datalist's KWs, # otherwise we just add the original KW. -function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; type_aliases::AbstractDict{Symbol,Symbol}=Dict()) +function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; type_aliases::AbstractDict{Symbol, Symbol}=Dict{Symbol,Symbol}()) if !isa(get(kw, :seriestype, nothing), Symbol) # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe push!(kw_list, kw) @@ -78,7 +81,7 @@ function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{ for data in datalist preprocessArgs!(data.plotattributes) if data.plotattributes[:seriestype] == st - @error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") end push!(still_to_process, data.plotattributes) end @@ -97,7 +100,7 @@ end # this method recursively applies series recipes when the seriestype is not supported # natively by the backend function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; type_aliases::AbstractDict{Symbol,Symbol} = Dict{Symbol,Symbol}()) - #println("process $(typeof(plotattributes))") + # replace seriestype aliases st = Symbol(plotattributes[:seriestype]) st = plotattributes[:seriestype] = get(type_aliases, st, st) From 5e68f095f5eca800bdcf126c0974f6026b21e393 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 17:02:09 +0100 Subject: [PATCH 127/356] add after_series hook --- RecipesPipeline/src/pipeline.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl index 11489ac04..07ca62e02 100644 --- a/RecipesPipeline/src/pipeline.jl +++ b/RecipesPipeline/src/pipeline.jl @@ -3,6 +3,7 @@ function _recipe_init!(plt, plotattributes, args) end function _recipe_after_user!(plt, plotattributes, args) end function _recipe_after_plot!(plt, plotattributes, kw_list) end function _recipe_before_series!(plt, kw, kw_list) kw end # this must always return the kwargs +function _recipe_after_series!(plt, kw, series_ind) end function _recipe_finish!(plt, plotattributes, args) plt end ## @@ -45,9 +46,10 @@ function recipe_pipeline!(plt, # frontend specific representation o # -------------------------------- # "SERIES RECIPES" # -------------------------------- - for kw in kw_list + for (series_ind, kw) in enumerate(kw_list) series_attr = _recipe_before_series!(plt, kw, kw_list) _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) + _recipe_after_series!(plt, kw, series_ind) end _recipe_finish!(plt, plotattributes, args) From 621a24d6ab3e07872728d1ce8ff41cac4b91bcc2 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 16:49:20 +0100 Subject: [PATCH 128/356] add default recipes --- RecipesPipeline/src/RecipePipeline.jl | 1 + RecipesPipeline/src/default_recipes.jl | 64 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 RecipesPipeline/src/default_recipes.jl diff --git a/RecipesPipeline/src/RecipePipeline.jl b/RecipesPipeline/src/RecipePipeline.jl index ceda55c57..376507e01 100644 --- a/RecipesPipeline/src/RecipePipeline.jl +++ b/RecipesPipeline/src/RecipePipeline.jl @@ -3,5 +3,6 @@ module RecipePipeline import RecipesBase include("pipeline.jl") include("process_recipes.jl") +include("default_recipes.jl") end # module diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl new file mode 100644 index 000000000..eefd17bb9 --- /dev/null +++ b/RecipesPipeline/src/default_recipes.jl @@ -0,0 +1,64 @@ +# ensure we dispatch to the slicer +struct SliceIt end + +# the catch-all recipes +@recipe function f(::Type{SliceIt}, x, y, z) + + # handle data with formatting attached + if typeof(x) <: Formatted + xformatter := x.formatter + x = x.data + end + if typeof(y) <: Formatted + yformatter := y.formatter + y = y.data + end + if typeof(z) <: Formatted + zformatter := z.formatter + z = z.data + end + + xs = convertToAnyVector(x, plotattributes) + ys = convertToAnyVector(y, plotattributes) + zs = convertToAnyVector(z, plotattributes) + + + fr = pop!(plotattributes, :fillrange, nothing) + fillranges = process_fillrange(fr, plotattributes) + mf = length(fillranges) + + rib = pop!(plotattributes, :ribbon, nothing) + ribbons = process_ribbon(rib, plotattributes) + mr = length(ribbons) + + # @show zs + + mx = length(xs) + my = length(ys) + mz = length(zs) + if mx > 0 && my > 0 && mz > 0 + for i in 1:max(mx, my, mz) + # add a new series + di = copy(plotattributes) + xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)] + di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi) + + # handle fillrange + fr = fillranges[mod1(i,mf)] + di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr + + # handle ribbons + rib = ribbons[mod1(i,mr)] + di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib + + push!(series_list, RecipeData(di, ())) + end + end + nothing # don't add a series for the main block +end + +# this is the default "type recipe"... just pass the object through +@recipe f(::Type{T}, v::T) where {T<:Any} = v + +# this should catch unhandled "series recipes" and error with a nice message +@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") From 05155e684d4d9d8bc25c68a48d425ca5fc9a30d0 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 18:10:59 +0100 Subject: [PATCH 129/356] move the dependencies --- RecipesPipeline/src/default_recipes.jl | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index eefd17bb9..a89000cf7 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -62,3 +62,71 @@ end # this should catch unhandled "series recipes" and error with a nice message @recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") + +# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems]. +# Special handling for: no args, xmin/xmax, parametric, dataframes +# Then once inputs have been converted, build the series args, map functions, etc. +# This should cut down on boilerplate code and allow more focused dispatch on type +# note: returns meta information... mainly for use with automatic labeling from DataFrames for now + +const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} +const MaybeNumber = Union{Number, Missing} +const MaybeString = Union{AbstractString, Missing} +const DataPoint = Union{MaybeNumber, MaybeString} + +prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") +prepareSeriesData(::Nothing) = nothing +prepareSeriesData(t::Tuple{T, T}) where {T<:Number} = t +prepareSeriesData(f::Function) = f +prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!( + x -> ismissing(x) || isinf(x) ? NaN : x, + map(float,a)) +prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a) +prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf)) +prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image +prepareSeriesData(v::Volume) = Volume(prepareSeriesData(v.v), v.x_extents, v.y_extents, v.z_extents) + +# default: assume x represents a single series +convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)] + +# fixed number of blank series +convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n] + +# vector of data points is a single series +convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)] + +# list of things (maybe other vectors, functions, or something else) +function convertToAnyVector(v::AVec, plotattributes) + if all(x -> x isa MaybeNumber, v) + convertToAnyVector(Vector{MaybeNumber}(v), plotattributes) + elseif all(x -> x isa MaybeString, v) + convertToAnyVector(Vector{MaybeString}(v), plotattributes) + else + vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) + end +end + +# Matrix is split into columns +function convertToAnyVector(v::AMat{<:DataPoint}, plotattributes) + if all3D(plotattributes) + Any[prepareSeriesData(Surface(v))] + else + Any[prepareSeriesData(v[:, i]) for i in axes(v, 2)] + end +end + +# -------------------------------------------------------------------- +# Fillranges & ribbons + + +process_fillrange(range::Number, plotattributes) = [range] +process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes) + +process_ribbon(ribbon::Number, plotattributes) = [ribbon] +process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes) +# ribbon as a tuple: (lower_ribbons, upper_ribbons) +process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAnyVector(ribbon[1], plotattributes), + convertToAnyVector(ribbon[2], plotattributes))) + + +all3D(plotattributes) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) From 07c571e0614c817b7ec848d66f237b58780d2bf9 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:14:43 +0100 Subject: [PATCH 130/356] move Formatted --- RecipesPipeline/src/default_recipes.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index a89000cf7..2d37c56cb 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -1,6 +1,12 @@ # ensure we dispatch to the slicer struct SliceIt end +"Represents data values with formatting that should apply to the tick labels." +struct Formatted{T} + data::T + formatter::Function +end + # the catch-all recipes @recipe function f(::Type{SliceIt}, x, y, z) From 60e3985b1cc76549f6b16e9840e25d940121b167 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:20:58 +0100 Subject: [PATCH 131/356] move Surface and trueOrAllTrue --- RecipesPipeline/src/default_recipes.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index 2d37c56cb..5b05bb183 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -7,6 +7,22 @@ struct Formatted{T} formatter::Function end +abstract type AbstractSurface end + +"represents a contour or surface mesh" +struct Surface{M<:AMat} <: AbstractSurface + surf::M +end + +Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for yi in y, xi in x]) + +Base.Array(surf::Surface) = surf.surf + +for f in (:length, :size) + @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) +end +Base.copy(surf::Surface) = Surface(copy(surf.surf)) +Base.eltype(surf::Surface{T}) where {T} = eltype(T) # the catch-all recipes @recipe function f(::Type{SliceIt}, x, y, z) @@ -136,3 +152,6 @@ process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAn all3D(plotattributes) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) + +trueOrAllTrue(f::Function, x::AbstractArray) = all(f, x) +trueOrAllTrue(f::Function, x) = f(x) From fe7563c8afff02e0493ae11b6533470534117dde Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:27:56 +0100 Subject: [PATCH 132/356] define shorthands for abstract types --- RecipesPipeline/src/default_recipes.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index 5b05bb183..1593f9915 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -1,3 +1,7 @@ +# aliases +const AVec = AbstractVector +const AMat = AbstractMatrix + # ensure we dispatch to the slicer struct SliceIt end From e7ce8b03e91f9592f33376b5dbb5e64d43224e1d Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:35:18 +0100 Subject: [PATCH 133/356] Qualify recipes --- RecipesPipeline/src/default_recipes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index 1593f9915..e175d9f7e 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -28,7 +28,7 @@ end Base.copy(surf::Surface) = Surface(copy(surf.surf)) Base.eltype(surf::Surface{T}) where {T} = eltype(T) # the catch-all recipes -@recipe function f(::Type{SliceIt}, x, y, z) +RecipesBase.@recipe function f(::Type{SliceIt}, x, y, z) # handle data with formatting attached if typeof(x) <: Formatted @@ -84,10 +84,10 @@ Base.eltype(surf::Surface{T}) where {T} = eltype(T) end # this is the default "type recipe"... just pass the object through -@recipe f(::Type{T}, v::T) where {T<:Any} = v +RecipesBase.@recipe f(::Type{T}, v::T) where {T<:Any} = v # this should catch unhandled "series recipes" and error with a nice message -@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") +RecipesBase.@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") # create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems]. # Special handling for: no args, xmin/xmax, parametric, dataframes From 1614aed120855863b3921114999c1156c056a37b Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:48:31 +0100 Subject: [PATCH 134/356] add Volume --- RecipesPipeline/src/default_recipes.jl | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl index e175d9f7e..ea8808bc0 100644 --- a/RecipesPipeline/src/default_recipes.jl +++ b/RecipesPipeline/src/default_recipes.jl @@ -27,6 +27,31 @@ for f in (:length, :size) end Base.copy(surf::Surface) = Surface(copy(surf.surf)) Base.eltype(surf::Surface{T}) where {T} = eltype(T) +#--- +struct Volume{T} + v::Array{T,3} + x_extents::Tuple{T,T} + y_extents::Tuple{T,T} + z_extents::Tuple{T,T} +end + +default_extents(::Type{T}) where {T} = (zero(T), one(T)) + +function Volume(v::Array{T,3}, + x_extents = default_extents(T), + y_extents = default_extents(T), + z_extents = default_extents(T)) where T + Volume(v, x_extents, y_extents, z_extents) +end + +Base.Array(vol::Volume) = vol.v +for f in (:length, :size) + @eval Base.$f(vol::Volume, args...) = $f(vol.v, args...) +end +Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) +Base.eltype(vol::Volume{T}) where {T} = T + +# ----------------------------------------------------------------------- # the catch-all recipes RecipesBase.@recipe function f(::Type{SliceIt}, x, y, z) @@ -57,8 +82,6 @@ RecipesBase.@recipe function f(::Type{SliceIt}, x, y, z) ribbons = process_ribbon(rib, plotattributes) mr = length(ribbons) - # @show zs - mx = length(xs) my = length(ys) mz = length(zs) From c31455dfc39ee3b05e7a312ba00d9596da0befbd Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 25 Mar 2020 12:12:29 +0100 Subject: [PATCH 135/356] allow `return` in `@recipe` --- RecipesBase/.gitignore | 1 + RecipesBase/src/RecipesBase.jl | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RecipesBase/.gitignore b/RecipesBase/.gitignore index 3f02ca741..46a00d5d7 100644 --- a/RecipesBase/.gitignore +++ b/RecipesBase/.gitignore @@ -2,3 +2,4 @@ *.jl.*.cov *.jl.mem Manifest.toml +dev/ diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 2317f4fad..36c9c54b6 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -185,7 +185,9 @@ function process_recipe_body!(expr::Expr) set_expr end - # TODO elseif it's a @series macrocall, add a series block and push to the `series` list + 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 From c27213dbbe40ea7baa48f4ba765170e0f8e05cc6 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 28 Mar 2020 12:32:53 +0100 Subject: [PATCH 136/356] add documentation --- .../.github/workflows/Documentation.yml | 23 + RecipesBase/.gitignore | 2 + RecipesBase/README.md | 2 + RecipesBase/docs/Project.toml | 4 + RecipesBase/docs/make.jl | 21 + RecipesBase/docs/src/api.md | 3 + RecipesBase/docs/src/index.md | 15 + RecipesBase/docs/src/internals.md | 149 +++++++ RecipesBase/docs/src/syntax.md | 121 ++++++ RecipesBase/docs/src/types.md | 392 ++++++++++++++++++ 10 files changed, 732 insertions(+) create mode 100644 RecipesBase/.github/workflows/Documentation.yml create mode 100644 RecipesBase/docs/Project.toml create mode 100644 RecipesBase/docs/make.jl create mode 100644 RecipesBase/docs/src/api.md create mode 100644 RecipesBase/docs/src/index.md create mode 100644 RecipesBase/docs/src/internals.md create mode 100644 RecipesBase/docs/src/syntax.md create mode 100644 RecipesBase/docs/src/types.md diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml new file mode 100644 index 000000000..ba95d5bda --- /dev/null +++ b/RecipesBase/.github/workflows/Documentation.yml @@ -0,0 +1,23 @@ +name: Documentation + +on: + push: + branches: + - master + tags: '*' + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@latest + with: + version: 1.4 + - name: Install dependencies + run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + - name: Build and deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: julia --project=docs/ docs/make.jl diff --git a/RecipesBase/.gitignore b/RecipesBase/.gitignore index 3f02ca741..6c6fbf5b3 100644 --- a/RecipesBase/.gitignore +++ b/RecipesBase/.gitignore @@ -2,3 +2,5 @@ *.jl.*.cov *.jl.mem Manifest.toml +docs/build/ +dev/ diff --git a/RecipesBase/README.md b/RecipesBase/README.md index 5f8754095..aeedf1195 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -1,5 +1,7 @@ # RecipesBase +[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaPlots.github.io/RecipesBase.jl/stable) +[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaPlots.github.io/RecipesBase.jl/dev) [![Build Status](https://travis-ci.org/JuliaPlots/RecipesBase.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/RecipesBase.jl) ### Author: Thomas Breloff (@tbreloff) diff --git a/RecipesBase/docs/Project.toml b/RecipesBase/docs/Project.toml new file mode 100644 index 000000000..72f258639 --- /dev/null +++ b/RecipesBase/docs/Project.toml @@ -0,0 +1,4 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" diff --git a/RecipesBase/docs/make.jl b/RecipesBase/docs/make.jl new file mode 100644 index 000000000..4b1e35ab9 --- /dev/null +++ b/RecipesBase/docs/make.jl @@ -0,0 +1,21 @@ +using Documenter, RecipesBase, Plots + +makedocs( + sitename = "RecipesBase.jl", + format = Documenter.HTML( + prettyurls = get(ENV, "CI", nothing) == "true" + ), + pages = [ + "Home" => "index.md", + "Recipe Syntax" => "syntax.md", + "Recipe Types" => "types.md", + "Internals" => "internals.md", + "Library" => "api.md" + ], + modules = [RecipesBase] +) + +# deploydocs( +# repo = "github.com/JuliaPlots/RecipesBase.jl.git", +# push_preview = true, +# ) diff --git a/RecipesBase/docs/src/api.md b/RecipesBase/docs/src/api.md new file mode 100644 index 000000000..8d25af306 --- /dev/null +++ b/RecipesBase/docs/src/api.md @@ -0,0 +1,3 @@ +```@autodocs +Modules = [RecipesBase] +``` diff --git a/RecipesBase/docs/src/index.md b/RecipesBase/docs/src/index.md new file mode 100644 index 000000000..97f1320ac --- /dev/null +++ b/RecipesBase/docs/src/index.md @@ -0,0 +1,15 @@ +# RecipesBase.jl + +**Author: Thomas Breloff (@tbreloff)** + +RecipesBase is a lightweight Package without dependencies that allows to define custom visualizations with the [`@recipe`](@ref) macro. + +Package developers and users can define recipes to tell [Plots.jl](https://github.com/JuliaPlots/Plots.jl) how to plot custom types without depending on it. +Furthermore, recipes can be used for complex visualizations and new series types. +Plots, for example, uses recipes internally to define histograms or bar plots. +[StatsPlots.jl](https://github.com/JuliaPlots/StatsPlots.jl) and [GraphRecipes.jl](https://github.com/JuliaPlots/GraphRecipes.jl) extend Plots functionality for statistical plotting and visualization of graphs. + +RecipesBase exports the [`@recipe`](@ref) macro which provides a nice syntax for defining plot recipes. +Under the hood [`@recipe`](@ref) defines a new method for `RecipesBase.apply_recipe` which is called recursively in Plots at different stages of the argument processing pipeline. +This way other packages can communicate with Plots, i.e. define custom plotting recipes, only depending on RecipesBase. +Furthermore, the convenience macros [`@series`](@ref), [`@userplot`](@ref) and [`@shorthands`](@ref) are exported by RecipesBase. diff --git a/RecipesBase/docs/src/internals.md b/RecipesBase/docs/src/internals.md new file mode 100644 index 000000000..46c91a3c1 --- /dev/null +++ b/RecipesBase/docs/src/internals.md @@ -0,0 +1,149 @@ +## RecipesBase + +The [`@recipe`](@ref) macro defines a new method for `RecipesBase.apply_recipe`. +```julia +@recipe function f(args...; kwargs...) +``` +defines +```julia +RecipesBase.apply_recipe(plotattributes, args...; kwargs...) +``` +returning a `Vector{RecipeData}` where `RecipeData` holds the `plotattributes` Dict and the arguments returned in [`@recipe`](@ref) or in [`@series`](@ref). +``` +struct RecipeData + plotattributes::AbstractDict{Symbol,Any} + args::Tuple +end +``` +This function sets and overwrites entries in `plotattributes` and possibly adds new series. +- `attr --> val` translates to `haskey(plotattributes, :attr) || plotattributes[:attr] = val` +- `attr := val` sets `plotattributes[:attr] = val`. +- [`@series`](@ref) allows to add new series within [`@recipe`](@ref). It copies `plotattributes` from [`@recipe`](@ref), applies the replacements defined in its code block and returns corresponding new `RecipeData` object. + !!! info + [`@series`](@ref) have to be defined as a code block with `begin` and `end` statements. + ```julia + @series begin + ... + end + ``` + +So `RecipesBase.apply_recipe(plotattributes, args...; kwargs...)` returns a `Vector{RecipeData}`. +Plots can then recursively apply it again on the `plotattributes` and `args` of the elements of this vector, dispatching on a different signature. + + +## Plots + +The standard plotting commands +```julia +plot(args...; plotattributes...) +plot!(args...; plotattributes...) +``` +and shorthands like `scatter` or `bar` call the core internal plotting function `Plots._plot!`. +```julia +Plots._plot!(plt::Plot, plotattributes::AbstractDict{Symbol, Any}, args::Tuple) +``` + +In the following we will go through the major steps of the preprocessing pipeline implemented in `Plots._plot!`. + +#### Preprocess `plotattributes` +Before `Plots._plot!` is called and after each recipe is applied, `preprocessArgs!` preprocesses the `plotattributes` Dict. +It replaces aliases, expands magic arguments, and converts some attribute types. +- `lc = nothing` is replaced by `linecolor = RGBA(0, 0, 0, 0)`. +- `marker = (:red, :circle, 8)` expands to `markercolor = :red`, `markershape = :circle` and `markersize = 8`. + +#### Process User Recipes + +In the first step, `_process_userrecipe` is called. + +```julia +kw_list = _process_userrecipes(plt, plotattributes, args) +``` +It converts the user-provided `plotattributes` to a vector of `RecipeData`. +It recursively applies `RecipesBase.apply_recipe` on the fields of the first element of the `RecipeData` vector and prepends the resulting `RecipeData` vector to it. +If the `args` of an element are empty, it extracts `plotattributes` and adds it to a Vector of Dicts `kw_list`. +When all `RecipeData` elements are fully processed, `kw_list` is returned. + +#### Process Type Recipes + +After user recipes are processed, at some point in the recursion above args is of the form `(y, )`, `(x, y)` or `(x, y, z)`. +Plots defines recipes for these signatures. +The two argument version, for example, looks like this. + +```julia +@recipe function f(x, y) + did_replace = false + newx = _apply_type_recipe(plotattributes, x) + x === newx || (did_replace = true) + newy = _apply_type_recipe(plotattributes, y) + y === newy || (did_replace = true) + if did_replace + newx, newy + else + SliceIt, x, y, nothing + end +end +``` + +It recursively calls `_apply_type_recipe` on each argument until none of the arguments is replaced. +`_apply_type_recipe` applies the type recipe with the corresponding signature and for vectors it tries to apply the recipe element-wise. +When no argument is changed by `_apply_type_recipe`, the fallback `SliceIt` recipe is applied, which adds the data to `plotattributes` and returns `RecipeData` with empty args. + +#### Process Plot Recipes + +At this stage all arguments have been processed to something Plots supports. +In `_plot!` we have a `Vector{Dict}` `kw_list` with an entry for each series and already populated `:x`, `:y` and `:z` keys. +Now `_process_plotrecipe` is called until all plot recipes are processed. + +```julia +still_to_process = kw_list +kw_list = KW[] +while !isempty(still_to_process) + next_kw = popfirst!(still_to_process) + _process_plotrecipe(plt, next_kw, kw_list, still_to_process) +end +``` + +If no series type is set in the Dict, `_process_plotrecipe` pushes it to `kw_list` and returns. +Otherwise it tries to call `RecipesBase.apply_recipe` with the plot recipe signature. +If there is a method for this signature and the seriestype has changed by applying the recipe, the new `plotattributes` are appended to `still_to_process`. +If there is no method for the current plot recipe signature, we append the current Dict to `kw_list` and rely on series recipe processing. + +After all plot recipes have been applied, the plot and subplots are set-up. +```julia +_plot_setup(plt, plotattributes, kw_list) +_subplot_setup(plt, plotattributes, kw_list) +``` + +#### Process Series Recipes + +We are almost finished. +Now the series defaults are populated and `_process_seriesrecipe` is called for each series . + +```julia +for kw in kw_list + # merge defaults + series_attr = Attr(kw, _series_defaults) + _process_seriesrecipe(plt, series_attr) +end +``` + +If the series type is natively supported by the backend, we finalize processing and pass the series along to the backend. +Otherwise, the series recipe for the current series type is applied and `_process_seriesrecipe` is called again for the `plotattributes` in each returned `RecipeData` object. +Here we have to check again that the series type changed. +Due to this recursive processing, complex series types can be built up by simple blocks. +For example if we add an `@show st` in `_process_seriesrecipe` and plot a histogram, we go through the following series types: + +```julia +plot(histogram(randn(1000))) +``` +```julia +st = :histogram +st = :barhist +st = :barbins +st = :bar +st = :shape +``` +```@example +using Plots # hide +plot(histogram(randn(1000))) #hide +``` diff --git a/RecipesBase/docs/src/syntax.md b/RecipesBase/docs/src/syntax.md new file mode 100644 index 000000000..21c439534 --- /dev/null +++ b/RecipesBase/docs/src/syntax.md @@ -0,0 +1,121 @@ +```@setup syntax +using Plots, Random +Random.seed!(100) +default(legend = :topleft, markerstrokecolor = :auto, markersize = 6) +``` + +# Recipes Syntax + +The syntax in the [`@recipe`](@ref) macro is best explained using an example. +Suppose, we have a custom type storing the results of a simulation `x` and `y` and a measure `ε` for the maximum error in `y`. + +```@example syntax +struct Result + x::Vector{Float64} + y::Vector{Float64} + ε::Vector{Float64} +end +``` + +If we want to plot the `x` and `y` values of such a result with an error band given by `ε`, we could run something like +```@example syntax +res = Result(1:10, cumsum(rand(10)), cumsum(rand(10)) / 5) + +using Plots + +# plot the error band as invisible line with fillrange +plot( + res.x, + res.y .+ res.ε, + xlabel = "x", + ylabel = "y", + fill = (res.y .- res.ε, :lightgray, 0.5), + linecolor = nothing, + primary = false, # no legend entry +) + +# add the data to the plots +plot!(res.x, res.y, marker = :diamond) +``` + +Instead of typing this plot command over and over for different results we can define a **user recipe** to tell Plots what to do with input of the type `Result`. +Here is an example for such a user recipe with the additional feature to highlight datapoints with a maximal error above a certain threshold `ε_max`. + +```@example syntax +@recipe function f(r::Result; ε_max = 0.5) + # set a default value for an attribute with `-->` + xlabel --> "x" + yguide --> "y" + markershape --> :diamond + # add a series for an error band + @series begin + # force an argument with `:=` + seriestype := :path + # ignore series in legend and color cycling + primary := false + linecolor := nothing + fillcolor := :lightgray + fillalpha := 0.5 + fillrange := r.y .- r.ε + # ensure no markers are shown for the error band + markershape := :none + # return series data + r.x, r.y .+ r.ε + end + # get the seriescolor passed by the user + c = get(plotattributes, :seriescolor, :auto) + # highlight big errors, otherwise use the user-defined color + markercolor := ifelse.(r.ε .> ε_max, :red, c) + # return data + r.x, r.y +end +``` + +Let's walk through this recipe step by step. +First, the function signature in the recipe definition determines the recipe type, in this case a user recipe. +The function name `f` in is irrelevant and can be replaced by any other function name. +[`@recipe`](@ref) does not use it. +In the recipe body we can set default values for [Plots attributes](http://docs.juliaplots.org/latest/attributes/). +``` +attr --> val +``` +This will set `attr` to `val` unless it is specified otherwise by the user in the plot command. +``` +plot(args...; kw..., attr = otherval) +``` +Similarly we can force an attribute value with `:=`. +``` +attr := val +``` +This overwrites whatever the user passed to `plot` for `attr` and sets it to `val`. +!!! tip + It is strongly recommended to avoid using attribute aliases in recipes as this might lead to unexpected behavior in some cases. + In the recipe above `xlabel` is used as aliases for `xguide`. + When the recipe is used Plots will show a warning and hint to the default attribute name. + They can also be found in the attribute tables under http://docs.juliaplots.org/latest/attributes/. + +We use the [`@series`](@ref) macro to add a new series for the error band to the plot. +Within an [`@series`](@ref) block we can use the same syntax as above to force or set default values for attributes. + +In [`@recipe`](@ref) we have access to `plotattributes`. This is an `AbstractDict` storing the attributes that have been already processed at the current stage in the Plots pipeline. +For user recipes, which are called early in the pipeline, this mostly contains the keyword arguments provided by the user in the `plot` command. +In our example we want to highlight data points with an error above a certain threshold by changing the marker color. +For all other data points we set the marker color to whatever is the default or has been provided as keyword argument. +We can do this by getting the `seriescolor` from `plotattributes` and defaulting to `auto` if it has not been specified by the user. + +Finally, in both, [`@recipe`](@ref)s and [`@series`](@ref) blocks we return the data we wish to pass on to Plots (or the next recipe). + +!!! compat + With RecipesBase 1.0 the `return` statement is allowed in [`@recipe`](@ref) and [`@series`](@ref). + +With the recipe above we can now plot `Result`s with just + +```@example syntax +plot(res) +``` + +or + +```@example syntax +scatter(res, ε_max = 0.7, color = :green, marker = :star) +``` diff --git a/RecipesBase/docs/src/types.md b/RecipesBase/docs/src/types.md new file mode 100644 index 000000000..844c3fe26 --- /dev/null +++ b/RecipesBase/docs/src/types.md @@ -0,0 +1,392 @@ +```@setup types +using Plots, Random +Random.seed!(100) +default(legend = :topleft, markerstrokecolor = :auto, markersize = 6) +``` + +# Recipe Types + +## Overview + +There are four main types of recipes which are determined by the signature of the [`@recipe`](@ref) macro. + +### User Recipes + +```julia +@recipe function f(custom_arg_1::T, custom_arg_2::S, ...; ...) +``` + +!!! tip + [`@userplot`](@ref) provides a convenient way to create a custom type to dispatch on and defines custom plotting functions. + ```julia + @userplot MyPlot + @recipe function f(mp::MyPlot; ...) + ... + end + ``` + Now we can plot with: + ```julia + myplot(args...; kw...) + myplot!(args...; kw...) + ``` + +### Type Recipes + +```julia +@recipe function f(::Type{T}, val::T) where T +``` + +!!! compat + With RecipesBase 1.0 type recipes are aware of the current axis (`:x`, `:y`, `:z`). + ```julia + @recipe function f(::Type{MyType}, val::MyType) + guide --> "My Guide" + ... + end + ``` + This only sets the guide for the axes with `MyType`. + For more complex type recipes the current axis letter can be accessed in [`@recipe`](@ref) with `plotattributes[:letter]`. + +!!! compat + With RecipesBase 1.0 type recipes of the form + ```julia + @recipe function f(::Type{T}, val::T) where T <: AbstractArry{MyType} + ``` + for `AbstractArray`s of custom types are supported too. + +!!! info + User recipes and type recipes must return either + - an `AbstractArray{<:V}` where `V` is a *valid type*, + - two functions, or + - nothing + + A *valid type* is either a Plots *datapoint* or a type that can be handled by another user recipe or type recipe. + Plots *datapoints* are all subtypes of `Union{AbstractString, Missing}` and `Union{Number, Missing}`. + + If two functions are returned the former should tell Plots how to convert from `T` to a *datapoint* and the latter how to convert from *datapoint* to string for tick label formatting. + +### Plot Recipes + +```julia +@recipe function f(::Type{Val{:myplotrecipename}}, plt::AbstractPlot; ...) +``` + +### Series Recipes + +```julia +@recipe function f(::Type{Val{:myseriesrecipename}}, x, y, z; ...) +``` + +!!! tip + The [`@shorthands`](@ref) macro provides a convenient way to define plotting functions for custom plot recipes or series recipes. + ```julia + @shorthands myseriestype + @recipe function f(::Type{Val{:myseriestype}}, x, y, z; ...) + ... + end + ``` + This allows to plot with: + ```julia + myseriestype(args...; kw...) + myseriestype!(args...; kw...) + ``` + +!!! warning + Plot recipes and series recipes have to set the `seriestype` attribute. + +## User Recipes +User recipes are called early in the processing pipeline and allow designing custom visualizations. +```julia +@recipe function f(custom_arg_1::T, custom_arg_2::S, ...; ...) +``` + +We have already seen an example for a user recipe in the syntax section above. +User recipes can also be used to define a custom visualization without necessarily wishing to plot a custom type. +For this purpose we can create a type to dispatch on. +The [`@userplot`](@ref) macro is a convenient way to do this. +``` +@userplot MyPlot +``` +expands to +``` +mutable struct MyPlot + args +end +export myplot, myplot! +myplot(args...; kw...) = plot(MyPlot(args); kw...) +myplot!(args...; kw...) = plot!(MyPlot(args); kw...) +``` +We can use this to define a user recipe for a pie plot. +```@example types +# defines mutable struct `UserPie` and sets shorthands `userpie` and `userpie!` +@userplot UserPie +@recipe function f(up::UserPie) + y = up.args[end] # extract y from the args + # if we are passed two args, we use the first as labels + labels = length(up.args) == 2 ? up.args[1] : eachindex(y) + framestyle --> :none + aspect_ratio --> true + s = sum(y) + θ = 0 + # add a shape for each piece of pie + for i in 1:length(y) + # determine the angle until we stop + θ_new = θ + 2π * y[i] / s + # calculate the coordinates + coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] + @series begin + seriestype := :shape + label --> string(labels[i]) + coords + end + θ = θ_new + end + # we already added all shapes in @series so we don't want to return a series + # here. (Technically we are returning an empty series which is not added to + # the legend.) + primary := false + () +end +``` + +Now we can just use the recipe like this: + +```@example types +userpie('A':'D', rand(4)) +``` + +## Type Recipes +Type recipes define one-to-one mappings from custom types to something Plots supports +```julia +@recipe function f(::Type{T}, val::T) where T +``` + +Suppose we have a custom wrapper for vectors. + +```@example types +struct MyWrapper + v::Vector +end +``` +We can tell Plots to just use the wrapped vector for plotting in a type recipe. +```@example types +@recipe f(::Type{MyWrapper}, mw::MyWrapper) = mw.v +``` +Now Plots knows what to do when it sees a `MyWrapper`. +```@example types +mw = MyWrapper(cumsum(rand(10))) +plot(mw) +``` +Due to the recursive application of type recipes they even compose automatically. +```@example types +struct MyOtherWrapper + w +end + +@recipe f(::Type{MyOtherWrapper}, mow::MyOtherWrapper) = mow.w + +mow = MyOtherWrapper(mw) +plot(mow) +``` +If we want an element-wise conversion of custom types we can define a conversion function to a type that Plots supports (`Real`, `AbstractString`) and a formatter for the tick labels. +Consider the following simple time type. +```@example types +struct MyTime + h::Int + m::Int +end + +# show e.g. `MyTime(1, 30)` as "01:30" +time_string(mt) = join((lpad(string(c), 2, "0") for c in (mt.h, mt.m)), ":") +# map a `MyTime` object to the number of minutes that have passed since midnight. +# this is the actual data Plots will use. +minutes_since_midnight(mt) = 60 * mt.h + mt.m +# convert the minutes passed since midnight to a nice string showing `MyTime` +formatter(n) = time_string(MyTime(divrem(n, 60)...)) + +# define the recipe (it must return two functions) +@recipe f(::Type{MyTime}, mt::MyTime) = (minutes_since_midnight, formatter) +``` +Now we can plot vectors of `MyTime` automatically with the correct tick labelling. +`DateTime`s and `Char`s are implemented with such a type recipe in Plots for example. + +```@example types +times = MyTime.(0:23, rand(0:59, 24)) +vals = log.(1:24) + +plot(times, vals) +``` +Again everything composes nicely. +```@example types +plot(MyWrapper(vals), MyOtherWrapper(times)) +``` + +## Plot Recipes +Plot recipes are called after all input data is processed by type recipes but before the plot and subplots are set-up. They allow to build series with custom layouts and set plot-wide attributes. +```julia +@recipe function f(::Type{Val{:myplotrecipename}}, plt::AbstractPlot; ...) +``` + +Plot recipes define a new series type. +They are applied after type recipes. +Hence, standard Plots types can be assumed for input data `:x`, `:y` and `:z` in `plotattributes`. +Plot recipes can access plot and subplot attributes before they are processed, for example to build layouts. +Both, plot recipes and series recipes must change the series type. +Otherwise we get a warning that we would run into a StackOverflow error. + +We can define a seriestype `:yscaleplot`, that automatically shows data with a linear y scale in one subplot and with a logarithmic yscale in another one. +```@example types +@recipe function f(::Type{Val{:yscaleplot}}, plt::AbstractPlot) + x, y = plotattributes[:x], plotattributes[:y] + layout := (1, 2) + for (i, scale) in enumerate((:linear, :log)) + @series begin + title --> string(scale, " scale") + seriestype := :path + subplot := i + yscale := scale + end + end +end +``` +We can call it with `plot(...; ..., seriestype = :yscaleplot)` or we can define a shorthand with the [`@shorthands`](@ref) macro. +``` +@shorthands myseries +``` +expands to +``` +export myseries, myseries! +myseries(args...; kw...) = plot(args...; kw..., seriestype = :myseries) +myseries!(args...; kw...) = plot!(args...; kw..., seriestype = :myseries) +``` +So let's try the `yscaleplot` plot recipe. +```@example types +@shorthands yscaleplot + +yscaleplot((1:10).^2) +``` +Magically the composition with type recipes works again. +```@example types +yscaleplot(MyWrapper(times), MyOtherWrapper((1:24).^2)) +``` +## Series Recipes +Series recipes are applied recursively until the current backend supports a series type. They are used for example to convert the input data of a bar plot to the coordinates of the shapes that define the bars. +```julia +@recipe function f(::Type{Val{:myseriesrecipename}}, x, y, z; ...) +``` + +If we want to call the `userpie` recipe with a custom type we run into errors. +```julia +userpie(MyWrapper(rand(4))) +``` +```julia +ERROR: MethodError: no method matching keys(::MyWrapper) +Stacktrace: + [1] eachindex(::MyWrapper) at ./abstractarray.jl:209 +``` +Furthermore, if we want to show multiple pie charts in different subplots, we don't get what we expect either +```@example types +userpie(rand(4, 2), layout = 2) +``` +We could overcome these issues by implementing the required `AbstractArray` methods for `MyWrapper` (instead of the type recipe) and by more carefully dealing with different series in the `userpie` recipe. +However, the simpler approach is writing the pie recipe as a series recipe and relying on Plots' processing pipeline. +```@example types +@recipe function f(::Type{Val{:seriespie}}, x, y, z) + framestyle --> :none + aspect_ratio --> true + s = sum(y) + θ = 0 + for i in eachindex(y) + θ_new = θ + 2π * y[i] / s + coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] + @series begin + seriestype := :shape + label --> string(x[i]) + x := first.(coords) + y := last.(coords) + end + θ = θ_new + end +end +@shorthands seriespie +``` +Here we use the already processed values `x` and `y` to calculate the shape coordinates for each pie piece, update `x` and `y` with these coordinates and set the series type to `:shape`. +```@example types +seriespie(rand(4)) +``` +This automatically works together with type recipes ... +```@example types +seriespie(MyWrapper(rand(4))) +``` +... or with layouts +```@example types +seriespie(rand(4, 2), layout = 2) +``` + +## Remarks + +Plot recipes and series recipes are actually very similar. +In fact, a pie recipe could be also implemented as a plot recipe by acessing the data through `plotattributes`. + +```@example types +@recipe function f(::Type{Val{:plotpie}}, plt::AbstractPlot) + y = plotattributes[:y] + labels = plotattributes[:x] + framestyle --> :none + aspect_ratio --> true + s = sum(y) + θ = 0 + for i in 1:length(y) + θ_new = θ + 2π * y[i] / s + coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] + @series begin + seriestype := :shape + label --> string(labels[i]) + x := first.(coords) + y := last.(coords) + end + θ = θ_new + end +end +@shorthands plotpie + +plotpie(rand(4, 2), layout = (1, 2)) +``` +The series recipe syntax is just a little nicer in this case. + +!!! info + Here's subtle difference between these recipe types: + Plot recipes are applied in any case while series are only applied if the backend does not support the series type natively. + +Let's try it the other way around and implement our `yscaleplot` recipe as a series recipe. + +```@example types +@recipe function f(::Type{Val{:yscaleseries}}, x, y, z) + layout := (1, 2) + for (i, scale) in enumerate((:linear, :log)) + @series begin + title --> string(scale, " scale") + seriestype := :path + subplot := i + yscale := scale + end + end +end +@shorthands yscaleseries +``` +That looks a little nicer than the plot recipe version as well. +Let's try to plot. +```julia +yscaleseries((1:10).^2) +``` +```julia +MethodError: Cannot `convert` an object of type Int64 to an object of type Plots.Subplot{Plots.GRBackend} +Closest candidates are: + convert(::Type{T}, !Matched::T) where T at essentials.jl:168 + Plots.Subplot{Plots.GRBackend}(::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any) where T<:RecipesBase.AbstractBackend at /home/daniel/.julia/packages/Plots/rNwM4/src/types.jl:88 +``` + +That is because the plot and subplots have already been built before the series recipe is applied. + +!!! tip + For everything that modifies plot-wide attributes plot recipes have to be used, otherwise series recipes are recommended. From e09ea6783a464bc9a1e1980c950da5647256c737 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 28 Mar 2020 13:25:39 +0100 Subject: [PATCH 137/356] try xvfb-run for docs --- RecipesBase/.github/workflows/Documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml index ba95d5bda..6243dbde4 100644 --- a/RecipesBase/.github/workflows/Documentation.yml +++ b/RecipesBase/.github/workflows/Documentation.yml @@ -20,4 +20,4 @@ jobs: - name: Build and deploy env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: julia --project=docs/ docs/make.jl + run: xvfb-run julia --project=docs/ docs/make.jl From 25fced806125b44eaf999156285ab7c2fdf5462d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 29 Mar 2020 00:00:20 +0100 Subject: [PATCH 138/356] docs on travis --- .../.github/workflows/Documentation.yml | 23 ------------------- RecipesBase/.travis.yml | 14 ++++++++++- 2 files changed, 13 insertions(+), 24 deletions(-) delete mode 100644 RecipesBase/.github/workflows/Documentation.yml diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml deleted file mode 100644 index 6243dbde4..000000000 --- a/RecipesBase/.github/workflows/Documentation.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Documentation - -on: - push: - branches: - - master - tags: '*' - pull_request: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@latest - with: - version: 1.4 - - name: Install dependencies - run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - name: Build and deploy - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: xvfb-run julia --project=docs/ docs/make.jl diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index 3b5f71c6f..385a8c543 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -4,7 +4,8 @@ os: - linux - osx julia: - - 1.1 + - 1.0 + - 1.4 - nightly notifications: email: false @@ -12,3 +13,14 @@ notifications: # script: # - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi # - julia -e 'import Pkg; Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' + +jobs: + include: + - stage: "Documentation" + julia: 1.4 + os: linux + script: + - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); + Pkg.instantiate()' + - xvfb-run julia --project=docs/ docs/make.jl + after_success: skip From 0ec7fddbaa8478785716b876e8a31520b52510e8 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 29 Mar 2020 00:14:37 +0100 Subject: [PATCH 139/356] add qt5 in travis --- RecipesBase/.travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml index 385a8c543..457839ec2 100644 --- a/RecipesBase/.travis.yml +++ b/RecipesBase/.travis.yml @@ -19,6 +19,10 @@ jobs: - stage: "Documentation" julia: 1.4 os: linux + addons: + apt: + packages: + - qt5-default script: - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' From 003e3895f2f8bd595840e8b4cf9c209e45d95c74 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 29 Mar 2020 16:08:44 +0200 Subject: [PATCH 140/356] actually deploy docs --- RecipesBase/docs/make.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecipesBase/docs/make.jl b/RecipesBase/docs/make.jl index 4b1e35ab9..5300b2154 100644 --- a/RecipesBase/docs/make.jl +++ b/RecipesBase/docs/make.jl @@ -15,7 +15,7 @@ makedocs( modules = [RecipesBase] ) -# deploydocs( -# repo = "github.com/JuliaPlots/RecipesBase.jl.git", -# push_preview = true, -# ) +deploydocs( + repo = "github.com/JuliaPlots/RecipesBase.jl.git", + push_preview = true, +) From 08eb4c98c324008eb924b8053416b95d2db6ccb4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 Apr 2020 11:45:18 +0200 Subject: [PATCH 141/356] rewrite from https://github.com/JuliaPlots/Plots.jl/pull/2530 --- RecipesPipeline/Project.toml | 3 + RecipesPipeline/src/RecipePipeline.jl | 97 +++++++- RecipesPipeline/src/api.jl | 142 +++++++++++ RecipesPipeline/src/default_recipes.jl | 184 -------------- RecipesPipeline/src/group.jl | 122 +++++++++ RecipesPipeline/src/pipeline.jl | 56 ----- RecipesPipeline/src/plot_recipe.jl | 46 ++++ RecipesPipeline/src/process_recipes.jl | 136 ---------- RecipesPipeline/src/series.jl | 170 +++++++++++++ RecipesPipeline/src/series_recipe.jl | 62 +++++ RecipesPipeline/src/type_recipe.jl | 94 +++++++ RecipesPipeline/src/user_recipe.jl | 330 +++++++++++++++++++++++++ RecipesPipeline/src/utils.jl | 220 +++++++++++++++++ 13 files changed, 1282 insertions(+), 380 deletions(-) create mode 100644 RecipesPipeline/src/api.jl delete mode 100644 RecipesPipeline/src/default_recipes.jl create mode 100644 RecipesPipeline/src/group.jl delete mode 100644 RecipesPipeline/src/pipeline.jl create mode 100644 RecipesPipeline/src/plot_recipe.jl delete mode 100644 RecipesPipeline/src/process_recipes.jl create mode 100644 RecipesPipeline/src/series.jl create mode 100644 RecipesPipeline/src/series_recipe.jl create mode 100644 RecipesPipeline/src/type_recipe.jl create mode 100644 RecipesPipeline/src/user_recipe.jl create mode 100644 RecipesPipeline/src/utils.jl diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 918c2877a..1f5f6f63d 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -4,10 +4,13 @@ authors = ["Michael Krabbe Borregaard "] version = "0.1.0" [deps] +PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] julia = "1" +PlotUtils = "0.6.5" +RecipesBase = "0.8" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/RecipesPipeline/src/RecipePipeline.jl b/RecipesPipeline/src/RecipePipeline.jl index 376507e01..03cc24e60 100644 --- a/RecipesPipeline/src/RecipePipeline.jl +++ b/RecipesPipeline/src/RecipePipeline.jl @@ -1,8 +1,97 @@ module RecipePipeline import RecipesBase -include("pipeline.jl") -include("process_recipes.jl") -include("default_recipes.jl") +import RecipesBase: @recipe, @series, RecipeData, is_explicit +import PlotUtils # tryrange and adapted_grid -end # module +export recipe_pipeline! +# Plots relies on these: +export SliceIt, + DefaultsDict, + Formatted, + AbstractSurface, + Surface, + Volume, + is3d, + is_surface, + needs_3d_axes, + group_as_matrix, + reset_kw!, + pop_kw!, + scale_func, + inverse_scale_func, + unzip +# API +export warn_on_recipe_aliases, + splittable_attribute, + split_attribute, + process_userrecipe!, + get_axis_limits, + is_axis_attribute, + type_alias, + plot_setup!, + slice_series_attributes! + +include("api.jl") +include("utils.jl") +include("series.jl") +include("group.jl") +include("user_recipe.jl") +include("type_recipe.jl") +include("plot_recipe.jl") +include("series_recipe.jl") + + +""" + recipe_pipeline!(plt, plotattributes, args) + +Recursively apply user recipes, type recipes, plot recipes and series recipes to build a +list of `Dict`s, each corresponding to a series. At the beginning `plotattributes` +contains only the keyword arguments passed in by the user. Add all series to the plot +bject `plt` and return it. +""" +function recipe_pipeline!(plt, plotattributes, args) + plotattributes[:plot_object] = plt + + # -------------------------------- + # "USER RECIPES" + # -------------------------------- + + # process user and type recipes + kw_list = _process_userrecipes!(plt, plotattributes, args) + + # -------------------------------- + # "PLOT RECIPES" + # -------------------------------- + + # The "Plot recipe" acts like a series type, and is processed before the plot layout + # is created, which allows for setting layouts and other plot-wide attributes. + # We get inputs which have been fully processed by "user recipes" and "type recipes", + # so we can expect standard vectors, surfaces, etc. No defaults have been set yet. + + kw_list = _process_plotrecipes!(plt, kw_list) + + # -------------------------------- + # Plot/Subplot/Layout setup + # -------------------------------- + + plot_setup!(plt, plotattributes, kw_list) + + # At this point, `kw_list` is fully decomposed into individual series... one KW per + # series. The next step is to recursively apply series recipes until the backend + # supports that series type. + + # -------------------------------- + # "SERIES RECIPES" + # -------------------------------- + + _process_seriesrecipes!(plt, kw_list) + + # -------------------------------- + # Return processed plot object + # -------------------------------- + + return plt +end + +end diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl new file mode 100644 index 000000000..feb9350ae --- /dev/null +++ b/RecipesPipeline/src/api.jl @@ -0,0 +1,142 @@ +## Warnings + +""" + warn_on_recipe_aliases!(plt, plotattributes, recipe_type, args...) + +Warn if an alias is dedected in `plotattributes` after a recipe of type `recipe_type` is +applied to 'args'. `recipe_type` is either `:user`, `:type`, `:plot` or `:series`. +""" +function warn_on_recipe_aliases!(plt, plotattributes, recipe_type, args...) end + + +## Grouping + +""" + splittable_attribute(plt, key, val, len) + +Returns `true` if the attribute `key` with the value `val` can be split into groups with +group provided as a vector of length `len`, `false` otherwise. +""" +splittable_attribute(plt, key, val, len) = false +splittable_attribute(plt, key, val::AbstractArray, len) = + !(key in (:group, :color_palette)) && length(axes(val, 1)) == len +splittable_attribute(plt, key, val::Tuple, n) = all(splittable_attribute.(key, val, len)) + + +""" + split_attribute(plt, key, val, indices) + +Select the proper indices from `val` for attribute `key`. +""" +split_attribute(plt, key, val::AbstractArray, indices) = + val[indices, fill(Colon(), ndims(val) - 1)...] +split_attribute(plt, key, val::Tuple, indices) = + Tuple(split_attribute(key, v, indices) for v in val) + + +## Preprocessing attributes + +""" + preprocess_attributes!(plt, plotattributes) + +Any plotting package specific preprocessing of user or recipe input happens here. +For example, Plots replaces aliases and expands magic arguments. +""" +function preprocess_attributes!(plt, plotattributes) end + +# TODO: should the Plots version be defined as fallback in RecipePipeline? +""" + is_subplot_attribute(plt, attr) + +Returns `true` if `attr` is a subplot attribute, otherwise `false`. +""" +is_subplot_attribute(plt, attr) = false + +# TODO: should the Plots version be defined as fallback in RecipePipeline? +""" + is_axis_attribute(plt, attr) + +Returns `true` if `attr` is an axis attribute, i.e. it applies to `xattr`, `yattr` and +`zattr`, otherwise `false`. +""" +is_axis_attribute(plt, attr) = false + + +## User recipes + +""" + process_userrecipe!(plt, attributes_list, attributes) + +Do plotting package specific post-processing and add series attributes to attributes_list. +For example, Plots increases the number of series in `plt`, sets `:series_plotindex` in +attributes and possible adds new series attributes for errorbars or smooth. +""" +function process_userrecipe!(plt, attributes_list, attributes) + push!(attributes_list, attributes) +end + +""" + get_axis_limits(plt, letter) + +Get the limits for the axis specified by `letter` (`:x`, `:y` or `:z`) in `plt`. If it +errors, `tryrange` from PlotUtils is used. +""" +get_axis_limits(plt, letter) = ErrorException("Axis limits not defined.") + + +## Plot recipes + +""" + type_alias(plt, st) + +Return the seriestype alias for `st`. +""" +type_alias(plt, st) = st + + +## Plot setup + +""" + plot_setup!(plt, plotattributes, kw_list) + +Setup plot, subplots and layouts. +For example, Plots creates the backend figure, initializes subplots, expands extrema and +links subplot axes. +""" +function plot_setup!(plt, plotattributes, kw_list) end + + +## Series recipes + +""" + slice_series_attributes!(plt, kw_list, kw) + +For attributes given as vector with one element per series, only select the value for +current series. +""" +function slice_series_attributes!(plt, kw_list, kw) end + + +""" + series_defaults(plt) + +Returns a `Dict` storing the defaults for series attributes. +""" +series_defaults(plt) = Dict{Symbol, Any}() + +# TODO: Add a more sensible fallback including e.g. path, scatter, ... +""" + is_seriestype_supported(plt, st) + +Check if the plotting package natively supports the seriestype `st`. +""" +is_seriestype_supported(plt, st) = false + +""" + add_series!(plt, kw) + +Adds the series defined by `kw` to the plot object. +For example Plots updates the current subplot arguments, expands extrema and pushes the +the series to the series_list of `plt`. +""" +function add_series!(plt, kw) end diff --git a/RecipesPipeline/src/default_recipes.jl b/RecipesPipeline/src/default_recipes.jl deleted file mode 100644 index ea8808bc0..000000000 --- a/RecipesPipeline/src/default_recipes.jl +++ /dev/null @@ -1,184 +0,0 @@ -# aliases -const AVec = AbstractVector -const AMat = AbstractMatrix - -# ensure we dispatch to the slicer -struct SliceIt end - -"Represents data values with formatting that should apply to the tick labels." -struct Formatted{T} - data::T - formatter::Function -end - -abstract type AbstractSurface end - -"represents a contour or surface mesh" -struct Surface{M<:AMat} <: AbstractSurface - surf::M -end - -Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for yi in y, xi in x]) - -Base.Array(surf::Surface) = surf.surf - -for f in (:length, :size) - @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) -end -Base.copy(surf::Surface) = Surface(copy(surf.surf)) -Base.eltype(surf::Surface{T}) where {T} = eltype(T) -#--- -struct Volume{T} - v::Array{T,3} - x_extents::Tuple{T,T} - y_extents::Tuple{T,T} - z_extents::Tuple{T,T} -end - -default_extents(::Type{T}) where {T} = (zero(T), one(T)) - -function Volume(v::Array{T,3}, - x_extents = default_extents(T), - y_extents = default_extents(T), - z_extents = default_extents(T)) where T - Volume(v, x_extents, y_extents, z_extents) -end - -Base.Array(vol::Volume) = vol.v -for f in (:length, :size) - @eval Base.$f(vol::Volume, args...) = $f(vol.v, args...) -end -Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) -Base.eltype(vol::Volume{T}) where {T} = T - -# ----------------------------------------------------------------------- -# the catch-all recipes -RecipesBase.@recipe function f(::Type{SliceIt}, x, y, z) - - # handle data with formatting attached - if typeof(x) <: Formatted - xformatter := x.formatter - x = x.data - end - if typeof(y) <: Formatted - yformatter := y.formatter - y = y.data - end - if typeof(z) <: Formatted - zformatter := z.formatter - z = z.data - end - - xs = convertToAnyVector(x, plotattributes) - ys = convertToAnyVector(y, plotattributes) - zs = convertToAnyVector(z, plotattributes) - - - fr = pop!(plotattributes, :fillrange, nothing) - fillranges = process_fillrange(fr, plotattributes) - mf = length(fillranges) - - rib = pop!(plotattributes, :ribbon, nothing) - ribbons = process_ribbon(rib, plotattributes) - mr = length(ribbons) - - mx = length(xs) - my = length(ys) - mz = length(zs) - if mx > 0 && my > 0 && mz > 0 - for i in 1:max(mx, my, mz) - # add a new series - di = copy(plotattributes) - xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)] - di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi) - - # handle fillrange - fr = fillranges[mod1(i,mf)] - di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr - - # handle ribbons - rib = ribbons[mod1(i,mr)] - di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib - - push!(series_list, RecipeData(di, ())) - end - end - nothing # don't add a series for the main block -end - -# this is the default "type recipe"... just pass the object through -RecipesBase.@recipe f(::Type{T}, v::T) where {T<:Any} = v - -# this should catch unhandled "series recipes" and error with a nice message -RecipesBase.@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") - -# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems]. -# Special handling for: no args, xmin/xmax, parametric, dataframes -# Then once inputs have been converted, build the series args, map functions, etc. -# This should cut down on boilerplate code and allow more focused dispatch on type -# note: returns meta information... mainly for use with automatic labeling from DataFrames for now - -const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} -const MaybeNumber = Union{Number, Missing} -const MaybeString = Union{AbstractString, Missing} -const DataPoint = Union{MaybeNumber, MaybeString} - -prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") -prepareSeriesData(::Nothing) = nothing -prepareSeriesData(t::Tuple{T, T}) where {T<:Number} = t -prepareSeriesData(f::Function) = f -prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!( - x -> ismissing(x) || isinf(x) ? NaN : x, - map(float,a)) -prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a) -prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf)) -prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image -prepareSeriesData(v::Volume) = Volume(prepareSeriesData(v.v), v.x_extents, v.y_extents, v.z_extents) - -# default: assume x represents a single series -convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)] - -# fixed number of blank series -convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n] - -# vector of data points is a single series -convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)] - -# list of things (maybe other vectors, functions, or something else) -function convertToAnyVector(v::AVec, plotattributes) - if all(x -> x isa MaybeNumber, v) - convertToAnyVector(Vector{MaybeNumber}(v), plotattributes) - elseif all(x -> x isa MaybeString, v) - convertToAnyVector(Vector{MaybeString}(v), plotattributes) - else - vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) - end -end - -# Matrix is split into columns -function convertToAnyVector(v::AMat{<:DataPoint}, plotattributes) - if all3D(plotattributes) - Any[prepareSeriesData(Surface(v))] - else - Any[prepareSeriesData(v[:, i]) for i in axes(v, 2)] - end -end - -# -------------------------------------------------------------------- -# Fillranges & ribbons - - -process_fillrange(range::Number, plotattributes) = [range] -process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes) - -process_ribbon(ribbon::Number, plotattributes) = [ribbon] -process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes) -# ribbon as a tuple: (lower_ribbons, upper_ribbons) -process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAnyVector(ribbon[1], plotattributes), - convertToAnyVector(ribbon[2], plotattributes))) - - -all3D(plotattributes) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) - -trueOrAllTrue(f::Function, x::AbstractArray) = all(f, x) -trueOrAllTrue(f::Function, x) = f(x) diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl new file mode 100644 index 000000000..ca9d46c5c --- /dev/null +++ b/RecipesPipeline/src/group.jl @@ -0,0 +1,122 @@ +"A special type that will break up incoming data into groups, and allow for easier creation of grouped plots" +mutable struct GroupBy + group_labels::Vector # length == numGroups + group_indices::Vector{Vector{Int}} # list of indices for each group +end + +# this is when given a vector-type of values to group by +function _extract_group_attributes(v::AVec, args...; legend_entry = string) + group_labels = sort(collect(unique(v))) + n = length(group_labels) + if n > 100 + @warn("You created n=$n groups... Is that intended?") + end + group_indices = Vector{Int}[filter(i -> v[i] == glab, eachindex(v)) for glab in group_labels] + GroupBy(map(legend_entry, group_labels), group_indices) +end + +legend_entry_from_tuple(ns::Tuple) = join(ns, ' ') + +# this is when given a tuple of vectors of values to group by +function _extract_group_attributes(vs::Tuple, args...) + isempty(vs) && return GroupBy([""], [axes(args[1],1)]) + v = map(tuple, vs...) + _extract_group_attributes(v, args...; legend_entry = legend_entry_from_tuple) +end + +# allow passing NamedTuples for a named legend entry +legend_entry_from_tuple(ns::NamedTuple) = + join(["$k = $v" for (k, v) in pairs(ns)], ", ") + +function _extract_group_attributes(vs::NamedTuple, args...) + isempty(vs) && return GroupBy([""], [axes(args[1],1)]) + v = map(NamedTuple{keys(vs)}∘tuple, values(vs)...) + _extract_group_attributes(v, args...; legend_entry = legend_entry_from_tuple) +end + +# expecting a mapping of "group label" to "group indices" +function _extract_group_attributes(idxmap::Dict{T,V}, args...) where {T, V<:AVec{Int}} + group_labels = sortedkeys(idxmap) + group_indices = Vector{Int}[collect(idxmap[k]) for k in group_labels] + GroupBy(group_labels, group_indices) +end + +filter_data(v::AVec, idxfilter::AVec{Int}) = v[idxfilter] +filter_data(v, idxfilter) = v + +function filter_data!(plotattributes::AKW, idxfilter) + for s in (:x, :y, :z) + plotattributes[s] = filter_data(get(plotattributes, s, nothing), idxfilter) + end +end + +function _filter_input_data!(plotattributes::AKW) + idxfilter = pop!(plotattributes, :idxfilter, nothing) + if idxfilter !== nothing + filter_data!(plotattributes, idxfilter) + end +end + +function groupedvec2mat(x_ind, x, y::AbstractArray, groupby, def_val = y[1]) + y_mat = Array{promote_type(eltype(y), typeof(def_val))}( + undef, + length(keys(x_ind)), + length(groupby.group_labels), + ) + fill!(y_mat, def_val) + for i in eachindex(groupby.group_labels) + xi = x[groupby.group_indices[i]] + yi = y[groupby.group_indices[i]] + y_mat[getindex.(Ref(x_ind), xi), i] = yi + end + return y_mat +end + +groupedvec2mat(x_ind, x, y::Tuple, groupby) = + Tuple(groupedvec2mat(x_ind, x, v, groupby) for v in y) + +group_as_matrix(t) = false + +# split the group into 1 series per group, and set the label and idxfilter for each +@recipe function f(groupby::GroupBy, args...) + plt = plotattributes[:plot_object] + group_length = maximum(union(groupby.group_indices...)) + if !(group_as_matrix(args[1])) + for (i, glab) in enumerate(groupby.group_labels) + @series begin + label --> string(glab) + idxfilter --> groupby.group_indices[i] + for (key, val) in plotattributes + if splittable_attribute(plt, key, val, group_length) + :($key) := split_attribute(plt, key, val, groupby.group_indices[i]) + end + end + args + end + end + else + g = args[1] + if length(g.args) == 1 + x = zeros(Int, group_length) + for indexes in groupby.group_indices + x[indexes] = eachindex(indexes) + end + last_args = g.args + else + x = g.args[1] + last_args = g.args[2:end] + end + x_u = unique(sort(x)) + x_ind = Dict(zip(x_u, eachindex(x_u))) + for (key, val) in plotattributes + if splittable_kw(key, val, group_length) + :($key) := groupedvec2mat(x_ind, x, val, groupby) + end + end + label --> reshape(groupby.group_labels, 1, :) + typeof(g)(( + x_u, + (groupedvec2mat(x_ind, x, arg, groupby, NaN) for arg in last_args)..., + )) + end +end diff --git a/RecipesPipeline/src/pipeline.jl b/RecipesPipeline/src/pipeline.jl deleted file mode 100644 index 07ca62e02..000000000 --- a/RecipesPipeline/src/pipeline.jl +++ /dev/null @@ -1,56 +0,0 @@ -## Stubs -function _recipe_init!(plt, plotattributes, args) end -function _recipe_after_user!(plt, plotattributes, args) end -function _recipe_after_plot!(plt, plotattributes, kw_list) end -function _recipe_before_series!(plt, kw, kw_list) kw end # this must always return the kwargs -function _recipe_after_series!(plt, kw, series_ind) end -function _recipe_finish!(plt, plotattributes, args) plt end - -## -# Here comes the specification of when which recipe is processed. -# It contains functions before and after every stage for interaction with the plotting package. - -function recipe_pipeline!(plt, # frontend specific representation of a plot - plotattributes, # current state of recipe keywords - args; # set of arguments passed by the user - type_aliases = Dict{Symbol, Symbol}()) - - _recipe_init!(plt, plotattributes, args) - - # -------------------------------- - # "USER RECIPES" - # -------------------------------- - kw_list = _process_userrecipes(plt, plotattributes, args) - _recipe_after_user!(plt, plotattributes, args) - - # -------------------------------- - # "PLOT RECIPES" - # -------------------------------- - - # "plot recipe", which acts like a series type, and is processed before - # the plot layout is created, which allows for setting layouts and other plot-wide attributes. - # we get inputs which have been fully processed by "user recipes" and "type recipes", - # so we can expect standard vectors, surfaces, etc. No defaults have been set yet. - still_to_process = kw_list - kw_list = Dict{Symbol,Any}[] - while !isempty(still_to_process) - next_kw = popfirst!(still_to_process) - _process_plotrecipe(plt, next_kw, kw_list, still_to_process; type_aliases=type_aliases) - end - - _recipe_after_plot!(plt, plotattributes, kw_list) - - # !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!! - # !!! The next step is to recursively apply series recipes until the backend supports that series type !!! - - # -------------------------------- - # "SERIES RECIPES" - # -------------------------------- - for (series_ind, kw) in enumerate(kw_list) - series_attr = _recipe_before_series!(plt, kw, kw_list) - _process_seriesrecipe(plt, series_attr, type_aliases=type_aliases) - _recipe_after_series!(plt, kw, series_ind) - end - - _recipe_finish!(plt, plotattributes, args) -end diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl new file mode 100644 index 000000000..6b7e05c3b --- /dev/null +++ b/RecipesPipeline/src/plot_recipe.jl @@ -0,0 +1,46 @@ +""" + _process_plotrecipes!(plt, kw_list) + +Grab the first in line to be processed and pass it through `apply_recipe` to generate a +list of `RecipeData` objects. +If we applied a "plot recipe" without error, then add the returned datalist's KWs, +otherwise we just add the original KW. +""" +function _process_plotrecipes!(plt, kw_list) + still_to_process = kw_list + kw_list = KW[] + while !isempty(still_to_process) + next_kw = popfirst!(still_to_process) + _process_plotrecipe(plt, next_kw, kw_list, still_to_process) + end + return kw_list +end + + +function _process_plotrecipe(plt, kw, kw_list, still_to_process) + if !isa(get(kw, :seriestype, nothing), Symbol) + # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe + push!(kw_list, kw) + return + end + try + st = kw[:seriestype] + st = kw[:seriestype] = type_alias(plt, st) + datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) + warn_on_recipe_aliases!(plt, datalist, :plot, st) + for data in datalist + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + end + push!(still_to_process, data.plotattributes) + end + catch err + if isa(err, MethodError) + push!(kw_list, kw) + else + rethrow() + end + end + return +end diff --git a/RecipesPipeline/src/process_recipes.jl b/RecipesPipeline/src/process_recipes.jl deleted file mode 100644 index 630bda1dc..000000000 --- a/RecipesPipeline/src/process_recipes.jl +++ /dev/null @@ -1,136 +0,0 @@ -# # The Recipe Consumer Interface -# To consume RecipesBase recipes, we allow plotting packages to overload the following -# hooks into the main Recipe pipeline. The docstrings should eventually describe all -# necessary functionality. -# All these methods have the first parameter as the plot object which is being acted on. -# This allows for a dispatch overload by any consumer of these recipes. - -""" - _preprocess_args(p, args, s) - -Take in a Vector of RecipeData (`s`) and fill in default attributes. -""" -_preprocess_args(p, args, s) = append!(s, RecipesBase.RecipeData[RecipesBase.RecipeData(convert(Dict{Symbol, Any}, copy(p)), args)]) # needs to modify still_to_process -# TODO define RecipesBase constructor better -""" -""" -_process_userrecipe(plt, kw_list, next_series) = nothing - -""" -""" -preprocessArgs!(p) = p - -""" -""" -is_st_supported(plt, st) = true - -""" -""" -finalize_subplot!(plt, st, att) = nothing - -function _process_userrecipes(plt, plotattributes::T, args) where T <: AbstractDict{Symbol, <: Any} - still_to_process = RecipesBase.RecipeData[] - # This should modify `still_to_process`! - _preprocess_args(plotattributes, args, still_to_process) - - # for plotting recipes, swap out the args and update the parameter dictionary - # we are keeping a stack of series that still need to be processed. - # each pass through the loop, we pop one off and apply the recipe. - # the recipe will return a list a Series objects... the ones that are - # finished (no more args) get added to the kw_list, the ones that are not - # are placed on top of the stack and are then processed further. - kw_list = Dict{Symbol,Any}[] - while !isempty(still_to_process) - # grab the first in line to be processed and either add it to the kw_list or - # pass it through apply_recipe to generate a list of RecipeData objects (data + attributes) - # for further processing. - next_series = popfirst!(still_to_process) - # recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes - if !(typeof(next_series) <: RecipesBase.RecipeData) - @error("Inputs couldn't be processed. Expected RecipeData but got: $next_series") - end - if isempty(next_series.args) - # WARNING: you need to define this on your - # custom plot type! - _process_userrecipe(plt, kw_list, next_series) - else - rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) - prepend!(still_to_process,rd_list) - end - end - - kw_list -end - -# plot recipes - -# Grab the first in line to be processed and pass it through apply_recipe -# to generate a list of RecipeData objects (data + attributes). -# If we applied a "plot recipe" without error, then add the returned datalist's KWs, -# otherwise we just add the original KW. -function _process_plotrecipe(plt, kw::AbstractDict{Symbol,Any}, kw_list::Vector{Dict{Symbol,Any}}, still_to_process::Vector{Dict{Symbol,Any}}; type_aliases::AbstractDict{Symbol, Symbol}=Dict{Symbol,Symbol}()) - if !isa(get(kw, :seriestype, nothing), Symbol) - # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe - push!(kw_list, kw) - return - end - try - st = kw[:seriestype] - st = kw[:seriestype] = get(type_aliases, st, st) - datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - for data in datalist - preprocessArgs!(data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") - end - push!(still_to_process, data.plotattributes) - end - catch err - if isa(err, MethodError) - push!(kw_list, kw) - else - rethrow() - end - end - return -end - -# ------------------------------------------------------------------------------- - -# this method recursively applies series recipes when the seriestype is not supported -# natively by the backend -function _process_seriesrecipe(plt, plotattributes::AbstractDict{Symbol,Any}; type_aliases::AbstractDict{Symbol,Symbol} = Dict{Symbol,Symbol}()) - - # replace seriestype aliases - st = Symbol(plotattributes[:seriestype]) - st = plotattributes[:seriestype] = get(type_aliases, st, st) - - # shapes shouldn't have fillrange set - if plotattributes[:seriestype] == :shape - plotattributes[:fillrange] = nothing - end - - # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse - if is_st_supported(plt, st) - finalize_subplot!(plt, st, plotattributes) - - else - # get a sub list of series for this seriestype - datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, plotattributes[:x], plotattributes[:y], plotattributes[:z]) - - # assuming there was no error, recursively apply the series recipes - for data in datalist - if isa(data, RecipesBase.RecipeData) - preprocessArgs!(data.plotattributes) - if data.plotattributes[:seriestype] == st - @error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") - end - _process_seriesrecipe(plt, data.plotattributes) - else - @warn("Unhandled recipe: $(data)") - break - end - end - end - return nothing -end diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl new file mode 100644 index 000000000..e967fa4c1 --- /dev/null +++ b/RecipesPipeline/src/series.jl @@ -0,0 +1,170 @@ +const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} +const MaybeNumber = Union{Number, Missing} +const MaybeString = Union{AbstractString, Missing} +const DataPoint = Union{MaybeNumber, MaybeString} + +_prepare_series_data(x) = error("Cannot convert $(typeof(x)) to series data for plotting") +_prepare_series_data(::Nothing) = nothing +_prepare_series_data(t::Tuple{T, T}) where {T <: Number} = t +_prepare_series_data(f::Function) = f +_prepare_series_data(ar::AbstractRange{<:Number}) = ar +function _prepare_series_data(a::AbstractArray{<:MaybeNumber}) + f = isimmutable(a) ? replace : replace! + a = f(x -> ismissing(x) || isinf(x) ? NaN : x, map(float, a)) +end +_prepare_series_data(a::AbstractArray{<:Missing}) = fill(NaN, axes(a)) +_prepare_series_data(a::AbstractArray{<:MaybeString}) = + replace(x -> ismissing(x) ? "" : x, a) +_prepare_series_data(s::Surface{<:AMat{<:MaybeNumber}}) = + Surface(_prepare_series_data(s.surf)) +_prepare_series_data(s::Surface) = s # non-numeric Surface, such as an image +_prepare_series_data(v::Volume) = + Volume(_prepare_series_data(v.v), v.x_extents, v.y_extents, v.z_extents) + +# default: assume x represents a single series +_series_data_vector(x, plotattributes) = [_prepare_series_data(x)] + +# fixed number of blank series +_series_data_vector(n::Integer, plotattributes) = [zeros(0) for i in 1:n] + +# vector of data points is a single series +_series_data_vector(v::AVec{<:DataPoint}, plotattributes) = [_prepare_series_data(v)] + +# list of things (maybe other vectors, functions, or something else) +function _series_data_vector(v::AVec, plotattributes) + if all(x -> x isa MaybeNumber, v) + _series_data_vector(Vector{MaybeNumber}(v), plotattributes) + elseif all(x -> x isa MaybeString, v) + _series_data_vector(Vector{MaybeString}(v), plotattributes) + else + vcat((_series_data_vector(vi, plotattributes) for vi in v)...) + end +end + +# Matrix is split into columns +function _series_data_vector(v::AMat{<:DataPoint}, plotattributes) + if is3d(plotattributes) + [_prepare_series_data(Surface(v))] + else + [_prepare_series_data(v[:, i]) for i in axes(v, 2)] + end +end + +# -------------------------------------------------------------------- +# Fillranges & ribbons + + +_process_fillrange(range::Number, plotattributes) = [range] +_process_fillrange(range, plotattributes) = _series_data_vector(range, plotattributes) + +_process_ribbon(ribbon::Number, plotattributes) = [ribbon] +_process_ribbon(ribbon, plotattributes) = _series_data_vector(ribbon, plotattributes) +# ribbon as a tuple: (lower_ribbons, upper_ribbons) +_process_ribbon(ribbon::Tuple{S, T}, plotattributes) where {S, T} = collect(zip( + _series_data_vector(ribbon[1], plotattributes), + _series_data_vector(ribbon[2], plotattributes), +)) + + +# -------------------------------------------------------------------- + +_compute_x(x::Nothing, y::Nothing, z) = axes(z, 1) +_compute_x(x::Nothing, y, z) = axes(y, 1) +_compute_x(x::Function, y, z) = map(x, y) +_compute_x(x, y, z) = x + +_compute_y(x::Nothing, y::Nothing, z) = axes(z, 2) +_compute_y(x, y::Function, z) = map(y, x) +_compute_y(x, y, z) = y + +_compute_z(x, y, z::Function) = map(z, x, y) +_compute_z(x, y, z::AbstractMatrix) = Surface(z) +_compute_z(x, y, z::Nothing) = nothing +_compute_z(x, y, z) = z + +_nobigs(v::AVec{BigFloat}) = map(Float64, v) +_nobigs(v::AVec{BigInt}) = map(Int64, v) +_nobigs(v) = v + +@noinline function _compute_xyz(x, y, z) + x = _compute_x(x, y, z) + y = _compute_y(x, y, z) + z = _compute_z(x, y, z) + _nobigs(x), _nobigs(y), _nobigs(z) +end + +# not allowed +_compute_xyz(x::Nothing, y::FuncOrFuncs{F}, z) where {F <: Function} = + error("If you want to plot the function `$y`, you need to define the x values!") +_compute_xyz(x::Nothing, y::Nothing, z::FuncOrFuncs{F}) where {F <: Function} = + error("If you want to plot the function `$z`, you need to define x and y values!") +_compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing!") + +# -------------------------------------------------------------------- + + +# we are going to build recipes to do the processing and splitting of the args + +# -------------------------------------------------------------------- +# The catch-all SliceIt recipe +# -------------------------------------------------------------------- + +# ensure we dispatch to the slicer +struct SliceIt end + +# TODO: Should ribbon and fillrange be handled by the plotting package? + +# The `SliceIt` recipe finishes user and type recipe processing. +# It splits processed data into individual series data, stores in copied `plotattributes` +# for each series and returns no arguments. +@recipe function f(::Type{SliceIt}, x, y, z) + + # handle data with formatting attached + if typeof(x) <: Formatted + xformatter := x.formatter + x = x.data + end + if typeof(y) <: Formatted + yformatter := y.formatter + y = y.data + end + if typeof(z) <: Formatted + zformatter := z.formatter + z = z.data + end + + xs = _series_data_vector(x, plotattributes) + ys = _series_data_vector(y, plotattributes) + zs = _series_data_vector(z, plotattributes) + + fr = pop!(plotattributes, :fillrange, nothing) + fillranges = _process_fillrange(fr, plotattributes) + mf = length(fillranges) + + rib = pop!(plotattributes, :ribbon, nothing) + ribbons = _process_ribbon(rib, plotattributes) + mr = length(ribbons) + + mx = length(xs) + my = length(ys) + mz = length(zs) + if mx > 0 && my > 0 && mz > 0 + for i in 1:max(mx, my, mz) + # add a new series + di = copy(plotattributes) + xi, yi, zi = xs[mod1(i, mx)], ys[mod1(i, my)], zs[mod1(i, mz)] + di[:x], di[:y], di[:z] = _compute_xyz(xi, yi, zi) + + # handle fillrange + fr = fillranges[mod1(i, mf)] + di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr + + # handle ribbons + rib = ribbons[mod1(i, mr)] + di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib + + push!(series_list, RecipeData(di, ())) + end + end + nothing # don't add a series for the main block +end diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl new file mode 100644 index 000000000..37bb6a4ce --- /dev/null +++ b/RecipesPipeline/src/series_recipe.jl @@ -0,0 +1,62 @@ +""" + _process_seriesrecipes!(plt, kw_list) + +Recursively apply series recipes until the backend supports the seriestype +""" +function _process_seriesrecipes!(plt, kw_list) + for kw in kw_list + # in series attributes given as vector with one element per series, + # select the value for current series + slice_series_attributes!(plt, kw_list, kw) + + series_attr = DefaultsDict(kw, series_defaults(plt)) + # now we have a fully specified series, with colors chosen. we must recursively + # handle series recipes, which dispatch on seriestype. If a backend does not + # natively support a seriestype, we check for a recipe that will convert that + # series type into one made up of lower-level components. + # For example, a histogram is just a bar plot with binned data, a bar plot is + # really a filled step plot, and a step plot is really just a path. So any backend + # that supports drawing a path will implicitly be able to support step, bar, and + # histogram plots (and any recipes that use those components). + _process_seriesrecipe(plt, series_attr) + end +end + +# this method recursively applies series recipes when the seriestype is not supported +# natively by the backend +function _process_seriesrecipe(plt, plotattributes) + # replace seriestype aliases + st = Symbol(plotattributes[:seriestype]) + st = plotattributes[:seriestype] = type_alias(plt, st) + + # shapes shouldn't have fillrange set + if plotattributes[:seriestype] == :shape + plotattributes[:fillrange] = nothing + end + + # if it's natively supported, finalize processing and pass along to the backend, + # otherwise recurse + if is_seriestype_supported(plt, st) + add_series!(plt, plotattributes) + else + # get a sub list of series for this seriestype + x, y, z = plotattributes[:x], plotattributes[:y], plotattributes[:z] + datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, x, y, z) + warn_on_recipe_aliases!(plt, datalist, :series, st) + + # assuming there was no error, recursively apply the series recipes + for data in datalist + if isa(data, RecipeData) + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") + end + _process_seriesrecipe(plt, data.plotattributes) + else + @warn("Unhandled recipe: $(data)") + break + end + end + end + nothing +end diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl new file mode 100644 index 000000000..527fbae69 --- /dev/null +++ b/RecipesPipeline/src/type_recipe.jl @@ -0,0 +1,94 @@ +# this is the default "type recipe"... just pass the object through +@recipe f(::Type{T}, v::T) where {T} = v + +# this should catch unhandled "series recipes" and error with a nice message +@recipe f(::Type{V}, x, y, z) where {V <: Val} = + error("The backend must not support the series type $V, and there isn't a series recipe defined.") + +""" + _apply_type_recipe(plotattributes, v::T, letter) + +Apply the type recipe with signature `(::Type{T}, ::T)`. +""" +function _apply_type_recipe(plotattributes, v, letter) + _preprocess_axis_args!(plotattributes, letter) + rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v) + warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, typeof(v)) + _postprocess_axis_args!(plotattributes, letter) + return rdvec[1].args[1] +end + +# Handle type recipes when the recipe is defined on the elements. +# This sort of recipe should return a pair of functions... one to convert to number, +# and one to format tick values. +function _apply_type_recipe(plotattributes, v::AbstractArray, letter) + plt = plotattributes[:plot_object] + _preprocess_axis_args!(plotattributes, letter) + # First we try to apply an array type recipe. + w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1] + warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(v)) + # If the type did not change try it element-wise + if typeof(v) == typeof(w) + isempty(skipmissing(v)) && return Float64[] + x = first(skipmissing(v)) + args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args + warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(x)) + _postprocess_axis_args!(plotattributes, letter) + if length(args) == 2 && all(arg -> arg isa Function, args) + numfunc, formatter = args + return Formatted(map(numfunc, v), formatter) + else + return v + end + end + _postprocess_axis_args!(plotattributes, letter) + return w +end + +# special handling for Surface... need to properly unwrap and re-wrap +_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:DataPoint}}) = v +function _apply_type_recipe(plotattributes, v::Surface) + ret = _apply_type_recipe(plotattributes, v.surf) + if typeof(ret) <: Formatted + Formatted(Surface(ret.data), ret.formatter) + else + Surface(ret.data) + end +end + +# don't do anything for datapoints or nothing +_apply_type_recipe(plotattributes, v::AbstractArray{<:DataPoint}, letter) = v +_apply_type_recipe(plotattributes, v::Nothing, letter) = v + +# axis args before type recipes should still be mapped to all axes +function _preprocess_axis_args!(plotattributes) + plt = plotattributes[:plot_object] + for (k, v) in plotattributes + if is_axis_attribute(plt, k) + pop!(plotattributes, k) + for l in (:x, :y, :z) + lk = Symbol(l, k) + haskey(plotattributes, lk) || (plotattributes[lk] = v) + end + end + end +end +function _preprocess_axis_args!(plotattributes, letter) + plotattributes[:letter] = letter + _preprocess_axis_args!(plotattributes) +end + +# axis args in type recipes should only be applied to the current axis +function _postprocess_axis_args!(plotattributes, letter) + plt = plotattributes[:plot_object] + pop!(plotattributes, :letter) + if letter in (:x, :y, :z) + for (k, v) in plotattributes + if is_axis_attribute(plt, k) + pop!(plotattributes, k) + lk = Symbol(letter, k) + haskey(plotattributes, lk) || (plotattributes[lk] = v) + end + end + end +end diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl new file mode 100644 index 000000000..0023474f2 --- /dev/null +++ b/RecipesPipeline/src/user_recipe.jl @@ -0,0 +1,330 @@ +""" + _process_userrecipes(plt, plotattributes, args) + +Wrap input arguments in a `RecipeData' vector and recursively apply user recipes and type +recipes on the first element. Prepend the returned `RecipeData` vector. If an element with +empy `args` is returned pop it from the vector, finish up, and it to vector of `Dict`s with +processed series. When all arguments are processed return the series `Dict`. +""" +function _process_userrecipes!(plt, plotattributes, args) + still_to_process = _recipedata_vector(plt, plotattributes, args) + + # for plotting recipes, swap out the args and update the parameter dictionary + # we are keeping a stack of series that still need to be processed. + # each pass through the loop, we pop one off and apply the recipe. + # the recipe will return a list a Series objects... the ones that are + # finished (no more args) get added to the kw_list, the ones that are not + # are placed on top of the stack and are then processed further. + kw_list = KW[] + while !isempty(still_to_process) + # grab the first in line to be processed and either add it to the kw_list or + # pass it through apply_recipe to generate a list of RecipeData objects + # (data + attributes) for further processing. + next_series = popfirst!(still_to_process) + # recipedata should be of type RecipeData. + # if it's not then the inputs must not have been fully processed by recipes + if !(typeof(next_series) <: RecipeData) + error("Inputs couldn't be processed... expected RecipeData but got: $next_series") + end + if isempty(next_series.args) + _finish_userrecipe!(plt, kw_list, next_series) + else + rd_list = + RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) + warn_on_recipe_aliases!(plt, rd_list, :user, next_series.args...) + prepend!(still_to_process, rd_list) + end + end + + # don't allow something else to handle it + plotattributes[:smooth] = false + kw_list +end + + +# TODO Move this to api.jl? + +function _recipedata_vector(plt, plotattributes, args) + still_to_process = RecipeData[] + # the grouping mechanism is a recipe on a GroupBy object + # we simply add the GroupBy object to the front of the args list to allow + # the recipe to be applied + if haskey(plotattributes, :group) + args = (_extract_group_attributes(plotattributes[:group], args...), args...) + end + + # if we were passed a vector/matrix of seriestypes and there's more than one row, + # we want to duplicate the inputs, once for each seriestype row. + if !isempty(args) + append!(still_to_process, _expand_seriestype_array(plotattributes, args)) + end + + # remove subplot and axis args from plotattributes... + # they will be passed through in the kw_list + if !isempty(args) + for (k, v) in plotattributes + if is_subplot_attribute(plt, k) || is_axis_attribute(plt, k) + reset_kw!(plotattributes, k) + end + end + end + + still_to_process +end + +function _expand_seriestype_array(plotattributes, args) + sts = get(plotattributes, :seriestype, :path) + if typeof(sts) <: AbstractArray + reset_kw!(plotattributes, :seriestype) + rd = Vector{RecipeData}(undef, size(sts, 1)) + for r in axes(sts, 1) + dc = copy(plotattributes) + dc[:seriestype] = sts[r:r, :] + rd[r] = RecipeData(dc, args) + end + rd + else + RecipeData[RecipeData(copy(plotattributes), args)] + end +end + + +function _finish_userrecipe!(plt, kw_list, recipedata) + # when the arg tuple is empty, that means there's nothing left to recursively + # process... finish up and add to the kw_list + kw = recipedata.plotattributes + preprocess_attributes!(plt, kw) + # if there was a grouping, filter the data here + _filter_input_data!(kw) + process_userrecipe!(plt, kw_list, kw) +end + + +# -------------------------------- +# Fallback user recipes +# -------------------------------- + +# These call `_apply_type_recipe` in type_recipe.jl and finally the `SliceIt` recipe in +# series.jl. + +# handle "type recipes" by converting inputs, and then either re-calling or slicing +@recipe function f(x, y, z) + wrap_surfaces!(plotattributes, x, y, z) + did_replace = false + newx = _apply_type_recipe(plotattributes, x, :x) + x === newx || (did_replace = true) + newy = _apply_type_recipe(plotattributes, y, :y) + y === newy || (did_replace = true) + newz = _apply_type_recipe(plotattributes, z, :z) + z === newz || (did_replace = true) + if did_replace + newx, newy, newz + else + SliceIt, x, y, z + end +end +@recipe function f(x, y) + wrap_surfaces!(plotattributes, x, y) + did_replace = false + newx = _apply_type_recipe(plotattributes, x, :x) + x === newx || (did_replace = true) + newy = _apply_type_recipe(plotattributes, y, :y) + y === newy || (did_replace = true) + if did_replace + newx, newy + else + SliceIt, x, y, nothing + end +end +@recipe function f(y) + wrap_surfaces!(plotattributes, y) + newy = _apply_type_recipe(plotattributes, y, :y) + if y !== newy + newy + else + SliceIt, nothing, y, nothing + end +end + +# if there's more than 3 inputs, it can't be passed directly to SliceIt +# so we'll apply_type_recipe to all of them +@recipe function f(v1, v2, v3, v4, vrest...) + did_replace = false + newargs = map( + v -> begin + newv = _apply_type_recipe(plotattributes, v, :unknown) + if newv !== v + did_replace = true + end + newv + end, + (v1, v2, v3, v4, vrest...), + ) + if !did_replace + error("Couldn't process recipe args: $(map(typeof, (v1, v2, v3, v4, vrest...)))") + end + newargs +end + + +# helper function to ensure relevant attributes are wrapped by Surface +function wrap_surfaces!(plotattributes, args...) end +wrap_surfaces!(plotattributes, x::AMat, y::AMat, z::AMat) = wrap_surfaces!(plotattributes) +wrap_surfaces!(plotattributes, x::AVec, y::AVec, z::AMat) = wrap_surfaces!(plotattributes) +function wrap_surfaces!(plotattributes, x::AVec, y::AVec, z::Surface) + wrap_surfaces!(plotattributes) +end +function wrap_surfaces!(plotattributes) + if haskey(plotattributes, :fill_z) + v = plotattributes[:fill_z] + if !isa(v, Surface) + plotattributes[:fill_z] = Surface(v) + end + end +end + + +# -------------------------------- +# Special Cases +# -------------------------------- + +# -------------------------------- +# 1 argument + +@recipe function f(n::Integer) + if is3d(plotattributes) + SliceIt, n, n, n + else + SliceIt, n, n, nothing + end +end + +# return a surface if this is a 3d plot, otherwise let it be sliced up +@recipe function f(mat::AMat) + if is3d(plotattributes) + n, m = axes(mat) + m, n, Surface(mat) + else + nothing, mat, nothing + end +end + +# if a matrix is wrapped by Formatted, do similar logic, but wrap data with Surface +@recipe function f(fmt::Formatted{<:AMat}) + if is3d(plotattributes) + mat = fmt.data + n, m = axes(mat) + m, n, Formatted(Surface(mat), fmt.formatter) + else + nothing, fmt, nothing + end +end + +# assume this is a Volume, so construct one +@recipe function f(vol::AbstractArray{<:MaybeNumber, 3}, args...) + seriestype := :volume + SliceIt, nothing, Volume(vol, args...), nothing +end + +# Dicts: each entry is a data point (x,y)=(key,value) +@recipe f(d::AbstractDict) = collect(keys(d)), collect(values(d)) + +# function without range... use the current range of the x-axis +@recipe function f(f::FuncOrFuncs{F}) where {F <: Function} + plt = plotattributes[:plot_object] + xmin, xmax = if haskey(plotattributes, :xlims) + plotattributes[:xlims] + else + try + get_axis_limits(plt, :x) + catch + xinv = inverse_scale_func(get(plotattributes, :xscale, :identity)) + xm = PlotUtils.tryrange(f, xinv.([-5, -1, 0, 0.01])) + xm, PlotUtils.tryrange(f, filter(x -> x > xm, xinv.([5, 1, 0.99, 0, -0.01]))) + end + end + f, xmin, xmax +end + + +# -------------------------------- +# 2 arguments + +# if functions come first, just swap the order (not to be confused with parametric +# functions... as there would be more than one function passed in) +@recipe function f(f::FuncOrFuncs{F}, x) where {F <: Function} + F2 = typeof(x) + @assert !(F2 <: Function || (F2 <: AbstractArray && F2.parameters[1] <: Function)) + # otherwise we'd hit infinite recursion here + x, f +end + + +# -------------------------------- +# 3 arguments + +# surface-like... function +@recipe function f(x::AVec, y::AVec, zf::Function) + x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported +end + +# surface-like... matrix grid +@recipe function f(x::AVec, y::AVec, z::AMat) + if !is_surface(plotattributes) + plotattributes[:seriestype] = :contour + end + x, y, Surface(z) +end + +# parametric functions +# special handling... xmin/xmax with parametric function(s) +@recipe function f(f::Function, xmin::Number, xmax::Number) + xscale, yscale = [get(plotattributes, sym, :identity) for sym in (:xscale, :yscale)] + _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) +end +@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where {F <: Function} + xscale, yscale = [get(plotattributes, sym, :identity) for sym in (:xscale, :yscale)] + unzip(_scaled_adapted_grid.(fs, xscale, yscale, xmin, xmax)) +end +@recipe f( + fx::FuncOrFuncs{F}, + fy::FuncOrFuncs{G}, + u::AVec, +) where {F <: Function, G <: Function} = _map_funcs(fx, u), _map_funcs(fy, u) +@recipe f( + fx::FuncOrFuncs{F}, + fy::FuncOrFuncs{G}, + umin::Number, + umax::Number, + n = 200, +) where {F <: Function, G <: Function} = fx, fy, range(umin, stop = umax, length = n) + +function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) + (xf, xinv), (yf, yinv) = ((scale_func(s), inverse_scale_func(s)) for s in (xscale, yscale)) + xs, ys = PlotUtils.adapted_grid(yf ∘ f ∘ xinv, xf.((xmin, xmax))) + xinv.(xs), yinv.(ys) +end + +# special handling... 3D parametric function(s) +@recipe function f( + fx::FuncOrFuncs{F}, + fy::FuncOrFuncs{G}, + fz::FuncOrFuncs{H}, + u::AVec, +) where {F <: Function, G <: Function, H <: Function} + _map_funcs(fx, u), _map_funcs(fy, u), _map_funcs(fz, u) +end +@recipe function f( + fx::FuncOrFuncs{F}, + fy::FuncOrFuncs{G}, + fz::FuncOrFuncs{H}, + umin::Number, + umax::Number, + numPoints = 200, +) where {F <: Function, G <: Function, H <: Function} + fx, fy, fz, range(umin, stop = umax, length = numPoints) +end + +# list of tuples +@recipe f(v::AVec{<:Tuple}) = unzip(v) +@recipe f(tup::Tuple) = [tup] diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl new file mode 100644 index 000000000..54862d47c --- /dev/null +++ b/RecipesPipeline/src/utils.jl @@ -0,0 +1,220 @@ +const AVec = AbstractVector +const AMat = AbstractMatrix +const KW = Dict{Symbol, Any} +const AKW = AbstractDict{Symbol, Any} + +# -------------------------------- +# DefaultsDict +# -------------------------------- + +struct DefaultsDict <: AbstractDict{Symbol, Any} + explicit::KW + defaults::KW +end + +function Base.getindex(dd::DefaultsDict, k) + return haskey(dd.explicit, k) ? dd.explicit[k] : dd.defaults[k] +end +Base.haskey(dd::DefaultsDict, k) = haskey(dd.explicit, k) || haskey(dd.defaults, k) +Base.get(dd::DefaultsDict, k, default) = haskey(dd, k) ? dd[k] : default +function Base.get!(dd::DefaultsDict, k, default) + v = if haskey(dd, k) + dd[k] + else + dd.defaults[k] = default + end + return v +end +function Base.delete!(dd::DefaultsDict, k) + haskey(dd.explicit, k) && delete!(dd.explicit, k) + haskey(dd.defaults, k) && delete!(dd.defaults, k) +end +Base.length(dd::DefaultsDict) = length(union(keys(dd.explicit), keys(dd.defaults))) +function Base.iterate(dd::DefaultsDict) + exp_keys = keys(dd.explicit) + def_keys = setdiff(keys(dd.defaults), exp_keys) + key_list = collect(Iterators.flatten((exp_keys, def_keys))) + iterate(dd, (key_list, 1)) +end +function Base.iterate(dd::DefaultsDict, (key_list, i)) + i > length(key_list) && return nothing + k = key_list[i] + (k => dd[k], (key_list, i + 1)) +end + +Base.copy(dd::DefaultsDict) = DefaultsDict(copy(dd.explicit), dd.defaults) + +RecipesBase.is_explicit(dd::DefaultsDict, k) = haskey(dd.explicit, k) +isdefault(dd::DefaultsDict, k) = !is_explicit(dd, k) && haskey(dd.defaults, k) + +Base.setindex!(dd::DefaultsDict, v, k) = dd.explicit[k] = v + +# Reset to default value and return dict +reset_kw!(dd::DefaultsDict, k) = is_explicit(dd, k) ? delete!(dd.explicit, k) : dd +# Reset to default value and return old value +pop_kw!(dd::DefaultsDict, k) = is_explicit(dd, k) ? pop!(dd.explicit, k) : dd.defaults[k] +pop_kw!(dd::DefaultsDict, k, default) = + is_explicit(dd, k) ? pop!(dd.explicit, k) : get(dd.defaults, k, default) +# Fallbacks for dicts without defaults +reset_kw!(d::AKW, k) = delete!(d, k) +pop_kw!(d::AKW, k) = pop!(d, k) +pop_kw!(d::AKW, k, default) = pop!(d, k, default) + + +# -------------------------------- +# 3D types +# -------------------------------- + +abstract type AbstractSurface end + +"represents a contour or surface mesh" +struct Surface{M <: AMat} <: AbstractSurface + surf::M +end + +Surface(f::Function, x, y) = Surface(Float64[f(xi, yi) for yi in y, xi in x]) + +Base.Array(surf::Surface) = surf.surf + +for f in (:length, :size, :axes) + @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) +end +Base.copy(surf::Surface) = Surface(copy(surf.surf)) +Base.eltype(surf::Surface{T}) where {T} = eltype(T) + + +struct Volume{T} + v::Array{T, 3} + x_extents::Tuple{T, T} + y_extents::Tuple{T, T} + z_extents::Tuple{T, T} +end + +default_extents(::Type{T}) where {T} = (zero(T), one(T)) + +function Volume( + v::Array{T, 3}, + x_extents = default_extents(T), + y_extents = default_extents(T), + z_extents = default_extents(T), +) where {T} + Volume(v, x_extents, y_extents, z_extents) +end + +Base.Array(vol::Volume) = vol.v +for f in (:length, :size) + @eval Base.$f(vol::Volume, args...) = $f(vol.v, args...) +end +Base.copy(vol::Volume{T}) where {T} = + Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) +Base.eltype(vol::Volume{T}) where {T} = T + + +# -------------------------------- +# Formatting +# -------------------------------- + +"Represents data values with formatting that should apply to the tick labels." +struct Formatted{T} + data::T + formatter::Function +end + +# ------------------------------- +# 3D seriestypes +# ------------------------------- + +# TODO: Move to RecipesBase? +""" + is3d(::Type{Val{:myseriestype}}) + +Returns `true` if `myseriestype` represents a 3D series, `false` otherwise. +""" +is3d(st) = false +for st in ( + :contour, + :contourf, + :contour3d, + :heatmap, + :image, + :path3d, + :scatter3d, + :surface, + :volume, + :wireframe, +) + @eval is3d(::Type{Val{Symbol($(string(st)))}}) = true +end +is3d(st::Symbol) = is3d(Val{st}) +is3d(plt, stv::AbstractArray) = all(st -> is3d(plt, st), stv) +is3d(plotattributes::AbstractDict) = is3d(get(plotattributes, :seriestype, :path)) + + +""" + is_surface(::Type{Val{:myseriestype}}) + +Returns `true` if `myseriestype` represents a surface series, `false` otherwise. +""" +is_surface(st) = false +for st in (:contour, :contourf, :contour3d, :image, :heatmap, :surface, :wireframe) + @eval is_surface(::Type{Val{Symbol($(string(st)))}}) = true +end +is_surface(st::Symbol) = is_surface(Val{st}) +is_surface(plt, stv::AbstractArray) = all(st -> is_surface(plt, st), stv) +is_surface(plotattributes::AbstractDict) = + is_surface(get(plotattributes, :seriestype, :path)) + + +""" + needs_3d_axes(::Type{Val{:myseriestype}}) + +Returns `true` if `myseriestype` needs 3d axes, `false` otherwise. +""" +needs_3d_axes(st) = false +for st in ( + :contour3d, + :path3d, + :scatter3d, + :surface, + :volume, + :wireframe, +) + @eval needs_3d_axes(::Type{Val{Symbol($(string(st)))}}) = true +end +needs_3d_axes(st::Symbol) = needs_3d_axes(Val{st}) +needs_3d_axes(plt, stv::AbstractArray) = all(st -> needs_3d_axes(plt, st), stv) +needs_3d_axes(plotattributes::AbstractDict) = + needs_3d_axes(get(plotattributes, :seriestype, :path)) + + +# -------------------------------- +# Scales +# -------------------------------- + +const SCALE_FUNCTIONS = Dict{Symbol, Function}(:log10 => log10, :log2 => log2, :ln => log) +const INVERSE_SCALE_FUNCTIONS = + Dict{Symbol, Function}(:log10 => exp10, :log2 => exp2, :ln => exp) + +scale_func(scale::Symbol) = x -> get(SCALE_FUNCTIONS, scale, identity)(Float64(x)) +inverse_scale_func(scale::Symbol) = + x -> get(INVERSE_SCALE_FUNCTIONS, scale, identity)(Float64(x)) + + +# -------------------------------- +# Unzip +# -------------------------------- + +for i in 2:4 + @eval begin + unzip(v::AVec{<:Tuple{Vararg{T, $i} where T}}) = + $(Expr(:tuple, (:([t[$j] for t in v]) for j in 1:i)...)) + end +end + + +# -------------------------------- +# Map functions on vectors +# -------------------------------- + +_map_funcs(f::Function, u::AVec) = map(f, u) +_map_funcs(fs::AVec{F}, u::AVec) where {F <: Function} = [map(f, u) for f in fs] From e43b39fbf14dd655240a70855ed86c88a3346db5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 Apr 2020 12:49:19 +0200 Subject: [PATCH 142/356] release 1.0 :tada: --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index 9b2cd0758..e15d69112 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "0.8.0" +version = "1.0.0" [compat] julia = "1" From 5476108aadad7d0ff94ed45a7a7498a9d57ff8b8 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 14:14:49 +0200 Subject: [PATCH 143/356] [wip] add readme --- RecipesPipeline/README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index a68ad847f..ccec3d501 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,4 +1,29 @@ -# RecipeUtils +# RecipePipeline [![Build Status](https://travis-ci.com/mkborregaard/RecipeUtils.jl.svg?branch=master)](https://travis-ci.com/mkborregaard/RecipeUtils.jl) [![Codecov](https://codecov.io/gh/mkborregaard/RecipeUtils.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/mkborregaard/RecipeUtils.jl) + +#### [WIP] An implementation of the recipe pipeline from Plots +This package was factored out of Plots.jl to allow any other plotting package to use the recipe pipeline. In short, the extremely lightweight RecipesBase.jl package can be depended on by any package to define "recipes": plot specifications of user-defined types, as well as custom plot types. RecipePipeline.jl contains the machinery to translate these recipes to full specifications for a plot. + +The package is intended to be used by consumer plotting packages, and is currently used by Plots.jl (v.1.1.0 and above) and MakieRecipes.jl, a package that bridges RecipesBase recipes to Makie.jl. + +Current functionality: +```julia +using RecipesBase + +# Our user-defined data type +struct T end + +@recipe function plot(::T, n = 1; customcolor = :green) + markershape --> :auto # if markershape is unset, make it :auto + markercolor := customcolor # force markercolor to be customcolor + xrotation --> 45 # if xrotation is unset, make it 45 + zrotation --> 90 # if zrotation is unset, make it 90 + rand(10,n) # return the arguments (input data) for the next recipe +end + +using Makie, MakieRecipes +plot(T(), 3) + +``` From 958a92772f95b6a0a9c4c5d401ad028b32bac10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 15:37:01 +0300 Subject: [PATCH 144/356] Add preliminary docs --- RecipesPipeline/docs/.gitignore | 2 ++ RecipesPipeline/docs/Project.toml | 2 ++ RecipesPipeline/docs/make.jl | 25 +++++++++++++++++++++++++ RecipesPipeline/docs/src/api.md | 18 ++++++++++++++++++ RecipesPipeline/docs/src/index.md | 7 +++++++ RecipesPipeline/docs/src/recipes.md | 10 ++++++++++ RecipesPipeline/docs/src/reference.md | 4 ++++ 7 files changed, 68 insertions(+) create mode 100644 RecipesPipeline/docs/.gitignore create mode 100644 RecipesPipeline/docs/Project.toml create mode 100644 RecipesPipeline/docs/make.jl create mode 100644 RecipesPipeline/docs/src/api.md create mode 100644 RecipesPipeline/docs/src/index.md create mode 100644 RecipesPipeline/docs/src/recipes.md create mode 100644 RecipesPipeline/docs/src/reference.md diff --git a/RecipesPipeline/docs/.gitignore b/RecipesPipeline/docs/.gitignore new file mode 100644 index 000000000..a303fff20 --- /dev/null +++ b/RecipesPipeline/docs/.gitignore @@ -0,0 +1,2 @@ +build/ +site/ diff --git a/RecipesPipeline/docs/Project.toml b/RecipesPipeline/docs/Project.toml new file mode 100644 index 000000000..dfa65cd10 --- /dev/null +++ b/RecipesPipeline/docs/Project.toml @@ -0,0 +1,2 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl new file mode 100644 index 000000000..38c38a757 --- /dev/null +++ b/RecipesPipeline/docs/make.jl @@ -0,0 +1,25 @@ +using Documenter +using RecipePipeline + +makedocs( + sitename = "RecipePipeline", + format = format = Documenter.HTML( + prettyurls = get(ENV, "CI", nothing) == "true" + ), + pages = [ + "index.md", + "Developer manual" => [ + "Public API" => "api.md", + "Recipes" => "recipes.md" + ], + "Reference" => "reference.md" + ], + modules = [RecipePipeline] +) + +# Documenter can also automatically deploy documentation to gh-pages. +# See "Hosting Documentation" and deploydocs() in the Documenter manual +# for more information. +#=deploydocs( + repo = "" +)=# diff --git a/RecipesPipeline/docs/src/api.md b/RecipesPipeline/docs/src/api.md new file mode 100644 index 000000000..d603b9044 --- /dev/null +++ b/RecipesPipeline/docs/src/api.md @@ -0,0 +1,18 @@ +### API + +```@autodocs +Modules = [RecipePipeline] +Pages = [ + "api.jl" +] +Private = false +``` + +### Utility functions + +```@autodocs +Modules = [RecipePipeline] +Pages = [ + "utils.jl" +] +``` diff --git a/RecipesPipeline/docs/src/index.md b/RecipesPipeline/docs/src/index.md new file mode 100644 index 000000000..1e6f4c8de --- /dev/null +++ b/RecipesPipeline/docs/src/index.md @@ -0,0 +1,7 @@ +# RecipePipeline.jl + +Documentation for RecipePipeline.jl + +```@docs +recipe_pipeline!(plt, plotattributes, args) +``` diff --git a/RecipesPipeline/docs/src/recipes.md b/RecipesPipeline/docs/src/recipes.md new file mode 100644 index 000000000..c306009af --- /dev/null +++ b/RecipesPipeline/docs/src/recipes.md @@ -0,0 +1,10 @@ +## Recipes processing + +```@autodocs +Modules = [RecipePipeline] +Pages = [ + "user_recipe.jl", + "plot_recipe.jl", + "series_recipe.jl" +] +``` diff --git a/RecipesPipeline/docs/src/reference.md b/RecipesPipeline/docs/src/reference.md new file mode 100644 index 000000000..d68550791 --- /dev/null +++ b/RecipesPipeline/docs/src/reference.md @@ -0,0 +1,4 @@ +## Reference + +```@index +``` From 816c3399eb4d9c158fb382ea72e80412760f6e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 16:19:15 +0300 Subject: [PATCH 145/356] Rename --- RecipesPipeline/Project.toml | 2 +- RecipesPipeline/docs/make.jl | 6 +++--- RecipesPipeline/docs/src/api.md | 4 ++-- RecipesPipeline/docs/src/index.md | 4 ++-- RecipesPipeline/docs/src/recipes.md | 2 +- RecipesPipeline/src/RecipePipeline.jl | 2 +- RecipesPipeline/src/api.jl | 4 ++-- RecipesPipeline/test/runtests.jl | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 1f5f6f63d..1c73c52a8 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,4 +1,4 @@ -name = "RecipePipeline" +name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] version = "0.1.0" diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index 38c38a757..b1286c72d 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -1,8 +1,8 @@ using Documenter -using RecipePipeline +using RecipesPipeline makedocs( - sitename = "RecipePipeline", + sitename = "RecipesPipeline", format = format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true" ), @@ -14,7 +14,7 @@ makedocs( ], "Reference" => "reference.md" ], - modules = [RecipePipeline] + modules = [RecipesPipeline] ) # Documenter can also automatically deploy documentation to gh-pages. diff --git a/RecipesPipeline/docs/src/api.md b/RecipesPipeline/docs/src/api.md index d603b9044..2896860ed 100644 --- a/RecipesPipeline/docs/src/api.md +++ b/RecipesPipeline/docs/src/api.md @@ -1,7 +1,7 @@ ### API ```@autodocs -Modules = [RecipePipeline] +Modules = [RecipesPipeline] Pages = [ "api.jl" ] @@ -11,7 +11,7 @@ Private = false ### Utility functions ```@autodocs -Modules = [RecipePipeline] +Modules = [RecipesPipeline] Pages = [ "utils.jl" ] diff --git a/RecipesPipeline/docs/src/index.md b/RecipesPipeline/docs/src/index.md index 1e6f4c8de..289969c77 100644 --- a/RecipesPipeline/docs/src/index.md +++ b/RecipesPipeline/docs/src/index.md @@ -1,6 +1,6 @@ -# RecipePipeline.jl +# RecipesPipeline.jl -Documentation for RecipePipeline.jl +Documentation for RecipesPipeline.jl ```@docs recipe_pipeline!(plt, plotattributes, args) diff --git a/RecipesPipeline/docs/src/recipes.md b/RecipesPipeline/docs/src/recipes.md index c306009af..381c648a0 100644 --- a/RecipesPipeline/docs/src/recipes.md +++ b/RecipesPipeline/docs/src/recipes.md @@ -1,7 +1,7 @@ ## Recipes processing ```@autodocs -Modules = [RecipePipeline] +Modules = [RecipesPipeline] Pages = [ "user_recipe.jl", "plot_recipe.jl", diff --git a/RecipesPipeline/src/RecipePipeline.jl b/RecipesPipeline/src/RecipePipeline.jl index 03cc24e60..fd3e56a93 100644 --- a/RecipesPipeline/src/RecipePipeline.jl +++ b/RecipesPipeline/src/RecipePipeline.jl @@ -1,4 +1,4 @@ -module RecipePipeline +module RecipesPipeline import RecipesBase import RecipesBase: @recipe, @series, RecipeData, is_explicit diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index feb9350ae..648a62560 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -44,7 +44,7 @@ For example, Plots replaces aliases and expands magic arguments. """ function preprocess_attributes!(plt, plotattributes) end -# TODO: should the Plots version be defined as fallback in RecipePipeline? +# TODO: should the Plots version be defined as fallback in RecipesPipeline? """ is_subplot_attribute(plt, attr) @@ -52,7 +52,7 @@ Returns `true` if `attr` is a subplot attribute, otherwise `false`. """ is_subplot_attribute(plt, attr) = false -# TODO: should the Plots version be defined as fallback in RecipePipeline? +# TODO: should the Plots version be defined as fallback in RecipesPipeline? """ is_axis_attribute(plt, attr) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index bee6d15f9..6c656152e 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -1,6 +1,6 @@ -using RecipePipeline +using RecipesPipeline using Test -@testset "RecipePipeline.jl" begin +@testset "RecipesPipeline.jl" begin # Write your own tests here. end From 07f9bd480cf9bf6c45ff94212583feaba619d2f3 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 15:36:53 +0200 Subject: [PATCH 146/356] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Sebastian Micluța-Câmpeanu <31181429+SebastianM-C@users.noreply.github.com> --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index ccec3d501..b71458849 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,4 +1,4 @@ -# RecipePipeline +# RecipesPipeline [![Build Status](https://travis-ci.com/mkborregaard/RecipeUtils.jl.svg?branch=master)](https://travis-ci.com/mkborregaard/RecipeUtils.jl) [![Codecov](https://codecov.io/gh/mkborregaard/RecipeUtils.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/mkborregaard/RecipeUtils.jl) From c08995cbbb603e015636fcb03fdf9e19372cb041 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 15:45:58 +0200 Subject: [PATCH 147/356] Update README.md Co-Authored-By: Anshul Singhvi --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index b71458849..576391195 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -6,7 +6,7 @@ #### [WIP] An implementation of the recipe pipeline from Plots This package was factored out of Plots.jl to allow any other plotting package to use the recipe pipeline. In short, the extremely lightweight RecipesBase.jl package can be depended on by any package to define "recipes": plot specifications of user-defined types, as well as custom plot types. RecipePipeline.jl contains the machinery to translate these recipes to full specifications for a plot. -The package is intended to be used by consumer plotting packages, and is currently used by Plots.jl (v.1.1.0 and above) and MakieRecipes.jl, a package that bridges RecipesBase recipes to Makie.jl. +The package is intended to be used by consumer plotting packages, and is currently used by [Plots.jl](https://github.com/JuliaPlots/Plots.jl) (v.1.1.0 and above) and [MakieRecipes.jl](https://github.com/JuliaPlots/MakieRecipes.jl), a package that bridges RecipesBase recipes to [Makie.jl](https://github.com/JuliaPlots/Makie.jl). Current functionality: ```julia From 00b33262c763c1290b22241c89e8992e74b2740c Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 15:46:04 +0200 Subject: [PATCH 148/356] Update README.md Co-Authored-By: Anshul Singhvi --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index 576391195..d43281f52 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -24,6 +24,6 @@ struct T end end using Makie, MakieRecipes -plot(T(), 3) +recipeplot(T(), 3; markersize = 5) ``` From 2b56b05b12631c0eadab34252963070024ee709f Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sun, 5 Apr 2020 19:16:30 +0530 Subject: [PATCH 149/356] Change the main file name (#30) --- RecipesPipeline/src/{RecipePipeline.jl => RecipesPipeline.jl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename RecipesPipeline/src/{RecipePipeline.jl => RecipesPipeline.jl} (100%) diff --git a/RecipesPipeline/src/RecipePipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl similarity index 100% rename from RecipesPipeline/src/RecipePipeline.jl rename to RecipesPipeline/src/RecipesPipeline.jl From fcce46da1bfad1952a631b417c142aa439d465ae Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 16:06:20 +0200 Subject: [PATCH 150/356] add is_key_supported --- RecipesPipeline/src/api.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 648a62560..ebd54cefc 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -132,6 +132,13 @@ Check if the plotting package natively supports the seriestype `st`. """ is_seriestype_supported(plt, st) = false +""" + is_key_supported(key) + +Check if the plotting package natively supports the attribute `key` +""" +RecipesBase.is_key_supported(key) = true + """ add_series!(plt, kw) From 280d890c810133a5b665e3efd71b2471bf33a11e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 Apr 2020 16:32:44 +0200 Subject: [PATCH 151/356] move some recipes --- RecipesPipeline/src/RecipesPipeline.jl | 6 +++++- RecipesPipeline/src/recipes.jl | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 RecipesPipeline/src/recipes.jl diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index fd3e56a93..b7eea9a56 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -20,7 +20,10 @@ export SliceIt, pop_kw!, scale_func, inverse_scale_func, - unzip + unzip, + dateformatter, + datetimeformatter, + timeformatter # API export warn_on_recipe_aliases, splittable_attribute, @@ -40,6 +43,7 @@ include("user_recipe.jl") include("type_recipe.jl") include("plot_recipe.jl") include("series_recipe.jl") +include("recipes.jl") """ diff --git a/RecipesPipeline/src/recipes.jl b/RecipesPipeline/src/recipes.jl new file mode 100644 index 000000000..9090425ca --- /dev/null +++ b/RecipesPipeline/src/recipes.jl @@ -0,0 +1,18 @@ +# ------------------------------------------------- +# Dates & Times + +dateformatter(dt) = string(Date(Dates.UTD(dt))) +datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) +timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) + +@recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) +@recipe f(::Type{DateTime}, dt::DateTime) = + (dt -> Dates.value(dt), datetimeformatter) +@recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) +@recipe f(::Type{P}, t::P) where {P<:Dates.Period} = + (t -> Dates.value(t), t -> string(P(t))) + +# ------------------------------------------------- +# Characters + +@recipe f(::Type{<:AbstractChar}, ::AbstractChar) = (string, string) From 95f9cc9993e6b0f4ac2169eaccf78720fa1fe22a Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 5 Apr 2020 16:41:37 +0200 Subject: [PATCH 152/356] add plot to readme --- RecipesPipeline/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index d43281f52..457c63ae3 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -15,7 +15,8 @@ using RecipesBase # Our user-defined data type struct T end -@recipe function plot(::T, n = 1; customcolor = :green) +RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) + seriestype --> :scatter markershape --> :auto # if markershape is unset, make it :auto markercolor := customcolor # force markercolor to be customcolor xrotation --> 45 # if xrotation is unset, make it 45 @@ -24,6 +25,7 @@ struct T end end using Makie, MakieRecipes -recipeplot(T(), 3; markersize = 5) +recipeplot(T(), 3; markersize = 3) ``` +Screenshot 2020-04-05 at 16 36 46 From a879ba584cdab34f4619f56a2f1386c366c37a03 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 Apr 2020 17:24:12 +0200 Subject: [PATCH 153/356] use Dates --- RecipesPipeline/Project.toml | 3 ++- RecipesPipeline/src/RecipesPipeline.jl | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 1c73c52a8..bf3228033 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -4,13 +4,14 @@ authors = ["Michael Krabbe Borregaard "] version = "0.1.0" [deps] +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] -julia = "1" PlotUtils = "0.6.5" RecipesBase = "0.8" +julia = "1" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index b7eea9a56..8be869fa2 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -3,6 +3,7 @@ module RecipesPipeline import RecipesBase import RecipesBase: @recipe, @series, RecipeData, is_explicit import PlotUtils # tryrange and adapted_grid +using Dates export recipe_pipeline! # Plots relies on these: From b76aa846c1684b74df003cbddc4dc43c2eadf7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 20:38:39 +0300 Subject: [PATCH 154/356] Add compat for RecipesBase --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index bf3228033..90431b266 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -10,7 +10,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] PlotUtils = "0.6.5" -RecipesBase = "0.8" +RecipesBase = "0.8, 1.0" julia = "1" [extras] From d7f2fad05342738276b9ef5b9fe59ec8152fc694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Sun, 5 Apr 2020 20:50:28 +0300 Subject: [PATCH 155/356] Fix badges --- RecipesPipeline/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index 457c63ae3..dfb15fb1c 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,7 +1,7 @@ # RecipesPipeline -[![Build Status](https://travis-ci.com/mkborregaard/RecipeUtils.jl.svg?branch=master)](https://travis-ci.com/mkborregaard/RecipeUtils.jl) -[![Codecov](https://codecov.io/gh/mkborregaard/RecipeUtils.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/mkborregaard/RecipeUtils.jl) +[![Build Status](https://travis-ci.com/JuliaPlots/RecipesPipeline.jl.svg?branch=master)](https://travis-ci.com/JuliaPlots/RecipesPipeline.jl) +[![Codecov](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl) #### [WIP] An implementation of the recipe pipeline from Plots This package was factored out of Plots.jl to allow any other plotting package to use the recipe pipeline. In short, the extremely lightweight RecipesBase.jl package can be depended on by any package to define "recipes": plot specifications of user-defined types, as well as custom plot types. RecipePipeline.jl contains the machinery to translate these recipes to full specifications for a plot. From e209aa01bf3ef2ada2c93ddf9e1e6b3d87bc56d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 14:30:00 +0300 Subject: [PATCH 156/356] Plots test --- RecipesPipeline/.travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 7a372f8ff..a67d546be 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -14,3 +14,28 @@ jobs: allow_failures: - julia: nightly fast_finish: true + +addons: + apt: + packages: + - at-spi2-core + - libgtk-3-dev + - xauth + - xvfb + +env: + - GKS_ENCODING="utf8" + +cache: + directories: + - $HOME/.julia/artifacts + +sudo: required + +notifications: + email: true + +script: + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test(Plots)' From f45d4a9e03625b807a22cee5bfc8684ee45e9409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 19:26:16 +0300 Subject: [PATCH 157/356] Fix travis From 28d48fdc43d9fd0ebc5b3020cc8d9b2b056e0ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 19:43:11 +0300 Subject: [PATCH 158/356] Forgot using --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index a67d546be..5645d50b7 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -38,4 +38,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test(Plots)' + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); using Plots; Pkg.test(Plots)' From cdad39924fb9db3f6cc0b9946f5c7417046a0e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Sun, 5 Apr 2020 20:03:33 +0300 Subject: [PATCH 159/356] Update .travis.yml Co-Authored-By: Anshul Singhvi --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 5645d50b7..869460126 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -38,4 +38,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); using Plots; Pkg.test(Plots)' + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test("Plots")' From d64236653e9d281609cf42d181f58d0a1482f859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 20:06:57 +0300 Subject: [PATCH 160/356] Use ds/rewrite --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 869460126..63fc4eadd 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -38,4 +38,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' From 963197473e4a53fc4485b9df8618d71575c6188c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 14:32:30 +0300 Subject: [PATCH 161/356] Try with --project Credit: Fredrik Ekre --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 63fc4eadd..7c33c6698 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -38,4 +38,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' From 7dc6d3d749de1893513cdeb37df693831312863c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 14:45:24 +0300 Subject: [PATCH 162/356] Use latest stable julia version --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 7c33c6698..2cc3a23cc 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - 1.0 + - 1 - nightly notifications: email: false From 519b8fc576dc020338161e6f269d463de53e938e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 16:09:28 +0300 Subject: [PATCH 163/356] Allow failures on MacOS --- RecipesPipeline/.travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 2cc3a23cc..d51eccd5e 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -8,11 +8,11 @@ julia: - nightly notifications: email: false -after_success: - - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' + jobs: allow_failures: - julia: nightly + - os: osx fast_finish: true addons: From fcfb63ee9ad8ce8d4dae2a1e51d9a7d4c88ae32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 16:43:03 +0300 Subject: [PATCH 164/356] Docs deployment --- RecipesPipeline/.github/workflows/docs.yml | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 RecipesPipeline/.github/workflows/docs.yml diff --git a/RecipesPipeline/.github/workflows/docs.yml b/RecipesPipeline/.github/workflows/docs.yml new file mode 100644 index 000000000..d0cff7c65 --- /dev/null +++ b/RecipesPipeline/.github/workflows/docs.yml @@ -0,0 +1,24 @@ +name: Documentation + +on: + push: + branches: + - master + tags: '*' + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@latest + with: + version: 1 + - name: Install dependencies + run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + - name: Build and deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key + run: julia --project=docs/ docs/make.jl From bc20d5403a3fdfa39abf921cfc0262f9205d94b6 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 19:59:56 +0530 Subject: [PATCH 165/356] Literate + enable deploy --- RecipesPipeline/docs/make.jl | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index b1286c72d..480924678 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -1,5 +1,12 @@ using Documenter using RecipesPipeline +using Literate + +# create literate versions of the source files +filepath = joinpath(@__DIR__, "..", "src") +files = joinpath.(filepath, readdir(filepath)) + +Literate.markdown.(files, joinpath(@__DIR__, "src", "generated"); documenter = false) makedocs( sitename = "RecipesPipeline", @@ -12,7 +19,22 @@ makedocs( "Public API" => "api.md", "Recipes" => "recipes.md" ], - "Reference" => "reference.md" + "Reference" => "reference.md", + "Source code" => joinpath.(generated, + [ + "RecipesPipeline.md", + "api.md", + "user_recipe.md", + "plot_recipe.md", + "type_recipe.md", + "series_recipe.md", + "group.md", + "recipes.md", + "series.md" + "group.md", + "utils.md" + ] + ), ], modules = [RecipesPipeline] ) @@ -20,6 +42,7 @@ makedocs( # Documenter can also automatically deploy documentation to gh-pages. # See "Hosting Documentation" and deploydocs() in the Documenter manual # for more information. -#=deploydocs( - repo = "" -)=# +deploydocs( + repo = "https://github.com/JuliaPlots/RecipesPipeline.jl", + push_preview = true +) From bf57349d59a589a92127839901d999144c6d60cb Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:08:06 +0530 Subject: [PATCH 166/356] Update Project.toml --- RecipesPipeline/docs/Project.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecipesPipeline/docs/Project.toml b/RecipesPipeline/docs/Project.toml index dfa65cd10..d06c370df 100644 --- a/RecipesPipeline/docs/Project.toml +++ b/RecipesPipeline/docs/Project.toml @@ -1,2 +1,6 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" + +[compat] +Literate = "2" From 5ca699087d3d168aecb16882b146c9c2a88aa7ee Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:12:00 +0530 Subject: [PATCH 167/356] fix missing comma --- RecipesPipeline/docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index 480924678..6b528c507 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -30,7 +30,7 @@ makedocs( "series_recipe.md", "group.md", "recipes.md", - "series.md" + "series.md", "group.md", "utils.md" ] From 6f834d230b4b964a0426002bb546ee0da5ee7eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 17:51:01 +0300 Subject: [PATCH 168/356] Fix error --- RecipesPipeline/docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index 6b528c507..af40b9e8d 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -20,7 +20,7 @@ makedocs( "Recipes" => "recipes.md" ], "Reference" => "reference.md", - "Source code" => joinpath.(generated, + "Source code" => joinpath.("generated", [ "RecipesPipeline.md", "api.md", From e030088d835355aeacb27c55e0bafa7f4e9e5c52 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:25:14 +0530 Subject: [PATCH 169/356] try fixing repo name --- RecipesPipeline/docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index af40b9e8d..463f89a63 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -43,6 +43,6 @@ makedocs( # See "Hosting Documentation" and deploydocs() in the Documenter manual # for more information. deploydocs( - repo = "https://github.com/JuliaPlots/RecipesPipeline.jl", + repo = "github.com/JuliaPlots/RecipesPipeline.jl", push_preview = true ) From 92ad2c91121424c690c5b70e0d37f31f4a3e1e9a Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:32:16 +0530 Subject: [PATCH 170/356] small change to trigger CI --- RecipesPipeline/docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index 463f89a63..f8c9d9eae 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -9,7 +9,7 @@ files = joinpath.(filepath, readdir(filepath)) Literate.markdown.(files, joinpath(@__DIR__, "src", "generated"); documenter = false) makedocs( - sitename = "RecipesPipeline", + sitename = "RecipesPipeline.jl", format = format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true" ), From 65a77aaee2234eb180e2a0cb1a2b3229a6ad7c1c Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:39:44 +0530 Subject: [PATCH 171/356] play better with Literate --- RecipesPipeline/src/RecipesPipeline.jl | 1 + RecipesPipeline/src/api.jl | 19 ++++++++++++------- RecipesPipeline/src/group.jl | 2 ++ RecipesPipeline/src/plot_recipe.jl | 2 ++ RecipesPipeline/src/recipes.jl | 6 ++++-- RecipesPipeline/src/series.jl | 2 ++ RecipesPipeline/src/series_recipe.jl | 2 ++ RecipesPipeline/src/type_recipe.jl | 2 ++ RecipesPipeline/src/user_recipe.jl | 2 ++ RecipesPipeline/src/utils.jl | 16 +++++++++------- 10 files changed, 38 insertions(+), 16 deletions(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 8be869fa2..949a0cd69 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -1,3 +1,4 @@ +# # RecipesPipeline module RecipesPipeline import RecipesBase diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index ebd54cefc..1795c052c 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -1,4 +1,6 @@ -## Warnings +# # API + +# ## Warnings """ warn_on_recipe_aliases!(plt, plotattributes, recipe_type, args...) @@ -9,7 +11,7 @@ applied to 'args'. `recipe_type` is either `:user`, `:type`, `:plot` or `:series function warn_on_recipe_aliases!(plt, plotattributes, recipe_type, args...) end -## Grouping +# ## Grouping """ splittable_attribute(plt, key, val, len) @@ -34,7 +36,7 @@ split_attribute(plt, key, val::Tuple, indices) = Tuple(split_attribute(key, v, indices) for v in val) -## Preprocessing attributes +# ## Preprocessing attributes """ preprocess_attributes!(plt, plotattributes) @@ -62,7 +64,7 @@ Returns `true` if `attr` is an axis attribute, i.e. it applies to `xattr`, `yatt is_axis_attribute(plt, attr) = false -## User recipes +# ## User recipes """ process_userrecipe!(plt, attributes_list, attributes) @@ -84,7 +86,7 @@ errors, `tryrange` from PlotUtils is used. get_axis_limits(plt, letter) = ErrorException("Axis limits not defined.") -## Plot recipes +# ## Plot recipes """ type_alias(plt, st) @@ -94,7 +96,7 @@ Return the seriestype alias for `st`. type_alias(plt, st) = st -## Plot setup +# ## Plot setup """ plot_setup!(plt, plotattributes, kw_list) @@ -106,7 +108,7 @@ links subplot axes. function plot_setup!(plt, plotattributes, kw_list) end -## Series recipes +# ## Series recipes """ slice_series_attributes!(plt, kw_list, kw) @@ -125,6 +127,7 @@ Returns a `Dict` storing the defaults for series attributes. series_defaults(plt) = Dict{Symbol, Any}() # TODO: Add a more sensible fallback including e.g. path, scatter, ... + """ is_seriestype_supported(plt, st) @@ -139,6 +142,8 @@ Check if the plotting package natively supports the attribute `key` """ RecipesBase.is_key_supported(key) = true +# ## Finalizer + """ add_series!(plt, kw) diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl index ca9d46c5c..79b455841 100644 --- a/RecipesPipeline/src/group.jl +++ b/RecipesPipeline/src/group.jl @@ -1,3 +1,5 @@ +# # Grouping + "A special type that will break up incoming data into groups, and allow for easier creation of grouped plots" mutable struct GroupBy group_labels::Vector # length == numGroups diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 6b7e05c3b..7f52237a0 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -1,3 +1,5 @@ +# # Plot Recipes + """ _process_plotrecipes!(plt, kw_list) diff --git a/RecipesPipeline/src/recipes.jl b/RecipesPipeline/src/recipes.jl index 9090425ca..40c8d2109 100644 --- a/RecipesPipeline/src/recipes.jl +++ b/RecipesPipeline/src/recipes.jl @@ -1,5 +1,7 @@ +# # Default recipes +# Includes stuff from Base/stdlib. # ------------------------------------------------- -# Dates & Times +# ## Dates & Times dateformatter(dt) = string(Date(Dates.UTD(dt))) datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) @@ -13,6 +15,6 @@ timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) (t -> Dates.value(t), t -> string(P(t))) # ------------------------------------------------- -# Characters +# ## Characters @recipe f(::Type{<:AbstractChar}, ::AbstractChar) = (string, string) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index e967fa4c1..3bd86f3a8 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -1,3 +1,5 @@ +# # Series handling + const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} const MaybeNumber = Union{Number, Missing} const MaybeString = Union{AbstractString, Missing} diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index 37bb6a4ce..297f64f09 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -1,3 +1,5 @@ +# # Series recipes + """ _process_seriesrecipes!(plt, kw_list) diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index 527fbae69..61b345661 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -1,3 +1,5 @@ +# # Type Recipes + # this is the default "type recipe"... just pass the object through @recipe f(::Type{T}, v::T) where {T} = v diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 0023474f2..fd1a8df75 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -1,3 +1,5 @@ +# # User Recipes + """ _process_userrecipes(plt, plotattributes, args) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 54862d47c..672154b90 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -1,10 +1,12 @@ +# # Utilities + const AVec = AbstractVector const AMat = AbstractMatrix const KW = Dict{Symbol, Any} const AKW = AbstractDict{Symbol, Any} # -------------------------------- -# DefaultsDict +# ## DefaultsDict # -------------------------------- struct DefaultsDict <: AbstractDict{Symbol, Any} @@ -62,7 +64,7 @@ pop_kw!(d::AKW, k, default) = pop!(d, k, default) # -------------------------------- -# 3D types +# ## 3D types # -------------------------------- abstract type AbstractSurface end @@ -111,7 +113,7 @@ Base.eltype(vol::Volume{T}) where {T} = T # -------------------------------- -# Formatting +# ## Formatting # -------------------------------- "Represents data values with formatting that should apply to the tick labels." @@ -121,7 +123,7 @@ struct Formatted{T} end # ------------------------------- -# 3D seriestypes +# ## 3D seriestypes # ------------------------------- # TODO: Move to RecipesBase? @@ -188,7 +190,7 @@ needs_3d_axes(plotattributes::AbstractDict) = # -------------------------------- -# Scales +# ## Scales # -------------------------------- const SCALE_FUNCTIONS = Dict{Symbol, Function}(:log10 => log10, :log2 => log2, :ln => log) @@ -201,7 +203,7 @@ inverse_scale_func(scale::Symbol) = # -------------------------------- -# Unzip +# ## Unzip # -------------------------------- for i in 2:4 @@ -213,7 +215,7 @@ end # -------------------------------- -# Map functions on vectors +# ## Map functions on vectors # -------------------------------- _map_funcs(f::Function, u::AVec) = map(f, u) From 7c7370a4c38cb59eae3684a434bd4c554ed586d5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 6 Apr 2020 17:16:32 +0200 Subject: [PATCH 172/356] allow type recipes for `Number`s in arrays and surfaces --- RecipesPipeline/src/type_recipe.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index 527fbae69..df0f9e951 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -46,7 +46,7 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) end # special handling for Surface... need to properly unwrap and re-wrap -_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:DataPoint}}) = v +_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:Union{AbstractFloat, Integer, Missing}}}) = v function _apply_type_recipe(plotattributes, v::Surface) ret = _apply_type_recipe(plotattributes, v.surf) if typeof(ret) <: Formatted @@ -57,7 +57,7 @@ function _apply_type_recipe(plotattributes, v::Surface) end # don't do anything for datapoints or nothing -_apply_type_recipe(plotattributes, v::AbstractArray{<:DataPoint}, letter) = v +_apply_type_recipe(plotattributes, v::AbstractArray{<:Union{AbstractFloat, Integer, Missing}}, letter) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v # axis args before type recipes should still be mapped to all axes From 6f03d5d54484a19e88e7a17de440b098ba2d95b8 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 6 Apr 2020 20:46:33 +0530 Subject: [PATCH 173/356] small fixes --- RecipesPipeline/src/series_recipe.jl | 2 +- RecipesPipeline/src/user_recipe.jl | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index 297f64f09..844a402b2 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -1,4 +1,4 @@ -# # Series recipes +# # Series Recipes """ _process_seriesrecipes!(plt, kw_list) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index fd1a8df75..713026e07 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -11,12 +11,13 @@ processed series. When all arguments are processed return the series `Dict`. function _process_userrecipes!(plt, plotattributes, args) still_to_process = _recipedata_vector(plt, plotattributes, args) - # for plotting recipes, swap out the args and update the parameter dictionary - # we are keeping a stack of series that still need to be processed. - # each pass through the loop, we pop one off and apply the recipe. - # the recipe will return a list a Series objects... the ones that are - # finished (no more args) get added to the kw_list, the ones that are not + # For plotting recipes, we swap out the args and update the parameter dictionary. We are keeping a stack of series that still need to be processed. + # + # On each pass through the loop, we pop one off and apply the recipe. + # the recipe will return a list a Series objects. The ones that are + # finished (no more args) get added to the `kw_list`, and the ones that are not # are placed on top of the stack and are then processed further. + kw_list = KW[] while !isempty(still_to_process) # grab the first in line to be processed and either add it to the kw_list or From 5e0ebc51ece5d5ecfd90c15d9caae4372f8ce459 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 6 Apr 2020 17:27:07 +0200 Subject: [PATCH 174/356] skip maybestrings --- RecipesPipeline/src/type_recipe.jl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index df0f9e951..bbb7e0fcf 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -46,7 +46,11 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) end # special handling for Surface... need to properly unwrap and re-wrap -_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:Union{AbstractFloat, Integer, Missing}}}) = v +_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:MaybeString}}) = v +_apply_type_recipe( + plotattributes, + v::Surface{<:AMat{<:Union{AbstractFloat, Integer, Missing}}}, +) = v function _apply_type_recipe(plotattributes, v::Surface) ret = _apply_type_recipe(plotattributes, v.surf) if typeof(ret) <: Formatted @@ -57,7 +61,12 @@ function _apply_type_recipe(plotattributes, v::Surface) end # don't do anything for datapoints or nothing -_apply_type_recipe(plotattributes, v::AbstractArray{<:Union{AbstractFloat, Integer, Missing}}, letter) = v +_apply_type_recipe(plotattributes, v::AbstractArray{<:MaybeString}, letter) = v +_apply_type_recipe( + plotattributes, + v::AbstractArray{<:Union{AbstractFloat, Integer, Missing}}, + letter, +) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v # axis args before type recipes should still be mapped to all axes From 38309b9802657718b24ddaca354fe4a55aa2bf0e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 6 Apr 2020 17:38:58 +0200 Subject: [PATCH 175/356] fix ambiguity --- RecipesPipeline/src/type_recipe.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index bbb7e0fcf..e3903e2d0 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -46,10 +46,9 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) end # special handling for Surface... need to properly unwrap and re-wrap -_apply_type_recipe(plotattributes, v::Surface{<:AMat{<:MaybeString}}) = v _apply_type_recipe( plotattributes, - v::Surface{<:AMat{<:Union{AbstractFloat, Integer, Missing}}}, + v::Surface{<:AMat{<:Union{AbstractFloat, Integer, AbstractString, Missing}}}, ) = v function _apply_type_recipe(plotattributes, v::Surface) ret = _apply_type_recipe(plotattributes, v.surf) @@ -61,10 +60,9 @@ function _apply_type_recipe(plotattributes, v::Surface) end # don't do anything for datapoints or nothing -_apply_type_recipe(plotattributes, v::AbstractArray{<:MaybeString}, letter) = v _apply_type_recipe( plotattributes, - v::AbstractArray{<:Union{AbstractFloat, Integer, Missing}}, + v::AbstractArray{<:Union{AbstractFloat, Integer, AbstractString, Missing}}, letter, ) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v From 40ab457c352026ac1ed6fabf560625ab8e4da509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 18:53:27 +0300 Subject: [PATCH 176/356] Add badge --- RecipesPipeline/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index dfb15fb1c..49995cb90 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,6 +1,12 @@ # RecipesPipeline +[travis-img]: https://img.shields.io/travis/JuliaPlots/RecipesPipeline.jl?logo=travis +[travis-url]: https://travis-ci.org/JuliaPlots/RecipesPipeline.jl -[![Build Status](https://travis-ci.com/JuliaPlots/RecipesPipeline.jl.svg?branch=master)](https://travis-ci.com/JuliaPlots/RecipesPipeline.jl) +[docs-img]: https://img.shields.io/badge/docs-dev-blue.svg +[docs-url]: http://docs.juliaplots.org/RecipesPipeline,jl/dev/ + +[![][travis-img]][travis-url] +[![][docs-img]][docs-url] [![Codecov](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl) #### [WIP] An implementation of the recipe pipeline from Plots From 9d5d191fd6fd418cba0c7a2b0873309a5c31ffa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Mon, 6 Apr 2020 19:22:04 +0300 Subject: [PATCH 177/356] Fix build badge link --- RecipesPipeline/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index 49995cb90..a8a5cc0d2 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,6 +1,6 @@ # RecipesPipeline -[travis-img]: https://img.shields.io/travis/JuliaPlots/RecipesPipeline.jl?logo=travis -[travis-url]: https://travis-ci.org/JuliaPlots/RecipesPipeline.jl +[travis-img]: https://img.shields.io/travis/com/JuliaPlots/RecipesPipeline.jl?style=flat +[travis-url]: https://travis-ci.com/JuliaPlots/RecipesPipeline.jl [docs-img]: https://img.shields.io/badge/docs-dev-blue.svg [docs-url]: http://docs.juliaplots.org/RecipesPipeline,jl/dev/ From 3dd7fb67a6484bb3791076ff24324363d0a1a4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Mon, 6 Apr 2020 19:41:54 +0300 Subject: [PATCH 178/356] Show status only for master branch --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index a8a5cc0d2..a1851c95e 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -1,5 +1,5 @@ # RecipesPipeline -[travis-img]: https://img.shields.io/travis/com/JuliaPlots/RecipesPipeline.jl?style=flat +[travis-img]: https://travis-ci.com/JuliaPlots/RecipesPipeline.jl.svg?branch=master [travis-url]: https://travis-ci.com/JuliaPlots/RecipesPipeline.jl [docs-img]: https://img.shields.io/badge/docs-dev-blue.svg From 159df77da8696e93762d6cdfe7f93037cea69a1b Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Tue, 7 Apr 2020 14:24:01 +0530 Subject: [PATCH 179/356] Fix README docs link --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index a1851c95e..84e8ac240 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -3,7 +3,7 @@ [travis-url]: https://travis-ci.com/JuliaPlots/RecipesPipeline.jl [docs-img]: https://img.shields.io/badge/docs-dev-blue.svg -[docs-url]: http://docs.juliaplots.org/RecipesPipeline,jl/dev/ +[docs-url]: http://docs.juliaplots.org/RecipesPipeline.jl/dev/ [![][travis-img]][travis-url] [![][docs-img]][docs-url] From 3ced4a8e0d2318e29952f213b2b3ffff1ad8745e Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Tue, 7 Apr 2020 14:24:56 +0530 Subject: [PATCH 180/356] remove subdomain --- RecipesPipeline/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index 84e8ac240..e2deb052d 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -3,7 +3,7 @@ [travis-url]: https://travis-ci.com/JuliaPlots/RecipesPipeline.jl [docs-img]: https://img.shields.io/badge/docs-dev-blue.svg -[docs-url]: http://docs.juliaplots.org/RecipesPipeline.jl/dev/ +[docs-url]: http://juliaplots.org/RecipesPipeline.jl/dev/ [![][travis-img]][travis-url] [![][docs-img]][docs-url] From c7bc267e7ec4a071194a800327300a2c19ca537c Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Wed, 8 Apr 2020 08:17:16 +0530 Subject: [PATCH 181/356] Create TagBot.yml --- RecipesPipeline/.github/workflows/TagBot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 RecipesPipeline/.github/workflows/TagBot.yml diff --git a/RecipesPipeline/.github/workflows/TagBot.yml b/RecipesPipeline/.github/workflows/TagBot.yml new file mode 100644 index 000000000..f8fd014ef --- /dev/null +++ b/RecipesPipeline/.github/workflows/TagBot.yml @@ -0,0 +1,12 @@ +name: TagBot +on: + schedule: + - cron: 0 * * * * +jobs: + TagBot: + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} From 39217367e4b86604db2a06e7243a8b8bdd0be8d2 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 10 Apr 2020 12:41:04 +0200 Subject: [PATCH 182/356] fix surface type recipe --- RecipesPipeline/src/type_recipe.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index 45e59c90e..3f1b89cfb 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -51,13 +51,14 @@ end _apply_type_recipe( plotattributes, v::Surface{<:AMat{<:Union{AbstractFloat, Integer, AbstractString, Missing}}}, + letter, ) = v -function _apply_type_recipe(plotattributes, v::Surface) - ret = _apply_type_recipe(plotattributes, v.surf) +function _apply_type_recipe(plotattributes, v::Surface, letter) + ret = _apply_type_recipe(plotattributes, v.surf, letter) if typeof(ret) <: Formatted Formatted(Surface(ret.data), ret.formatter) else - Surface(ret.data) + Surface(ret) end end From 9bac5ee8cafb6f002532e6b10a94d87da5d247ac Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 10 Apr 2020 12:43:36 +0200 Subject: [PATCH 183/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 90431b266..f90bd0b4a 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.0" +version = "0.1.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From e49eea4b9c2abfaebb9b9c9cc1caf2beb78e3df1 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 10 Apr 2020 22:05:00 +0200 Subject: [PATCH 184/356] fix error for grouping --- RecipesPipeline/src/api.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 1795c052c..32490ec77 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -22,7 +22,7 @@ group provided as a vector of length `len`, `false` otherwise. splittable_attribute(plt, key, val, len) = false splittable_attribute(plt, key, val::AbstractArray, len) = !(key in (:group, :color_palette)) && length(axes(val, 1)) == len -splittable_attribute(plt, key, val::Tuple, n) = all(splittable_attribute.(key, val, len)) +splittable_attribute(plt, key, val::Tuple, len) = all(splittable_attribute.(key, val, len)) """ From fa547656e3e6f06ca6b844aa997e0ead30625103 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 10 Apr 2020 22:05:25 +0200 Subject: [PATCH 185/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index f90bd0b4a..c8d37b247 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.1" +version = "0.1.2" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 63d623247722115755473c5288894ea02a48ff35 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 11 Apr 2020 08:45:25 +0200 Subject: [PATCH 186/356] further grouping fixes --- RecipesPipeline/src/api.jl | 3 ++- RecipesPipeline/src/group.jl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 32490ec77..b8379b9f7 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -22,7 +22,8 @@ group provided as a vector of length `len`, `false` otherwise. splittable_attribute(plt, key, val, len) = false splittable_attribute(plt, key, val::AbstractArray, len) = !(key in (:group, :color_palette)) && length(axes(val, 1)) == len -splittable_attribute(plt, key, val::Tuple, len) = all(splittable_attribute.(key, val, len)) +splittable_attribute(plt, key, val::Tuple, len) = + all(v -> splittable_attribute(plt, key, v, len), val) """ diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl index 79b455841..3e600ef98 100644 --- a/RecipesPipeline/src/group.jl +++ b/RecipesPipeline/src/group.jl @@ -111,7 +111,7 @@ group_as_matrix(t) = false x_u = unique(sort(x)) x_ind = Dict(zip(x_u, eachindex(x_u))) for (key, val) in plotattributes - if splittable_kw(key, val, group_length) + if splittable_kw(plt, key, val, group_length) :($key) := groupedvec2mat(x_ind, x, val, groupby) end end From 295dc6058d9177e32145a4ec5cfa981fd414c2f5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 11 Apr 2020 08:45:53 +0200 Subject: [PATCH 187/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index c8d37b247..8a07b29b7 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.2" +version = "0.1.3" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 9bf00209699d6597d62267c386640a76a986d95e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 11 Apr 2020 12:09:33 +0200 Subject: [PATCH 188/356] fix plotting functions --- RecipesPipeline/src/api.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index b8379b9f7..1ec8f7291 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -84,7 +84,7 @@ end Get the limits for the axis specified by `letter` (`:x`, `:y` or `:z`) in `plt`. If it errors, `tryrange` from PlotUtils is used. """ -get_axis_limits(plt, letter) = ErrorException("Axis limits not defined.") +get_axis_limits(plt, letter) = throw(ErrorException("Axis limits not defined.")) # ## Plot recipes From ae0c18dd5193249ae4d63b2254679a9692d50c42 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 11 Apr 2020 12:10:13 +0200 Subject: [PATCH 189/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 8a07b29b7..17d5f52fd 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.3" +version = "0.1.4" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 681a5ea34c6319fc1582128d28c48faab9ccafe9 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 11 Apr 2020 12:48:43 +0200 Subject: [PATCH 190/356] downgrade version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 17d5f52fd..8a07b29b7 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.4" +version = "0.1.3" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 08eae2cc74d183d7625b8b68719277cbcf1fbfc1 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 20 Apr 2020 00:14:17 +0200 Subject: [PATCH 191/356] fix plotting rowvector of functions --- RecipesPipeline/src/user_recipe.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 713026e07..32a43bba1 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -287,7 +287,7 @@ end end @recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where {F <: Function} xscale, yscale = [get(plotattributes, sym, :identity) for sym in (:xscale, :yscale)] - unzip(_scaled_adapted_grid.(fs, xscale, yscale, xmin, xmax)) + unzip(_scaled_adapted_grid.(vec(fs), xscale, yscale, xmin, xmax)) end @recipe f( fx::FuncOrFuncs{F}, From b5e9ce215b43645e36bb6644d183a34d48bac149 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 20 Apr 2020 00:14:46 +0200 Subject: [PATCH 192/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 8a07b29b7..17d5f52fd 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.3" +version = "0.1.4" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 8f26a518ec82f2ac3ee1e344acf1472c6437fc14 Mon Sep 17 00:00:00 2001 From: Lirimy <31124605+Lirimy@users.noreply.github.com> Date: Wed, 22 Apr 2020 16:40:56 +0900 Subject: [PATCH 193/356] support parametric type in `@userplot` --- RecipesBase/src/RecipesBase.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 36c9c54b6..b5bd97a40 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -345,7 +345,7 @@ function _userplot(expr::Expr) error("Must call userplot on a [mutable] struct expression. Got: $expr") end - typename = expr.args[2] + typename = gettypename(expr.args[2]) funcname = Symbol(lowercase(string(typename))) funcname2 = Symbol(funcname, "!") @@ -365,6 +365,13 @@ function _userplot(sym::Symbol) end)) end +gettypename(sym::Symbol) = sym + +function gettypename(expr::Expr) + expr.head == :curly || @error "Unexpected struct name: $expr" + expr.args[1] +end + #---------------------------------------------------------------------------- """ From 460dc25865664e0e2fa12835b5509a00246f6d2d Mon Sep 17 00:00:00 2001 From: Lirimy <31124605+Lirimy@users.noreply.github.com> Date: Thu, 23 Apr 2020 22:31:42 +0900 Subject: [PATCH 194/356] add docs for parametric type in `@userplot` --- RecipesBase/docs/src/types.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RecipesBase/docs/src/types.md b/RecipesBase/docs/src/types.md index 844c3fe26..bdec52bcc 100644 --- a/RecipesBase/docs/src/types.md +++ b/RecipesBase/docs/src/types.md @@ -116,6 +116,15 @@ export myplot, myplot! myplot(args...; kw...) = plot(MyPlot(args); kw...) myplot!(args...; kw...) = plot!(MyPlot(args); kw...) ``` + +To check `args` type, define a struct with type parameters. + +``` +@userplot struct MyPlot{T<:Tuple{AbstractVector}} + args::T +end +``` + We can use this to define a user recipe for a pie plot. ```@example types # defines mutable struct `UserPie` and sets shorthands `userpie` and `userpie!` From a3594c5e74d40fe455169a57a08a91f1d9eafc39 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 23 Apr 2020 15:48:25 +0200 Subject: [PATCH 195/356] bump version --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index e15d69112..fc64fc186 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.0.0" +version = "1.0.1" [compat] julia = "1" From 2058f72bb14d0f0055b26a85042c0b633bd18beb Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 23 Apr 2020 19:31:26 +0200 Subject: [PATCH 196/356] fix grouping --- RecipesPipeline/src/group.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl index 3e600ef98..4e0c18d1f 100644 --- a/RecipesPipeline/src/group.jl +++ b/RecipesPipeline/src/group.jl @@ -111,7 +111,7 @@ group_as_matrix(t) = false x_u = unique(sort(x)) x_ind = Dict(zip(x_u, eachindex(x_u))) for (key, val) in plotattributes - if splittable_kw(plt, key, val, group_length) + if splittable_attribute(plt, key, val, group_length) :($key) := groupedvec2mat(x_ind, x, val, groupby) end end From 1ea081cb83dd80e8883dcb1b139ddc6b995bf393 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 23 Apr 2020 19:31:50 +0200 Subject: [PATCH 197/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 17d5f52fd..bef952186 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.4" +version = "0.1.5" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From b1e64094d43f6b2bd6d73747365c9db5ba8702d9 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 20 Apr 2020 00:06:17 +0200 Subject: [PATCH 198/356] bump PlotUtils compat --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index bef952186..508c858d5 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -9,7 +9,7 @@ PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] -PlotUtils = "0.6.5" +PlotUtils = "0.6.5, 1" RecipesBase = "0.8, 1.0" julia = "1" From 0ff3da15d33833fb9b8f366510fc56220799437f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 24 Apr 2020 20:57:03 +0200 Subject: [PATCH 199/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 508c858d5..d3fb5c1cb 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.5" +version = "0.1.6" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From a1afecdcbed624aace614624292393347ee85fdd Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 28 Apr 2020 21:50:05 +0200 Subject: [PATCH 200/356] add zulip chat link to readme [skip ci] --- RecipesBase/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index aeedf1195..a92729947 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -3,6 +3,7 @@ [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaPlots.github.io/RecipesBase.jl/stable) [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaPlots.github.io/RecipesBase.jl/dev) [![Build Status](https://travis-ci.org/JuliaPlots/RecipesBase.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/RecipesBase.jl) +[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots) ### Author: Thomas Breloff (@tbreloff) From ca3a7c67ac793c19848134958dd82c21a424af21 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 28 Apr 2020 21:57:55 +0200 Subject: [PATCH 201/356] add zulip link [skip ci] --- RecipesPipeline/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index e2deb052d..80297d6ec 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -8,6 +8,7 @@ [![][travis-img]][travis-url] [![][docs-img]][docs-url] [![Codecov](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl) +[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots) #### [WIP] An implementation of the recipe pipeline from Plots This package was factored out of Plots.jl to allow any other plotting package to use the recipe pipeline. In short, the extremely lightweight RecipesBase.jl package can be depended on by any package to define "recipes": plot specifications of user-defined types, as well as custom plot types. RecipePipeline.jl contains the machinery to translate these recipes to full specifications for a plot. From 966a1f0aa76999f924b97af1475edfbf3e4bd9ae Mon Sep 17 00:00:00 2001 From: mtsch Date: Thu, 30 Apr 2020 11:51:10 +0200 Subject: [PATCH 202/356] Fix typo in docs `AbstractArry` -> `AbstractArray` --- RecipesBase/docs/src/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/docs/src/types.md b/RecipesBase/docs/src/types.md index bdec52bcc..c69c96f7e 100644 --- a/RecipesBase/docs/src/types.md +++ b/RecipesBase/docs/src/types.md @@ -50,7 +50,7 @@ There are four main types of recipes which are determined by the signature of th !!! compat With RecipesBase 1.0 type recipes of the form ```julia - @recipe function f(::Type{T}, val::T) where T <: AbstractArry{MyType} + @recipe function f(::Type{T}, val::T) where T <: AbstractArray{MyType} ``` for `AbstractArray`s of custom types are supported too. From 824f74aafb7aad3a347994856c45e94a3fd9f255 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 7 May 2020 16:39:36 +0200 Subject: [PATCH 203/356] add hook after series decomposition (#52) * add process_sliced_series_attributes! * export process_slice_series_attrributes! * remove `kw` --- RecipesPipeline/src/RecipesPipeline.jl | 3 ++- RecipesPipeline/src/api.jl | 6 ++++++ RecipesPipeline/src/series_recipe.jl | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 949a0cd69..18d9086e5 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -35,7 +35,8 @@ export warn_on_recipe_aliases, is_axis_attribute, type_alias, plot_setup!, - slice_series_attributes! + slice_series_attributes!, + process_sliced_series_attributes! include("api.jl") include("utils.jl") diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 1ec8f7291..4ec1f659e 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -119,6 +119,12 @@ current series. """ function slice_series_attributes!(plt, kw_list, kw) end +""" + process_sliced_series_attributes!(plt, kw_list) + +All series attributes are now properly resolved. Any change of the `kw_list` before the application of recipes must come here. +""" +function process_sliced_series_attributes!(plt, kw_list) end """ series_defaults(plt) diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index 844a402b2..a56f66e91 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -10,7 +10,9 @@ function _process_seriesrecipes!(plt, kw_list) # in series attributes given as vector with one element per series, # select the value for current series slice_series_attributes!(plt, kw_list, kw) - + end + process_sliced_series_attributes!(plt, kw_list) + for kw in kw_list series_attr = DefaultsDict(kw, series_defaults(plt)) # now we have a fully specified series, with colors chosen. we must recursively # handle series recipes, which dispatch on seriestype. If a backend does not From 116abb6402f352d4fa5a2412122ade60bb9fc623 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 7 May 2020 16:44:09 +0200 Subject: [PATCH 204/356] Update Project.toml [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index d3fb5c1cb..92311be51 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.6" +version = "0.1.7" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 1c4d20a0b73b27a0a7ddfb3da01504fdc8d2caab Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 2 Apr 2020 15:17:17 +0530 Subject: [PATCH 205/356] Initial pass at CI --- RecipesPipeline/.github/workflows/CI.yml | 54 ++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 RecipesPipeline/.github/workflows/CI.yml diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml new file mode 100644 index 000000000..db2dfce9d --- /dev/null +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -0,0 +1,54 @@ +name: CI + +on: [push] + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1.4] + julia-arch: [x64] + os: [ubuntu-latest, macOS-latest] + fail-fast: false + + steps: + - uses: actions/checkout@v1.0.0 + + - name: Set up Julia + uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - name: Add package versions + run: julia --project=. -e 'using Pkg; pkg"add Plots#mkb/recipeutils AbstractPlotting CairoMakie#master"' + + - name: Run tests + uses: julia-actions/julia-runtest@master + + - name: Upload recordings + uses: actions/upload-artifact@v1.0.0 + with: + name: Recordings + path: ./test/test_recordings + if: always() + + - name: Upload diffs + uses: actions/upload-artifact@v1.0.0 + with: + name: Recordings + path: ./test/tested_different + if: always() + + - name: Cache artifacts + uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + if: always() From 2c8b5e32d82e60dfd575539526246ba03bcb39b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 17:41:55 +0300 Subject: [PATCH 206/356] Add script from Plots --- RecipesPipeline/.travis.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index d51eccd5e..1bbb22f93 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -2,18 +2,14 @@ language: julia os: - linux - - osx + # - osx julia: - 1 - nightly -notifications: - email: false -jobs: +matrix: allow_failures: - - julia: nightly - - os: osx - fast_finish: true + - julia: nightly addons: apt: @@ -31,6 +27,11 @@ cache: - $HOME/.julia/artifacts sudo: required +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi + - julia -e 'using Pkg; pkg"add Plots"'; + - PLOTSPATH=`julia -e 'using Plots; pathof(Plots)'` + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then .$PLOTSPATH/test/install_wkhtmltoimage.sh ; fi notifications: email: true @@ -38,4 +39,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD -e 'using Pkg; Pkg.build(); Pkg.test(Plots)' From 42019024e48b9c5717a9f0d95f22050ffe890436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 17:42:21 +0300 Subject: [PATCH 207/356] Update to MakieRecipes --- RecipesPipeline/.github/workflows/CI.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index db2dfce9d..56ec9a348 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -14,14 +14,14 @@ jobs: steps: - uses: actions/checkout@v1.0.0 - + - name: Set up Julia uses: julia-actions/setup-julia@latest with: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=. -e 'using Pkg; pkg"add Plots#mkb/recipeutils AbstractPlotting CairoMakie#master"' + run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl AbstractPlotting CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master @@ -39,7 +39,7 @@ jobs: name: Recordings path: ./test/tested_different if: always() - + - name: Cache artifacts uses: actions/cache@v1 env: From e301c1eaeb11818c84ce87332a8ff77f8cf9d543 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Sun, 5 Apr 2020 20:33:42 +0530 Subject: [PATCH 208/356] comment out artifact uploads --- RecipesPipeline/.github/workflows/CI.yml | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 56ec9a348..c3c4d5580 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -26,19 +26,19 @@ jobs: - name: Run tests uses: julia-actions/julia-runtest@master - - name: Upload recordings - uses: actions/upload-artifact@v1.0.0 - with: - name: Recordings - path: ./test/test_recordings - if: always() - - - name: Upload diffs - uses: actions/upload-artifact@v1.0.0 - with: - name: Recordings - path: ./test/tested_different - if: always() +# - name: Upload recordings +# uses: actions/upload-artifact@v1.0.0 +# with: +# name: Recordings +# path: ./test/test_recordings +# if: always() +# +# - name: Upload diffs +# uses: actions/upload-artifact@v1.0.0 +# with: +# name: Recordings +# path: ./test/tested_different +# if: always() - name: Cache artifacts uses: actions/cache@v1 From 977946c01a8b38f5840e40d81e0e52835ed6e01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 18:12:00 +0300 Subject: [PATCH 209/356] Plots test --- RecipesPipeline/.travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 1bbb22f93..ed552fce8 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -27,11 +27,6 @@ cache: - $HOME/.julia/artifacts sudo: required -before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi - - julia -e 'using Pkg; pkg"add Plots"'; - - PLOTSPATH=`julia -e 'using Plots; pathof(Plots)'` - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then .$PLOTSPATH/test/install_wkhtmltoimage.sh ; fi notifications: email: true @@ -39,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; Pkg.build(); Pkg.test(Plots)' + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test(Plots)' From a63793a3706a31cd8b6693bb4e8d234c67882566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 19:02:55 +0300 Subject: [PATCH 210/356] CairoMakie tests --- RecipesPipeline/.github/workflows/CI.yml | 4 +- RecipesPipeline/Project.toml | 9 +++- RecipesPipeline/test/makie.jl | 55 ++++++++++++++++++++++++ RecipesPipeline/test/runtests.jl | 2 +- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 RecipesPipeline/test/makie.jl diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index c3c4d5580..b1272c26c 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl AbstractPlotting CairoMakie#master"' + run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master @@ -32,7 +32,7 @@ jobs: # name: Recordings # path: ./test/test_recordings # if: always() -# +# # - name: Upload diffs # uses: actions/upload-artifact@v1.0.0 # with: diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 92311be51..c1b3131ab 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -14,7 +14,14 @@ RecipesBase = "0.8, 1.0" julia = "1" [extras] +AbstractPlotting = "537997a7-5e4e-5d89-9595-2241ea00577e" +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" +MakieRecipes = "3c562d8e-4afa-4f1c-99bf-ad54af2b207f" +MarketData = "945b72a4-3b13-509d-9b46-1525bb5c06de" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e" [targets] -test = ["Test"] +test = ["Test", "AbstractPlotting", "CairoMakie", "DifferentialEquations", + "MakieRecipes", "MarketData", "TimeSeries"] diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl new file mode 100644 index 000000000..30bf109d4 --- /dev/null +++ b/RecipesPipeline/test/makie.jl @@ -0,0 +1,55 @@ +using AbstractPlotting, CairoMakie +using MakieRecipes +using MakieRecipes.RecipesBase +using DifferentialEquations, MarketData, TimeSeries + +sc = Scene() +# # The simplest example model +struct T end +RecipesBase.@recipe function plot(::T, n = 1) + markershape --> :auto # if markershape is unset, make it :auto + markercolor := :green # force markercolor to be customcolor + xrotation --> 45 # if xrotation is unset, make it 45 + zrotation --> 90 # if zrotation is unset, make it 90 + rand(10,n) # return the arguments (input data) for the next recipe +end + +@test_nowarn recipeplot(T(); seriestype = :path) + +RecipesBase.is_key_supported(::Symbol) = true +# AbstractPlotting.scatter!(sc, rand(10)) + +sc = Scene() +@test_nowarn recipeplot!(sc, rand(10, 2); seriestype = :scatter) +@test_nowarn recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) + +f(u,p,t) = 1.01.*u +u0 = [1/2, 1] +tspan = (0.0,1.0) +prob = ODEProblem(f,u0,tspan) +sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) +@test_nowarn recipeplot(sol) + +A = [1. 0 0 -5 + 4 -2 4 -3 + -4 0 0 1 + 5 -2 2 3] +u0 = rand(4,2) +tspan = (0.0,1.0) +f(u,p,t) = A*u +prob = ODEProblem(f,u0,tspan) +sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) +@test_nowarn recipeplot(sol) + +f(du,u,p,t) = (du .= u) +g(du,u,p,t) = (du .= u) +u0 = rand(4,2) +W = WienerProcess(0.0,0.0,0.0) +prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) +sol = solve(prob,SRIW1()) +@test_nowarn recipeplot(sol) + +@test_nowarn recipeplot(AbstractPlotting.peaks(); seriestype = :surface, cgrad = :inferno) +@test_nowarn recipeplot(AbstractPlotting.peaks(); seriestype = :heatmap, cgrad = :RdYlBu) +# Timeseries with market data +@test_nowarn recipeplot(MarketData.ohlc; seriestype = :path) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 6c656152e..7fee2809b 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -2,5 +2,5 @@ using RecipesPipeline using Test @testset "RecipesPipeline.jl" begin - # Write your own tests here. + @testset "Makie integration" begin include("makie.jl") end end From ae0d0e7475cfb3aaa68c37d511b27fab6f8418b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 19:43:11 +0300 Subject: [PATCH 211/356] Forgot using --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index ed552fce8..c494b75f5 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test(Plots)' + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); using Plots; Pkg.test(Plots)' From ee0d0e7f42ee9b30628385967899d111b0c54118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Sun, 5 Apr 2020 20:03:33 +0300 Subject: [PATCH 212/356] Update .travis.yml Co-Authored-By: Anshul Singhvi --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index c494b75f5..7db0b6570 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); using Plots; Pkg.test(Plots)' + - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test("Plots")' From 1f83b42751bf68470cb923d61d4687c8c3f527b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 20:06:57 +0300 Subject: [PATCH 213/356] Use ds/rewrite --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 7db0b6570..bf1be78a5 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' From 07719627bb6d0b4b35056a8a2202e8426e5fc573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 20:28:29 +0300 Subject: [PATCH 214/356] Try with --project --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index bf1be78a5..1fd7f2b58 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD --project -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' From b6adae2769a47f36bc62b1d90143b5ac2a544ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Sun, 5 Apr 2020 23:41:32 +0300 Subject: [PATCH 215/356] Another try Credit: Fredrik Ekre --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index 1fd7f2b58..d12434521 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD --project -e 'using Pkg; pkg"add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' From 2bd13b2fad82b6254cca904849a48cbd738bf897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 11:06:11 +0300 Subject: [PATCH 216/356] Import examples from MakieRecipes --- RecipesPipeline/Project.toml | 11 ++++-- RecipesPipeline/test/makie.jl | 70 ++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index c1b3131ab..880284837 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -16,12 +16,17 @@ julia = "1" [extras] AbstractPlotting = "537997a7-5e4e-5d89-9595-2241ea00577e" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" -DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" +OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" +DiffEqNoiseProcess = "77a26b50-5914-5dd7-bc55-306e6241c503" MakieRecipes = "3c562d8e-4afa-4f1c-99bf-ad54af2b207f" MarketData = "945b72a4-3b13-509d-9b46-1525bb5c06de" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e" +Phylo = "aea672f4-3940-5932-aa44-993d1c3ff149" +GraphRecipes = "bd48cda9-67a9-57be-86fa-5b3c104eda73" [targets] -test = ["Test", "AbstractPlotting", "CairoMakie", "DifferentialEquations", - "MakieRecipes", "MarketData", "TimeSeries"] +test = ["Test", "AbstractPlotting", "CairoMakie", "OrdinaryDiffEq", + "StochasticDiffEq", "DiffEqNoiseProcess", + "MakieRecipes", "MarketData", "TimeSeries", "Phylo", "GraphRecipes"] diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl index 30bf109d4..5d61d0e22 100644 --- a/RecipesPipeline/test/makie.jl +++ b/RecipesPipeline/test/makie.jl @@ -1,14 +1,15 @@ using AbstractPlotting, CairoMakie using MakieRecipes using MakieRecipes.RecipesBase -using DifferentialEquations, MarketData, TimeSeries +using MarketData, TimeSeries + +# ## The simplest example model -sc = Scene() -# # The simplest example model struct T end -RecipesBase.@recipe function plot(::T, n = 1) + +RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) markershape --> :auto # if markershape is unset, make it :auto - markercolor := :green # force markercolor to be customcolor + markercolor := customcolor # force markercolor to be customcolor xrotation --> 45 # if xrotation is unset, make it 45 zrotation --> 90 # if zrotation is unset, make it 90 rand(10,n) # return the arguments (input data) for the next recipe @@ -16,13 +17,22 @@ end @test_nowarn recipeplot(T(); seriestype = :path) -RecipesBase.is_key_supported(::Symbol) = true -# AbstractPlotting.scatter!(sc, rand(10)) +# ## Testing out series decomposition sc = Scene() @test_nowarn recipeplot!(sc, rand(10, 2); seriestype = :scatter) @test_nowarn recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) +# ## Distributions + +# ### + +# ## Differential Equations + +using OrdinaryDiffEq, StochasticDiffEq, DiffEqNoiseProcess + +# ### A simple exponential growth model + f(u,p,t) = 1.01.*u u0 = [1/2, 1] tspan = (0.0,1.0) @@ -30,6 +40,8 @@ prob = ODEProblem(f,u0,tspan) sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) @test_nowarn recipeplot(sol) +# ### Matrix DiffEq + A = [1. 0 0 -5 4 -2 4 -3 -4 0 0 1 @@ -41,15 +53,55 @@ prob = ODEProblem(f,u0,tspan) sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) @test_nowarn recipeplot(sol) +# ### Stochastic DiffEq + f(du,u,p,t) = (du .= u) g(du,u,p,t) = (du .= u) u0 = rand(4,2) + W = WienerProcess(0.0,0.0,0.0) prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) sol = solve(prob,SRIW1()) @test_nowarn recipeplot(sol) -@test_nowarn recipeplot(AbstractPlotting.peaks(); seriestype = :surface, cgrad = :inferno) -@test_nowarn recipeplot(AbstractPlotting.peaks(); seriestype = :heatmap, cgrad = :RdYlBu) +# ## Phylogenetic tree +using Phylo +assetpath = joinpath(dirname(pathof(MakieRecipes)), "..", "docs", "src", "assets") +hummer = open(t -> parsenewick(t, NamedPolytomousTree), joinpath(assetpath, "hummingbirds.tree")) +evolve(tree) = Phylo.map_depthfirst((val, node) -> val + randn(), 0., tree, Float64) +trait = evolve(hummer) + +scp = recipeplot!( + Scene(scale_plot = false, show_axis = false), + hummer; + treetype = :fan, + line_z = trait, + linewidth = 5, + showtips = false, + cgrad = :RdYlBu, + seriestype = :path +) + +# ## GraphRecipes +using GraphRecipes + +# ### Julia AST with GraphRecipes + +code = quote + function mysum(list) + out = 0 + for value in list + out += value + end + out + end +end + +@test_nowarn recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) + +# ### Type tree with GraphRecipes + +@test_nowarn recipeplot(AbstractFloat; method = :tree, fontsize = 10) + # Timeseries with market data @test_nowarn recipeplot(MarketData.ohlc; seriestype = :path) From 5dedafbceb29be89e930dd9dd0390c90768e50d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 11:20:40 +0300 Subject: [PATCH 217/356] add separately --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index b1272c26c..ea4a10c01 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl CairoMakie#master"' + run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master From 65ffb96fcfe9f07a0ce6095a3e19545404742b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 11:24:23 +0300 Subject: [PATCH 218/356] dev --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index ea4a10c01..87b3e771b 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=. -e 'using Pkg; pkg"add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' + run: julia --project=. -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master From a6f691fdde62c48c0181df7cb94cdcb36962cc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 11:27:45 +0300 Subject: [PATCH 219/356] $(mktemp -d) --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 87b3e771b..0a4662e48 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=. -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' + run: julia --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master From cd51e547e4734ff36b9e5f3d3658fa0b5d07c821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Mon, 6 Apr 2020 11:32:39 +0300 Subject: [PATCH 220/356] Update .github/workflows/CI.yml Co-Authored-By: Anshul Singhvi --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 0a4662e48..bd568a541 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: version: ${{ matrix.julia-version }} - name: Add package versions - run: julia --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' + run: julia --project=temp_for_test -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - name: Run tests uses: julia-actions/julia-runtest@master From a6c3bc165988816d735225c7374c788b6af416e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= Date: Mon, 6 Apr 2020 13:03:44 +0300 Subject: [PATCH 221/356] use temp_for_test --- RecipesPipeline/.github/workflows/CI.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index bd568a541..28333c420 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -24,7 +24,8 @@ jobs: run: julia --project=temp_for_test -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - name: Run tests - uses: julia-actions/julia-runtest@master +# uses: julia-actions/julia-runtest@master + - run: julia --project=temp_for_test -e 'using Pkg; pkg"test"' # - name: Upload recordings # uses: actions/upload-artifact@v1.0.0 From 29677acb4f37cebbc8c95a9b7cfb1ba44105b1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Mon, 6 Apr 2020 13:07:51 +0300 Subject: [PATCH 222/356] fix typo --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 28333c420..c414e36c8 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -25,7 +25,7 @@ jobs: - name: Run tests # uses: julia-actions/julia-runtest@master - - run: julia --project=temp_for_test -e 'using Pkg; pkg"test"' + run: julia --project=temp_for_test -e 'using Pkg; pkg"test"' # - name: Upload recordings # uses: actions/upload-artifact@v1.0.0 From f6bb9fd5f6a60b0982a141e96f2af53afac49fed Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Tue, 7 Apr 2020 18:49:26 +0530 Subject: [PATCH 223/356] Update .github/workflows/CI.yml --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index c414e36c8..175c22deb 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -25,7 +25,7 @@ jobs: - name: Run tests # uses: julia-actions/julia-runtest@master - run: julia --project=temp_for_test -e 'using Pkg; pkg"test"' + run: julia --project=temp_for_test -e 'using Pkg; pkg"test RecipesPipeline"' # - name: Upload recordings # uses: actions/upload-artifact@v1.0.0 From af62878a28fb4e7dccdf6e62afa44d9c88650b66 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 7 May 2020 20:30:53 +0530 Subject: [PATCH 224/356] ensure that images are uploaded --- RecipesPipeline/.github/workflows/CI.yml | 19 +++++----------- RecipesPipeline/test/makie.jl | 29 ++++++++++++++++-------- RecipesPipeline/test/runtests.jl | 7 +++++- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 175c22deb..27bf4c8b8 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -27,19 +27,12 @@ jobs: # uses: julia-actions/julia-runtest@master run: julia --project=temp_for_test -e 'using Pkg; pkg"test RecipesPipeline"' -# - name: Upload recordings -# uses: actions/upload-artifact@v1.0.0 -# with: -# name: Recordings -# path: ./test/test_recordings -# if: always() -# -# - name: Upload diffs -# uses: actions/upload-artifact@v1.0.0 -# with: -# name: Recordings -# path: ./test/tested_different -# if: always() + - name: Upload test images + uses: actions/upload-artifact@v1.0.0 + with: + name: Recordings + path: ./test + if: always() - name: Cache artifacts uses: actions/cache@v1 diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl index 5d61d0e22..286eee70b 100644 --- a/RecipesPipeline/test/makie.jl +++ b/RecipesPipeline/test/makie.jl @@ -5,6 +5,17 @@ using MarketData, TimeSeries # ## The simplest example model +const i = Ref(0) + +macro test_and_save(arg) + return quote + @test_nowarn scene = $arg + i[] += 1 + save("test_$(i[])", scene) + end +end + + struct T end RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) @@ -15,13 +26,13 @@ RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) rand(10,n) # return the arguments (input data) for the next recipe end -@test_nowarn recipeplot(T(); seriestype = :path) +@test_and_save recipeplot(T(); seriestype = :path) # ## Testing out series decomposition sc = Scene() -@test_nowarn recipeplot!(sc, rand(10, 2); seriestype = :scatter) -@test_nowarn recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) +@test_and_save recipeplot!(sc, rand(10, 2); seriestype = :scatter) +@test_and_save recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) # ## Distributions @@ -38,7 +49,7 @@ u0 = [1/2, 1] tspan = (0.0,1.0) prob = ODEProblem(f,u0,tspan) sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_nowarn recipeplot(sol) +@test_and_save recipeplot(sol) # ### Matrix DiffEq @@ -51,7 +62,7 @@ tspan = (0.0,1.0) f(u,p,t) = A*u prob = ODEProblem(f,u0,tspan) sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_nowarn recipeplot(sol) +@test_and_save recipeplot(sol) # ### Stochastic DiffEq @@ -62,7 +73,7 @@ u0 = rand(4,2) W = WienerProcess(0.0,0.0,0.0) prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) sol = solve(prob,SRIW1()) -@test_nowarn recipeplot(sol) +@test_and_save recipeplot(sol) # ## Phylogenetic tree using Phylo @@ -97,11 +108,11 @@ code = quote end end -@test_nowarn recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) +@test_and_save recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) # ### Type tree with GraphRecipes -@test_nowarn recipeplot(AbstractFloat; method = :tree, fontsize = 10) +@test_and_save recipeplot(AbstractFloat; method = :tree, fontsize = 10) # Timeseries with market data -@test_nowarn recipeplot(MarketData.ohlc; seriestype = :path) +@test_and_save recipeplot(MarketData.ohlc; seriestype = :path) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 7fee2809b..f970e7fb1 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -1,6 +1,11 @@ using RecipesPipeline using Test +makie_test_dir = joinpath(@__DIR__, "test_makie") +mkpath(makie_test_dir) + @testset "RecipesPipeline.jl" begin - @testset "Makie integration" begin include("makie.jl") end + @testset "Makie integration" cd(makie_test_dir) do + include("makie.jl") + end end From 28fa4226e46ef90e62a7f7f5b0e94f08b82f1637 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 7 May 2020 20:38:03 +0530 Subject: [PATCH 225/356] Pass a begin block to testset --- RecipesPipeline/test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index f970e7fb1..4134abce0 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -5,7 +5,7 @@ makie_test_dir = joinpath(@__DIR__, "test_makie") mkpath(makie_test_dir) @testset "RecipesPipeline.jl" begin - @testset "Makie integration" cd(makie_test_dir) do + @testset "Makie integration" begin cd(makie_test_dir) do include("makie.jl") - end + end end end From d3492a68d0b6c999a48daf3942c331c4817e8cba Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 7 May 2020 20:55:37 +0530 Subject: [PATCH 226/356] fix the macro --- RecipesPipeline/test/makie.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl index 286eee70b..9628c73c2 100644 --- a/RecipesPipeline/test/makie.jl +++ b/RecipesPipeline/test/makie.jl @@ -9,9 +9,8 @@ const i = Ref(0) macro test_and_save(arg) return quote - @test_nowarn scene = $arg i[] += 1 - save("test_$(i[])", scene) + @test_nowarn save("test_$(i[])", $arg) end end From e19becd69ffac2142565e1c1dc332e4e6dc6cf86 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 7 May 2020 21:33:21 +0530 Subject: [PATCH 227/356] seriously, I forgot .png? --- RecipesPipeline/test/makie.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl index 9628c73c2..84d3cc107 100644 --- a/RecipesPipeline/test/makie.jl +++ b/RecipesPipeline/test/makie.jl @@ -10,7 +10,7 @@ const i = Ref(0) macro test_and_save(arg) return quote i[] += 1 - @test_nowarn save("test_$(i[])", $arg) + @test_nowarn save("test_$(i[]).png", $arg) end end From 4679ec41ef4ee5808b5013836719fc28b6dc5c2f Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Thu, 7 May 2020 22:13:17 +0530 Subject: [PATCH 228/356] Update .travis.yml --- RecipesPipeline/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml index d12434521..bc8b4670c 100644 --- a/RecipesPipeline/.travis.yml +++ b/RecipesPipeline/.travis.yml @@ -34,4 +34,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#ds/rewrite"; Pkg.build(); Pkg.test("Plots")' + - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#master"; Pkg.build(); Pkg.test("Plots")' From 90beb3db409084387bad8caec1f7ec80dce98607 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 8 May 2020 08:25:15 +0200 Subject: [PATCH 229/356] Fix split_attribute (#53) --- RecipesPipeline/src/api.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 4ec1f659e..1bba6fe15 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -34,7 +34,7 @@ Select the proper indices from `val` for attribute `key`. split_attribute(plt, key, val::AbstractArray, indices) = val[indices, fill(Colon(), ndims(val) - 1)...] split_attribute(plt, key, val::Tuple, indices) = - Tuple(split_attribute(key, v, indices) for v in val) + Tuple(split_attribute(plt, key, v, indices) for v in val) # ## Preprocessing attributes From f3a52c80bf8d25da5c9b22be24749fd04bf96989 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Fri, 8 May 2020 13:41:32 +0530 Subject: [PATCH 230/356] Fix a typo in the `recipe_pipeline!` constructor (#54) --- RecipesPipeline/src/RecipesPipeline.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 18d9086e5..b554457f9 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -53,9 +53,9 @@ include("recipes.jl") recipe_pipeline!(plt, plotattributes, args) Recursively apply user recipes, type recipes, plot recipes and series recipes to build a -list of `Dict`s, each corresponding to a series. At the beginning `plotattributes` -contains only the keyword arguments passed in by the user. Add all series to the plot -bject `plt` and return it. +list of `Dict`s, each corresponding to a series. At the beginning, `plotattributes` +contains only the keyword arguments passed in by the user. Then, add all series to the plot +object `plt` and return it. """ function recipe_pipeline!(plt, plotattributes, args) plotattributes[:plot_object] = plt From 7c47e20b3564048a8608e996d3c8b88cb88239d9 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 8 May 2020 10:16:07 +0200 Subject: [PATCH 231/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 880284837..d9a5d1d06 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.7" +version = "0.1.8" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 480b84a79fce6f03d24bbd1ea7d5d7c68777542f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 8 May 2020 10:48:58 +0200 Subject: [PATCH 232/356] fix time and period recipes --- RecipesPipeline/src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/recipes.jl b/RecipesPipeline/src/recipes.jl index 40c8d2109..ce78801d3 100644 --- a/RecipesPipeline/src/recipes.jl +++ b/RecipesPipeline/src/recipes.jl @@ -5,14 +5,14 @@ dateformatter(dt) = string(Date(Dates.UTD(dt))) datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) -timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) +timeformatter(t) = string(Dates.Time(Dates.Nanosecond(round(t)))) @recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) @recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter) @recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) @recipe f(::Type{P}, t::P) where {P<:Dates.Period} = - (t -> Dates.value(t), t -> string(P(t))) + (t -> Dates.value(t), t -> string(P(round(t)))) # ------------------------------------------------- # ## Characters From 49c172cd1220a86a8190c6fd842695e9a9bf716a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Fri, 8 May 2020 10:50:44 +0200 Subject: [PATCH 233/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index d9a5d1d06..6125bc914 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.8" +version = "0.1.9" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 54abbff4f965b3e4c025d72b0b308308dd6cd2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Miclu=C8=9Ba-C=C3=A2mpeanu?= <31181429+SebastianM-C@users.noreply.github.com> Date: Sat, 9 May 2020 15:57:55 +0300 Subject: [PATCH 234/356] Fix typo (#56) --- RecipesPipeline/docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl index f8c9d9eae..eafd6a423 100644 --- a/RecipesPipeline/docs/make.jl +++ b/RecipesPipeline/docs/make.jl @@ -10,7 +10,7 @@ Literate.markdown.(files, joinpath(@__DIR__, "src", "generated"); documenter = f makedocs( sitename = "RecipesPipeline.jl", - format = format = Documenter.HTML( + format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true" ), pages = [ From ff88236f9e7fc300fdec58015bad2da039d3c895 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jun 2020 12:05:46 +0200 Subject: [PATCH 235/356] implement `Base.axes` for `Volume` --- RecipesPipeline/src/utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 672154b90..c0ffdb4a7 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -110,6 +110,7 @@ end Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) Base.eltype(vol::Volume{T}) where {T} = T +Base.axes(vol::Volume, args...) = axes(vol.v, args...) # -------------------------------- From 93e8430a222b5b572fb54cbc4d9f9421d1348f4d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 4 Jun 2020 12:06:22 +0200 Subject: [PATCH 236/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 6125bc914..2f152a563 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.9" +version = "0.1.10" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From c0c0d31778fd7b4d2e6105874882d778b54fce23 Mon Sep 17 00:00:00 2001 From: JonasIsensee Date: Fri, 12 Jun 2020 11:35:25 +0200 Subject: [PATCH 237/356] Update group.jl --- RecipesPipeline/src/group.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl index 4e0c18d1f..778846226 100644 --- a/RecipesPipeline/src/group.jl +++ b/RecipesPipeline/src/group.jl @@ -8,7 +8,7 @@ end # this is when given a vector-type of values to group by function _extract_group_attributes(v::AVec, args...; legend_entry = string) - group_labels = sort(collect(unique(v))) + group_labels = collect(unique(sort(v))) n = length(group_labels) if n > 100 @warn("You created n=$n groups... Is that intended?") From c6062e48a44c90b3b83dbe31a9537447fe0ad341 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 27 Jun 2020 14:05:44 +0200 Subject: [PATCH 238/356] implement iterate for Surface and Volume --- RecipesPipeline/src/utils.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index c0ffdb4a7..8fc6da81e 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -78,7 +78,7 @@ Surface(f::Function, x, y) = Surface(Float64[f(xi, yi) for yi in y, xi in x]) Base.Array(surf::Surface) = surf.surf -for f in (:length, :size, :axes) +for f in (:length, :size, :axes, :iterate) @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) end Base.copy(surf::Surface) = Surface(copy(surf.surf)) @@ -104,13 +104,12 @@ function Volume( end Base.Array(vol::Volume) = vol.v -for f in (:length, :size) +for f in (:length, :size, :axes, :iterate) @eval Base.$f(vol::Volume, args...) = $f(vol.v, args...) end Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) Base.eltype(vol::Volume{T}) where {T} = T -Base.axes(vol::Volume, args...) = axes(vol.v, args...) # -------------------------------- From e72f75f55824f55739723f88b67994df7b9eec63 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 27 Jun 2020 14:06:29 +0200 Subject: [PATCH 239/356] bump version --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 2f152a563..687a34348 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.10" +version = "0.1.11" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 95d4e26d59d633b32cbf98ba14a433c6a22fb492 Mon Sep 17 00:00:00 2001 From: Michael Abbott Date: Mon, 13 Jul 2020 12:37:39 +0200 Subject: [PATCH 240/356] use NaNMath log functions --- RecipesPipeline/Project.toml | 1 + RecipesPipeline/src/RecipesPipeline.jl | 1 + RecipesPipeline/src/utils.jl | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 687a34348..52043175d 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -5,6 +5,7 @@ version = "0.1.11" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index b554457f9..b10bff18a 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -5,6 +5,7 @@ import RecipesBase import RecipesBase: @recipe, @series, RecipeData, is_explicit import PlotUtils # tryrange and adapted_grid using Dates +using NaNMath export recipe_pipeline! # Plots relies on these: diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 8fc6da81e..6bfdf9714 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -193,7 +193,7 @@ needs_3d_axes(plotattributes::AbstractDict) = # ## Scales # -------------------------------- -const SCALE_FUNCTIONS = Dict{Symbol, Function}(:log10 => log10, :log2 => log2, :ln => log) +const SCALE_FUNCTIONS = Dict{Symbol, Function}(:log10 => NaNMath.log10, :log2 => NaNMath.log2, :ln => NaNMath.log) const INVERSE_SCALE_FUNCTIONS = Dict{Symbol, Function}(:log10 => exp10, :log2 => exp2, :ln => exp) From 81c716478b2c46fbe397f02e63fd41a31813d7b6 Mon Sep 17 00:00:00 2001 From: Benoit Pasquier <4486578+briochemc@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:30:34 +1000 Subject: [PATCH 241/356] Add one_arg_shorthands macro (#73) * Add one_arg_shorthands macro * export one_arg_shorthands --- RecipesBase/src/RecipesBase.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b5bd97a40..be80a69ca 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,6 +6,7 @@ export @series, @userplot, @shorthands, + @one_arg_shorthands, RecipeData, AbstractBackend, AbstractPlot, @@ -404,6 +405,31 @@ macro shorthands(funcname::Symbol) end) end +""" + @one_arg_shorthands(funcname::Symbol) + +Similar to `@shorthands`, but for one-argument plots. + +The main difference with `@shorthands` is that the arguments +are reordered according to the `orientation` keyword +such that the axis letter is correctly assigned. +""" +macro one_arg_shorthands(funcname::Symbol) + funcname2 = Symbol(funcname, "!") + esc(quote + export $funcname, $funcname2 + Core.@__doc__ $funcname(x; kw...) = get(kw, :orientation, :vertical) == :vertical ? + RecipesBase.plot(x, []; kw..., seriestype = $(Meta.quot(funcname))) : + RecipesBase.plot([], x; kw..., seriestype = $(Meta.quot(funcname))) + Core.@__doc__ $funcname2(plt, x; kw...) = get(kw, :orientation, :vertical) == :vertical ? + RecipesBase.plot!(plt, x, []; kw..., seriestype = $(Meta.quot(funcname))) : + RecipesBase.plot!(plt, [], x; kw..., seriestype = $(Meta.quot(funcname))) + Core.@__doc__ $funcname2(x; kw...) = get(kw, :orientation, :vertical) == :vertical ? + RecipesBase.plot!(x, []; kw..., seriestype = $(Meta.quot(funcname))) : + RecipesBase.plot!([], x; kw..., seriestype = $(Meta.quot(funcname))) + end) +end + #---------------------------------------------------------------------------- # allow usage of type recipes without depending on StatsPlots From 720d400fed958014454e8dcb1c07790a0ef32b0e Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 23 Jul 2020 09:31:28 +0200 Subject: [PATCH 242/356] patch version [skip ci] --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index fc64fc186..d91c18bef 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.0.1" +version = "1.0.2" [compat] julia = "1" From fe76c3bb4339eeecb7597ab66f8a7357b92efa3d Mon Sep 17 00:00:00 2001 From: Adrian Dawid Date: Fri, 14 Aug 2020 08:50:56 +0200 Subject: [PATCH 243/356] Add :mesh3d as 3d series type (#62) --- RecipesPipeline/src/utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 6bfdf9714..8b3298ddd 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -144,6 +144,7 @@ for st in ( :surface, :volume, :wireframe, + :mesh3d ) @eval is3d(::Type{Val{Symbol($(string(st)))}}) = true end From 9d8752f261198715e561bdaf9e673e519d0a6b01 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 14 Aug 2020 14:27:25 +0200 Subject: [PATCH 244/356] 0.1.12 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 52043175d..a5186327a 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.11" +version = "0.1.12" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 336263e57b685ca3331c523883570c1aa89bc05f Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 14 Aug 2020 15:30:08 +0200 Subject: [PATCH 245/356] add compat for NaNMath --- RecipesPipeline/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index a5186327a..96fd744a6 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -10,6 +10,7 @@ PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] +NaNMath = "0.3" PlotUtils = "0.6.5, 1" RecipesBase = "0.8, 1.0" julia = "1" From 385d1d1ed2592d0fa3dbb6761e179d7ccfdca936 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 8 Sep 2020 13:41:25 +0200 Subject: [PATCH 246/356] dispatch processing of axis args on the plot object (#63) * dispatch processing of axis args on the plot object * Update type_recipe.jl * Update type_recipe.jl * Update type_recipe.jl * add to API * Update api.jl --- RecipesPipeline/src/api.jl | 48 ++++++++++++++++++++++++++++++ RecipesPipeline/src/type_recipe.jl | 44 ++++----------------------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 1bba6fe15..124fad5d0 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -64,6 +64,54 @@ Returns `true` if `attr` is an axis attribute, i.e. it applies to `xattr`, `yatt """ is_axis_attribute(plt, attr) = false +# ### processing of axis args +# axis args before type recipes should still be mapped to all axes +""" + preprocess_axis_args!(plt, plotattributes) + +Preprocessing of axis attributes. +Prepends the axis letter to axis attributes by default. +""" +function preprocess_axis_args!(plt, plotattributes) + for (k, v) in plotattributes + if is_axis_attribute(plt, k) + pop!(plotattributes, k) + for l in (:x, :y, :z) + lk = Symbol(l, k) + haskey(plotattributes, lk) || (plotattributes[lk] = v) + end + end + end +end + +""" + preprocess_axis_args!(plt, plotattributes, letter) + +This version additionally stores the letter name in `plotattributes[:letter]`. +""" +function preprocess_axis_args!(plt, plotattributes, letter) + plotattributes[:letter] = letter + preprocess_axis_args!(plt, plotattributes) +end + +# axis args in type recipes should only be applied to the current axis +""" + postprocess_axis_args!(plt, plotattributes, letter) + +Removes the `:letter` key from `plotattributes` and does the same prepending of the letters as `preprocess_axis_args!`. +""" +function postprocess_axis_args!(plt, plotattributes, letter) + pop!(plotattributes, :letter) + if letter in (:x, :y, :z) + for (k, v) in plotattributes + if is_axis_attribute(plt, k) + pop!(plotattributes, k) + lk = Symbol(letter, k) + haskey(plotattributes, lk) || (plotattributes[lk] = v) + end + end + end +end # ## User recipes diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index 3f1b89cfb..f0bbd5516 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -13,10 +13,11 @@ Apply the type recipe with signature `(::Type{T}, ::T)`. """ function _apply_type_recipe(plotattributes, v, letter) - _preprocess_axis_args!(plotattributes, letter) + plt = plotattributes[:plot_object] + preprocess_axis_args!(plt, plotattributes, letter) rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v) warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, typeof(v)) - _postprocess_axis_args!(plotattributes, letter) + postprocess_axis_args!(plt, plotattributes, letter) return rdvec[1].args[1] end @@ -25,7 +26,7 @@ end # and one to format tick values. function _apply_type_recipe(plotattributes, v::AbstractArray, letter) plt = plotattributes[:plot_object] - _preprocess_axis_args!(plotattributes, letter) + preprocess_axis_args!(plt, plotattributes, letter) # First we try to apply an array type recipe. w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1] warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(v)) @@ -35,7 +36,7 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) x = first(skipmissing(v)) args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(x)) - _postprocess_axis_args!(plotattributes, letter) + postprocess_axis_args!(plt, plotattributes, letter) if length(args) == 2 && all(arg -> arg isa Function, args) numfunc, formatter = args return Formatted(map(numfunc, v), formatter) @@ -43,7 +44,7 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) return v end end - _postprocess_axis_args!(plotattributes, letter) + postprocess_axis_args!(plt, plotattributes, letter) return w end @@ -69,36 +70,3 @@ _apply_type_recipe( letter, ) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v - -# axis args before type recipes should still be mapped to all axes -function _preprocess_axis_args!(plotattributes) - plt = plotattributes[:plot_object] - for (k, v) in plotattributes - if is_axis_attribute(plt, k) - pop!(plotattributes, k) - for l in (:x, :y, :z) - lk = Symbol(l, k) - haskey(plotattributes, lk) || (plotattributes[lk] = v) - end - end - end -end -function _preprocess_axis_args!(plotattributes, letter) - plotattributes[:letter] = letter - _preprocess_axis_args!(plotattributes) -end - -# axis args in type recipes should only be applied to the current axis -function _postprocess_axis_args!(plotattributes, letter) - plt = plotattributes[:plot_object] - pop!(plotattributes, :letter) - if letter in (:x, :y, :z) - for (k, v) in plotattributes - if is_axis_attribute(plt, k) - pop!(plotattributes, k) - lk = Symbol(letter, k) - haskey(plotattributes, lk) || (plotattributes[lk] = v) - end - end - end -end From c6c29a4b9f10c0c2f7d9943acbd44598016e116c Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 8 Sep 2020 13:42:53 +0200 Subject: [PATCH 247/356] 0.1.13 --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 96fd744a6..7eca0c76c 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.12" +version = "0.1.13" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 1474496a279fcca7dadb0522ada0d0eb62bc38b4 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 9 Sep 2020 12:51:17 +0200 Subject: [PATCH 248/356] remove one_arg_shorthands macro (#74) It didn't work out as intended --- RecipesBase/src/RecipesBase.jl | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index be80a69ca..b5bd97a40 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,7 +6,6 @@ export @series, @userplot, @shorthands, - @one_arg_shorthands, RecipeData, AbstractBackend, AbstractPlot, @@ -405,31 +404,6 @@ macro shorthands(funcname::Symbol) end) end -""" - @one_arg_shorthands(funcname::Symbol) - -Similar to `@shorthands`, but for one-argument plots. - -The main difference with `@shorthands` is that the arguments -are reordered according to the `orientation` keyword -such that the axis letter is correctly assigned. -""" -macro one_arg_shorthands(funcname::Symbol) - funcname2 = Symbol(funcname, "!") - esc(quote - export $funcname, $funcname2 - Core.@__doc__ $funcname(x; kw...) = get(kw, :orientation, :vertical) == :vertical ? - RecipesBase.plot(x, []; kw..., seriestype = $(Meta.quot(funcname))) : - RecipesBase.plot([], x; kw..., seriestype = $(Meta.quot(funcname))) - Core.@__doc__ $funcname2(plt, x; kw...) = get(kw, :orientation, :vertical) == :vertical ? - RecipesBase.plot!(plt, x, []; kw..., seriestype = $(Meta.quot(funcname))) : - RecipesBase.plot!(plt, [], x; kw..., seriestype = $(Meta.quot(funcname))) - Core.@__doc__ $funcname2(x; kw...) = get(kw, :orientation, :vertical) == :vertical ? - RecipesBase.plot!(x, []; kw..., seriestype = $(Meta.quot(funcname))) : - RecipesBase.plot!([], x; kw..., seriestype = $(Meta.quot(funcname))) - end) -end - #---------------------------------------------------------------------------- # allow usage of type recipes without depending on StatsPlots From af6e1de68e0b62a20dcdd1704980dd05eaf04aeb Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 9 Sep 2020 12:51:58 +0200 Subject: [PATCH 249/356] 1.1.0 --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index d91c18bef..c75aa8566 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.0.2" +version = "1.1.0" [compat] julia = "1" From 284e9cff8288b895d019debce47052ce45b1266a Mon Sep 17 00:00:00 2001 From: Moelf Date: Fri, 9 Oct 2020 10:38:12 -0400 Subject: [PATCH 250/356] more friendly error when x,y shape mis-match --- RecipesPipeline/src/series.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index 3bd86f3a8..9df0dc4ab 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -92,6 +92,11 @@ _nobigs(v) = v x = _compute_x(x, y, z) y = _compute_y(x, y, z) z = _compute_z(x, y, z) + if !isnothing(x) + n = size(x,1) + !isnothing(y) && size(y,1) != n && error("Expects $n elements in each col of y, found $(size(y,1)).") + !isnothing(z) && size(z,1) != n && error("Expects $n elements in each col of z, found $(size(z,1)).") + end _nobigs(x), _nobigs(y), _nobigs(z) end From 2143f6eb8bb83d1687bfb8df60929bc20838c76f Mon Sep 17 00:00:00 2001 From: Moelf Date: Fri, 9 Oct 2020 10:39:11 -0400 Subject: [PATCH 251/356] AbstractDict plot sorted --- RecipesPipeline/src/series.jl | 5 ----- RecipesPipeline/src/user_recipe.jl | 6 ++++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index 9df0dc4ab..3bd86f3a8 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -92,11 +92,6 @@ _nobigs(v) = v x = _compute_x(x, y, z) y = _compute_y(x, y, z) z = _compute_z(x, y, z) - if !isnothing(x) - n = size(x,1) - !isnothing(y) && size(y,1) != n && error("Expects $n elements in each col of y, found $(size(y,1)).") - !isnothing(z) && size(z,1) != n && error("Expects $n elements in each col of z, found $(size(z,1)).") - end _nobigs(x), _nobigs(y), _nobigs(z) end diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 32a43bba1..aa4724d25 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -230,8 +230,10 @@ end end # Dicts: each entry is a data point (x,y)=(key,value) -@recipe f(d::AbstractDict) = collect(keys(d)), collect(values(d)) - +@recipe function f(d::AbstractDict) + seriestype := :line + collect(keys(d)), collect(values(d)) +end # function without range... use the current range of the x-axis @recipe function f(f::FuncOrFuncs{F}) where {F <: Function} plt = plotattributes[:plot_object] From 9d67d1e15cc54eef90aea01b03b9196dece9a56c Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Mon, 12 Oct 2020 08:13:04 -0400 Subject: [PATCH 252/356] more friendly error when x,y shape mis-match (#65) * more friendly error when x,y shape mis-match * don't touch z --- RecipesPipeline/src/series.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index 3bd86f3a8..b3b35d028 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -92,6 +92,10 @@ _nobigs(v) = v x = _compute_x(x, y, z) y = _compute_y(x, y, z) z = _compute_z(x, y, z) + if !isnothing(x) && isnothing(z) + n = size(x,1) + !isnothing(y) && size(y,1) != n && error("Expects $n elements in each col of y, found $(size(y,1)).") + end _nobigs(x), _nobigs(y), _nobigs(z) end From 818c5ece85d34e61176418844c41805be2aedc44 Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Wed, 21 Oct 2020 19:45:14 -0400 Subject: [PATCH 253/356] Update src/user_recipe.jl Co-authored-by: Daniel Schwabeneder --- RecipesPipeline/src/user_recipe.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index aa4724d25..a7b99327c 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -231,7 +231,7 @@ end # Dicts: each entry is a data point (x,y)=(key,value) @recipe function f(d::AbstractDict) - seriestype := :line + seriestype --> :line collect(keys(d)), collect(values(d)) end # function without range... use the current range of the x-axis From 9092a3a08b84157bfc93b6ab2a191309ec7bb19f Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 28 Oct 2020 21:14:26 +0100 Subject: [PATCH 254/356] switch to github-actions and update runtests.jl to run Plots test images --- RecipesPipeline/.github/workflows/CI.yml | 69 ++++++++----- RecipesPipeline/.travis.yml | 37 ------- RecipesPipeline/Project.toml | 27 +++--- RecipesPipeline/test/makie.jl | 117 ----------------------- RecipesPipeline/test/runtests.jl | 26 +++-- 5 files changed, 81 insertions(+), 195 deletions(-) delete mode 100644 RecipesPipeline/.travis.yml delete mode 100644 RecipesPipeline/test/makie.jl diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 27bf4c8b8..96d958eae 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -1,39 +1,43 @@ name: CI -on: [push] +on: + push: + pull_request: + +defaults: + run: + shell: bash jobs: - test: + CI: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + env: + GKS_ENCODING: "utf8" + + name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.version == 'nightly' }} strategy: - matrix: - julia-version: [1.4] - julia-arch: [x64] - os: [ubuntu-latest, macOS-latest] fail-fast: false + matrix: + version: + - '1' + - 'nightly' + os: + - ubuntu-latest + - macOS-latest + - windows-latest + arch: + - x64 steps: - - uses: actions/checkout@v1.0.0 + - uses: actions/checkout@v2 - name: Set up Julia uses: julia-actions/setup-julia@latest with: version: ${{ matrix.julia-version }} - - name: Add package versions - run: julia --project=temp_for_test -e 'using Pkg; pkg"dev .; add https://github.com/JuliaPlots/MakieRecipes.jl; add CairoMakie#master"' - - - name: Run tests -# uses: julia-actions/julia-runtest@master - run: julia --project=temp_for_test -e 'using Pkg; pkg"test RecipesPipeline"' - - - name: Upload test images - uses: actions/upload-artifact@v1.0.0 - with: - name: Recordings - path: ./test - if: always() - - name: Cache artifacts uses: actions/cache@v1 env: @@ -45,4 +49,25 @@ jobs: ${{ runner.os }}-test-${{ env.cache-name }}- ${{ runner.os }}-test- ${{ runner.os }}- - if: always() + + # TESTCMD + - name: Default TESTCMD + run: echo ::set-env name=TESTCMD::"julia" + - name: Ubuntu TESTCMD + if: startsWith(matrix.os,'ubuntu') + run: echo ::set-env name=TESTCMD::"xvfb-run --auto-servernum julia" + + # Julia Dependencies + - name: Install Julia dependencies + uses: julia-actions/julia-buildpkg@latest + + # Run tests + - name: Run tests + run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true);' + + Skip: + if: "contains(github.event.head_commit.message, '[skip ci]')" + runs-on: ubuntu-latest + steps: + - name: Skip CI 🚫 + run: echo skip ci \ No newline at end of file diff --git a/RecipesPipeline/.travis.yml b/RecipesPipeline/.travis.yml deleted file mode 100644 index bc8b4670c..000000000 --- a/RecipesPipeline/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -# Documentation: http://docs.travis-ci.com/user/languages/julia/ -language: julia -os: - - linux - # - osx -julia: - - 1 - - nightly - -matrix: - allow_failures: - - julia: nightly - -addons: - apt: - packages: - - at-spi2-core - - libgtk-3-dev - - xauth - - xvfb - -env: - - GKS_ENCODING="utf8" - -cache: - directories: - - $HOME/.julia/artifacts - -sudo: required - -notifications: - email: true - -script: - - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD --project=$(mktemp -d) -e 'using Pkg; pkg"dev .; add Plots#master"; Pkg.build(); Pkg.test("Plots")' diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 7eca0c76c..844630fb9 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -16,19 +16,20 @@ RecipesBase = "0.8, 1.0" julia = "1" [extras] -AbstractPlotting = "537997a7-5e4e-5d89-9595-2241ea00577e" -CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" -DiffEqNoiseProcess = "77a26b50-5914-5dd7-bc55-306e6241c503" -MakieRecipes = "3c562d8e-4afa-4f1c-99bf-ad54af2b207f" -MarketData = "945b72a4-3b13-509d-9b46-1525bb5c06de" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" +ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" +Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e" -Phylo = "aea672f4-3940-5932-aa44-993d1c3ff149" -GraphRecipes = "bd48cda9-67a9-57be-86fa-5b3c104eda73" [targets] -test = ["Test", "AbstractPlotting", "CairoMakie", "OrdinaryDiffEq", - "StochasticDiffEq", "DiffEqNoiseProcess", - "MakieRecipes", "MarketData", "TimeSeries", "Phylo", "GraphRecipes"] +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test"] diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl deleted file mode 100644 index 84d3cc107..000000000 --- a/RecipesPipeline/test/makie.jl +++ /dev/null @@ -1,117 +0,0 @@ -using AbstractPlotting, CairoMakie -using MakieRecipes -using MakieRecipes.RecipesBase -using MarketData, TimeSeries - -# ## The simplest example model - -const i = Ref(0) - -macro test_and_save(arg) - return quote - i[] += 1 - @test_nowarn save("test_$(i[]).png", $arg) - end -end - - -struct T end - -RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) - markershape --> :auto # if markershape is unset, make it :auto - markercolor := customcolor # force markercolor to be customcolor - xrotation --> 45 # if xrotation is unset, make it 45 - zrotation --> 90 # if zrotation is unset, make it 90 - rand(10,n) # return the arguments (input data) for the next recipe -end - -@test_and_save recipeplot(T(); seriestype = :path) - -# ## Testing out series decomposition - -sc = Scene() -@test_and_save recipeplot!(sc, rand(10, 2); seriestype = :scatter) -@test_and_save recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) - -# ## Distributions - -# ### - -# ## Differential Equations - -using OrdinaryDiffEq, StochasticDiffEq, DiffEqNoiseProcess - -# ### A simple exponential growth model - -f(u,p,t) = 1.01.*u -u0 = [1/2, 1] -tspan = (0.0,1.0) -prob = ODEProblem(f,u0,tspan) -sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_and_save recipeplot(sol) - -# ### Matrix DiffEq - -A = [1. 0 0 -5 - 4 -2 4 -3 - -4 0 0 1 - 5 -2 2 3] -u0 = rand(4,2) -tspan = (0.0,1.0) -f(u,p,t) = A*u -prob = ODEProblem(f,u0,tspan) -sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_and_save recipeplot(sol) - -# ### Stochastic DiffEq - -f(du,u,p,t) = (du .= u) -g(du,u,p,t) = (du .= u) -u0 = rand(4,2) - -W = WienerProcess(0.0,0.0,0.0) -prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) -sol = solve(prob,SRIW1()) -@test_and_save recipeplot(sol) - -# ## Phylogenetic tree -using Phylo -assetpath = joinpath(dirname(pathof(MakieRecipes)), "..", "docs", "src", "assets") -hummer = open(t -> parsenewick(t, NamedPolytomousTree), joinpath(assetpath, "hummingbirds.tree")) -evolve(tree) = Phylo.map_depthfirst((val, node) -> val + randn(), 0., tree, Float64) -trait = evolve(hummer) - -scp = recipeplot!( - Scene(scale_plot = false, show_axis = false), - hummer; - treetype = :fan, - line_z = trait, - linewidth = 5, - showtips = false, - cgrad = :RdYlBu, - seriestype = :path -) - -# ## GraphRecipes -using GraphRecipes - -# ### Julia AST with GraphRecipes - -code = quote - function mysum(list) - out = 0 - for value in list - out += value - end - out - end -end - -@test_and_save recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) - -# ### Type tree with GraphRecipes - -@test_and_save recipeplot(AbstractFloat; method = :tree, fontsize = 10) - -# Timeseries with market data -@test_and_save recipeplot(MarketData.ohlc; seriestype = :path) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 4134abce0..b0783540f 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -1,11 +1,25 @@ +using Distributions +using FileIO +using GeometryBasics +using ImageMagick +using Images +using OffsetArrays +using Plots +using Random using RecipesPipeline +using RDatasets +using SparseArrays +using StaticArrays +using Statistics +using StatsPlots using Test -makie_test_dir = joinpath(@__DIR__, "test_makie") -mkpath(makie_test_dir) - @testset "RecipesPipeline.jl" begin - @testset "Makie integration" begin cd(makie_test_dir) do - include("makie.jl") - end end + @testset "Plots tests" begin + for i in eachindex(Plots._examples) + if i ∉ Plots._backend_skips[:gr] + @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot + end + end + end end From 1c9dffa10ef251cdcc575c2c1e60bf15599e7224 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 28 Oct 2020 21:19:33 +0100 Subject: [PATCH 255/356] update CI.yml --- RecipesPipeline/.github/workflows/CI.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 96d958eae..31bcc7a4c 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -1,4 +1,4 @@ -name: CI +name: ci on: push: @@ -25,19 +25,19 @@ jobs: - 'nightly' os: - ubuntu-latest - - macOS-latest - windows-latest + - macos-latest arch: - x64 + # - x86 steps: - - uses: actions/checkout@v2 - - name: Set up Julia - uses: julia-actions/setup-julia@latest + # Setup environment + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@latest with: - version: ${{ matrix.julia-version }} - + version: ${{ matrix.version }} - name: Cache artifacts uses: actions/cache@v1 env: @@ -70,4 +70,4 @@ jobs: runs-on: ubuntu-latest steps: - name: Skip CI 🚫 - run: echo skip ci \ No newline at end of file + run: echo skip ci From 22cc594f185ade61d30ef3e003906e1c0cb60cbd Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 28 Oct 2020 21:33:12 +0100 Subject: [PATCH 256/356] keep makie tests --- RecipesPipeline/test/makie.jl | 117 +++++++++++++++++++++++++++++++ RecipesPipeline/test/runtests.jl | 6 ++ 2 files changed, 123 insertions(+) create mode 100644 RecipesPipeline/test/makie.jl diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl new file mode 100644 index 000000000..84d3cc107 --- /dev/null +++ b/RecipesPipeline/test/makie.jl @@ -0,0 +1,117 @@ +using AbstractPlotting, CairoMakie +using MakieRecipes +using MakieRecipes.RecipesBase +using MarketData, TimeSeries + +# ## The simplest example model + +const i = Ref(0) + +macro test_and_save(arg) + return quote + i[] += 1 + @test_nowarn save("test_$(i[]).png", $arg) + end +end + + +struct T end + +RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) + markershape --> :auto # if markershape is unset, make it :auto + markercolor := customcolor # force markercolor to be customcolor + xrotation --> 45 # if xrotation is unset, make it 45 + zrotation --> 90 # if zrotation is unset, make it 90 + rand(10,n) # return the arguments (input data) for the next recipe +end + +@test_and_save recipeplot(T(); seriestype = :path) + +# ## Testing out series decomposition + +sc = Scene() +@test_and_save recipeplot!(sc, rand(10, 2); seriestype = :scatter) +@test_and_save recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) + +# ## Distributions + +# ### + +# ## Differential Equations + +using OrdinaryDiffEq, StochasticDiffEq, DiffEqNoiseProcess + +# ### A simple exponential growth model + +f(u,p,t) = 1.01.*u +u0 = [1/2, 1] +tspan = (0.0,1.0) +prob = ODEProblem(f,u0,tspan) +sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) +@test_and_save recipeplot(sol) + +# ### Matrix DiffEq + +A = [1. 0 0 -5 + 4 -2 4 -3 + -4 0 0 1 + 5 -2 2 3] +u0 = rand(4,2) +tspan = (0.0,1.0) +f(u,p,t) = A*u +prob = ODEProblem(f,u0,tspan) +sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) +@test_and_save recipeplot(sol) + +# ### Stochastic DiffEq + +f(du,u,p,t) = (du .= u) +g(du,u,p,t) = (du .= u) +u0 = rand(4,2) + +W = WienerProcess(0.0,0.0,0.0) +prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) +sol = solve(prob,SRIW1()) +@test_and_save recipeplot(sol) + +# ## Phylogenetic tree +using Phylo +assetpath = joinpath(dirname(pathof(MakieRecipes)), "..", "docs", "src", "assets") +hummer = open(t -> parsenewick(t, NamedPolytomousTree), joinpath(assetpath, "hummingbirds.tree")) +evolve(tree) = Phylo.map_depthfirst((val, node) -> val + randn(), 0., tree, Float64) +trait = evolve(hummer) + +scp = recipeplot!( + Scene(scale_plot = false, show_axis = false), + hummer; + treetype = :fan, + line_z = trait, + linewidth = 5, + showtips = false, + cgrad = :RdYlBu, + seriestype = :path +) + +# ## GraphRecipes +using GraphRecipes + +# ### Julia AST with GraphRecipes + +code = quote + function mysum(list) + out = 0 + for value in list + out += value + end + out + end +end + +@test_and_save recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) + +# ### Type tree with GraphRecipes + +@test_and_save recipeplot(AbstractFloat; method = :tree, fontsize = 10) + +# Timeseries with market data +@test_and_save recipeplot(MarketData.ohlc; seriestype = :path) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index b0783540f..e8416f934 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -14,7 +14,13 @@ using Statistics using StatsPlots using Test +# makie_test_dir = joinpath(@__DIR__, "test_makie") +# mkpath(makie_test_dir) + @testset "RecipesPipeline.jl" begin + # @testset "Makie integration" begin cd(makie_test_dir) do + # include("makie.jl") + # end end @testset "Plots tests" begin for i in eachindex(Plots._examples) if i ∉ Plots._backend_skips[:gr] From 7bc6ab6e9780c03104186355685411fb053fd0db Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 26 Sep 2020 19:34:26 +0200 Subject: [PATCH 257/356] move `signature_string` to RecipesPipeline --- RecipesPipeline/src/RecipesPipeline.jl | 3 ++- RecipesPipeline/src/api.jl | 10 +++++++++- RecipesPipeline/src/plot_recipe.jl | 2 +- RecipesPipeline/src/series_recipe.jl | 2 +- RecipesPipeline/src/type_recipe.jl | 6 +++--- RecipesPipeline/src/user_recipe.jl | 2 +- RecipesPipeline/src/utils.jl | 12 ++++++++++++ 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index b10bff18a..2000b5226 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -39,8 +39,8 @@ export warn_on_recipe_aliases, slice_series_attributes!, process_sliced_series_attributes! -include("api.jl") include("utils.jl") +include("api.jl") include("series.jl") include("group.jl") include("user_recipe.jl") @@ -59,6 +59,7 @@ contains only the keyword arguments passed in by the user. Then, add all series object `plt` and return it. """ function recipe_pipeline!(plt, plotattributes, args) + @nospecialize plotattributes[:plot_object] = plt # -------------------------------- diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 124fad5d0..d6c0ee5c7 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -8,7 +8,15 @@ Warn if an alias is dedected in `plotattributes` after a recipe of type `recipe_type` is applied to 'args'. `recipe_type` is either `:user`, `:type`, `:plot` or `:series`. """ -function warn_on_recipe_aliases!(plt, plotattributes, recipe_type, args...) end +function warn_on_recipe_aliases!(plt, plotattributes::AKW, recipe_type, signature_string) end +function warn_on_recipe_aliases!(plt, v::AbstractVector, recipe_type, signature_string) + for x in v + warn_on_recipe_aliases!(plt, x, recipe_type, signature_string) + end +end +function warn_on_recipe_aliases!(plt, rd::RecipeData, recipe_type, signature_string) + warn_on_recipe_aliases!(plt, rd.plotattributes, recipe_type, signature_string) +end # ## Grouping diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 7f52237a0..45a70218a 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -29,7 +29,7 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) st = kw[:seriestype] st = kw[:seriestype] = type_alias(plt, st) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - warn_on_recipe_aliases!(plt, datalist, :plot, st) + warn_on_recipe_aliases!(plt, datalist, :plot, plotrecipe_signature_string(st)) for data in datalist preprocess_attributes!(plt, data.plotattributes) if data.plotattributes[:seriestype] == st diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index a56f66e91..dc3caf00e 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -46,7 +46,7 @@ function _process_seriesrecipe(plt, plotattributes) # get a sub list of series for this seriestype x, y, z = plotattributes[:x], plotattributes[:y], plotattributes[:z] datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, x, y, z) - warn_on_recipe_aliases!(plt, datalist, :series, st) + warn_on_recipe_aliases!(plt, datalist, :series, seriesrecipe_signature_string(st)) # assuming there was no error, recursively apply the series recipes for data in datalist diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index f0bbd5516..db173c29e 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -16,7 +16,7 @@ function _apply_type_recipe(plotattributes, v, letter) plt = plotattributes[:plot_object] preprocess_axis_args!(plt, plotattributes, letter) rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v) - warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, typeof(v)) + warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, typerecipe_signature_string(v)) postprocess_axis_args!(plt, plotattributes, letter) return rdvec[1].args[1] end @@ -29,13 +29,13 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) preprocess_axis_args!(plt, plotattributes, letter) # First we try to apply an array type recipe. w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1] - warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(v)) + warn_on_recipe_aliases!(plt, plotattributes, :type, typerecipe_signature_string(v)) # If the type did not change try it element-wise if typeof(v) == typeof(w) isempty(skipmissing(v)) && return Float64[] x = first(skipmissing(v)) args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args - warn_on_recipe_aliases!(plt, plotattributes, :type, typeof(x)) + warn_on_recipe_aliases!(plt, plotattributes, :type, typerecipe_signature_string(x)) postprocess_axis_args!(plt, plotattributes, letter) if length(args) == 2 && all(arg -> arg isa Function, args) numfunc, formatter = args diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index a7b99327c..b7306e6df 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -34,7 +34,7 @@ function _process_userrecipes!(plt, plotattributes, args) else rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) - warn_on_recipe_aliases!(plt, rd_list, :user, next_series.args...) + warn_on_recipe_aliases!(plt, rd_list, :user, userrecipe_signature_string(next_series.args...)) prepend!(still_to_process, rd_list) end end diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 8b3298ddd..93ab1c416 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -221,3 +221,15 @@ end _map_funcs(f::Function, u::AVec) = map(f, u) _map_funcs(fs::AVec{F}, u::AVec) where {F <: Function} = [map(f, u) for f in fs] + + +# -------------------------------- +# ## Signature strings +# -------------------------------- + +function userrecipe_signature_string(args...) + return string("(::", join(string.(typeof.(args)), ", ::"), ")") +end +typerecipe_signature_string(::T) where T = "(::Type{$T}, ::$T)" +plotrecipe_signature_string(st) = "(::Type{Val{:$st}}, ::AbstractPlot)" +seriesrecipe_signature_string(st) = "(::Type{Val{:$st}}, x, y, z)" \ No newline at end of file From 1f73a817f70932b6839a72942602628435055d11 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 18:18:28 +0100 Subject: [PATCH 258/356] minor version bump --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 844630fb9..a7d51a3f6 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.13" +version = "0.2.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From d5066880a6d0a2737d48dc0a998c038d341d51ab Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 18:22:00 +0100 Subject: [PATCH 259/356] Revert "minor version bump" This reverts commit 63c713b7808adf305484a9724cef9eabae2a0702. --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index a7d51a3f6..844630fb9 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.2.0" +version = "0.1.13" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From c1d5754eb367f008fcd48355f27a999b0b274e5a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:13:57 +0100 Subject: [PATCH 260/356] move `warn_on_recipe_aliases!` from Plots and add some `@nospecialize` --- RecipesPipeline/src/RecipesPipeline.jl | 3 +++ RecipesPipeline/src/plot_recipe.jl | 4 ++++ RecipesPipeline/src/series.jl | 1 + RecipesPipeline/src/series_recipe.jl | 4 ++++ RecipesPipeline/src/type_recipe.jl | 4 ++++ RecipesPipeline/src/user_recipe.jl | 19 +++++++++++++------ RecipesPipeline/src/utils.jl | 6 +++++- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 2000b5226..172961882 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -103,4 +103,7 @@ function recipe_pipeline!(plt, plotattributes, args) return plt end +include("precompile.jl") +_precompile_() + end diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 45a70218a..70a511e11 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -1,5 +1,7 @@ # # Plot Recipes +@nospecialize + """ _process_plotrecipes!(plt, kw_list) @@ -46,3 +48,5 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) end return end + +@specialize \ No newline at end of file diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index b3b35d028..239ec383f 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -124,6 +124,7 @@ struct SliceIt end # It splits processed data into individual series data, stores in copied `plotattributes` # for each series and returns no arguments. @recipe function f(::Type{SliceIt}, x, y, z) + @nospecialize # handle data with formatting attached if typeof(x) <: Formatted diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index dc3caf00e..45289b2f6 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -1,5 +1,7 @@ # # Series Recipes +@nospecialize + """ _process_seriesrecipes!(plt, kw_list) @@ -64,3 +66,5 @@ function _process_seriesrecipe(plt, plotattributes) end nothing end + +@specialize \ No newline at end of file diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index db173c29e..4013611e6 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -1,5 +1,7 @@ # # Type Recipes +@nospecialize + # this is the default "type recipe"... just pass the object through @recipe f(::Type{T}, v::T) where {T} = v @@ -70,3 +72,5 @@ _apply_type_recipe( letter, ) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v + +@specialize \ No newline at end of file diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index b7306e6df..992eab235 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -9,6 +9,7 @@ empy `args` is returned pop it from the vector, finish up, and it to vector of ` processed series. When all arguments are processed return the series `Dict`. """ function _process_userrecipes!(plt, plotattributes, args) + @nospecialize still_to_process = _recipedata_vector(plt, plotattributes, args) # For plotting recipes, we swap out the args and update the parameter dictionary. We are keeping a stack of series that still need to be processed. @@ -48,6 +49,7 @@ end # TODO Move this to api.jl? function _recipedata_vector(plt, plotattributes, args) + @nospecialize still_to_process = RecipeData[] # the grouping mechanism is a recipe on a GroupBy object # we simply add the GroupBy object to the front of the args list to allow @@ -76,6 +78,7 @@ function _recipedata_vector(plt, plotattributes, args) end function _expand_seriestype_array(plotattributes, args) + @nospecialize sts = get(plotattributes, :seriestype, :path) if typeof(sts) <: AbstractArray reset_kw!(plotattributes, :seriestype) @@ -107,6 +110,8 @@ end # Fallback user recipes # -------------------------------- +@nospecialize + # These call `_apply_type_recipe` in type_recipe.jl and finally the `SliceIt` recipe in # series.jl. @@ -304,12 +309,6 @@ end n = 200, ) where {F <: Function, G <: Function} = fx, fy, range(umin, stop = umax, length = n) -function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) - (xf, xinv), (yf, yinv) = ((scale_func(s), inverse_scale_func(s)) for s in (xscale, yscale)) - xs, ys = PlotUtils.adapted_grid(yf ∘ f ∘ xinv, xf.((xmin, xmax))) - xinv.(xs), yinv.(ys) -end - # special handling... 3D parametric function(s) @recipe function f( fx::FuncOrFuncs{F}, @@ -333,3 +332,11 @@ end # list of tuples @recipe f(v::AVec{<:Tuple}) = unzip(v) @recipe f(tup::Tuple) = [tup] + +@specialize + +function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) + (xf, xinv), (yf, yinv) = ((scale_func(s), inverse_scale_func(s)) for s in (xscale, yscale)) + xs, ys = PlotUtils.adapted_grid(yf ∘ f ∘ xinv, xf.((xmin, xmax))) + xinv.(xs), yinv.(ys) +end \ No newline at end of file diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 93ab1c416..3a45df70d 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -227,9 +227,13 @@ _map_funcs(fs::AVec{F}, u::AVec) where {F <: Function} = [map(f, u) for f in fs] # ## Signature strings # -------------------------------- +@nospecialize + function userrecipe_signature_string(args...) return string("(::", join(string.(typeof.(args)), ", ::"), ")") end typerecipe_signature_string(::T) where T = "(::Type{$T}, ::$T)" plotrecipe_signature_string(st) = "(::Type{Val{:$st}}, ::AbstractPlot)" -seriesrecipe_signature_string(st) = "(::Type{Val{:$st}}, x, y, z)" \ No newline at end of file +seriesrecipe_signature_string(st) = "(::Type{Val{:$st}}, x, y, z)" + +@specialize \ No newline at end of file From 4736bd3bce1db5c4ad801cde9744b9f76e0079fa Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:23:18 +0100 Subject: [PATCH 261/356] add CompileBot --- .../.github/workflows/SnoopCompile.yml | 88 +++++++++++++++++ .../linux/1.5/precompile_RecipesPipeline.jl | 94 +++++++++++++++++++ .../deps/SnoopCompile/snoop_bench.jl | 10 ++ .../deps/SnoopCompile/snoop_bot.jl | 10 ++ RecipesPipeline/src/RecipesPipeline.jl | 3 +- RecipesPipeline/src/precompile_includer.jl | 34 +++++++ 6 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 RecipesPipeline/.github/workflows/SnoopCompile.yml create mode 100644 RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl create mode 100644 RecipesPipeline/deps/SnoopCompile/snoop_bench.jl create mode 100644 RecipesPipeline/deps/SnoopCompile/snoop_bot.jl create mode 100644 RecipesPipeline/src/precompile_includer.jl diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml new file mode 100644 index 000000000..3d71a8e62 --- /dev/null +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -0,0 +1,88 @@ +name: SnoopCompile + +on: + push: + branches: + # - 'master' # NOTE: to run the bot only on pushes to master + +defaults: + run: + shell: bash + +jobs: + SnoopCompile: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + env: + GKS_ENCODING: "utf8" + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: # NOTE: the versions below should match those in your botconfig + - '1.5' + os: # NOTE: should match the os setting of your botconfig + - ubuntu-latest + arch: + - x64 + steps: + # Setup environment + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.version }} + + - name: Install dependencies + run: | + 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 + - name: Default TESTCMD + run: echo ::set-env name=TESTCMD::"julia" + - name: Ubuntu TESTCMD + if: startsWith(matrix.os,'ubuntu') + run: echo ::set-env name=TESTCMD::"xvfb-run --auto-servernum julia" + + # Generate precompile files + - name: Generating precompile files + run: $TESTCMD --project -e 'include("deps/SnoopCompile/snoop_bot.jl")' # NOTE: must match path + + # Run benchmarks + - name: Running Benchmark + run: $TESTCMD --project -e 'include("deps/SnoopCompile/snoop_bench.jl")' # NOTE: optional, if have benchmark file + + - name: Upload all + uses: actions/upload-artifact@v2.0.1 + with: + path: ./ + + Create_PR: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + needs: SnoopCompile + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Download all + uses: actions/download-artifact@v2 + + - name: CompileBot postprocess + run: julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();' + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update precompile_*.jl file + title: "[AUTO] Update precompiles" + labels: SnoopCompile + branch: "SnoopCompile_AutoPR" + + + Skip: + if: "contains(github.event.head_commit.message, '[skip ci]')" + runs-on: ubuntu-latest + steps: + - name: Skip CI 🚫 + run: echo skip ci diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl new file mode 100644 index 000000000..4c03bca95 --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl @@ -0,0 +1,94 @@ +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{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(RecipesPipeline._scaled_adapted_grid),Tuple{Array{Function,1},Base.RefValue{Symbol},Base.RefValue{Symbol},Float64,Float64}}}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Array{Function,1},Number,Number}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},RecipesPipeline.GroupBy,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Type{RecipesPipeline.SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,AbstractArray,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,Surface,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1}}) + Base.precompile(Tuple{typeof(RecipesPipeline._map_funcs),Function,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}) + Base.precompile(Tuple{typeof(RecipesPipeline._process_plotrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._process_ribbon),Tuple{LinRange{Float64},LinRange{Float64}},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipe),Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{AbstractArray{Float64,1},1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{Float64,1},1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{T,1} where T,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Float64,2},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Function,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Int64,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Real,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{String,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Union{Missing, Int64},1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Int64,Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRange{Int64,Int64},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Array{Int64,2}},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline.recipe_pipeline!),Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline.typerecipe_signature_string),typeof(atan)}) + Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Array{Float64,1},Array{Float64,1}},1}}) + Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Float64,Float64,Float64},1}}) + Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Int64,Real},1}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Base.OneTo{Int64},Base.OneTo{Int64},Surface{Array{Int64,2}}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{RecipesPipeline.GroupBy,Array{Float64,1}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Surface{Array{Float64,2}}}}}}}}) + Base.precompile(Tuple{typeof(setindex!),RecipesPipeline.DefaultsDict,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Symbol}) + let fbody = try __lookup_kwbody__(which(RecipesPipeline._extract_group_attributes, (Array{String,1},Array{Float64,1},))) catch missing end + if !ismissing(fbody) + precompile(fbody, (Function,typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1},)) + end + end +end diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl new file mode 100644 index 000000000..9f1551b37 --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl @@ -0,0 +1,10 @@ +using CompileBot + +snoop_bench( + BotConfig( + "RecipesPipeline", + yml_path= "SnoopCompile.yml", + else_os = "linux", + else_version = "1.5", + ) +) diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl new file mode 100644 index 000000000..c5eb2d63d --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl @@ -0,0 +1,10 @@ +using CompileBot + +snoop_bot( + BotConfig( + "RecipesPipeline", + yml_path= "SnoopCompile.yml", + else_os = "linux", + else_version = "1.5", + ) +) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 172961882..2bf23af1b 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -103,7 +103,6 @@ function recipe_pipeline!(plt, plotattributes, args) return plt end -include("precompile.jl") -_precompile_() +include("precompile_includer.jl") end diff --git a/RecipesPipeline/src/precompile_includer.jl b/RecipesPipeline/src/precompile_includer.jl new file mode 100644 index 000000000..10d539b67 --- /dev/null +++ b/RecipesPipeline/src/precompile_includer.jl @@ -0,0 +1,34 @@ +should_precompile = true + + +# Don't edit the following! Instead change the script for `snoop_bot`. +ismultios = true +ismultiversion = true +# precompile_enclosure +@static if !should_precompile + # nothing +elseif !ismultios && !ismultiversion + include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") + _precompile_() +else + @static if Sys.islinux() + @static if v"1.5.0-DEV" <= VERSION <= v"1.5.9" + include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") + _precompile_() + else + include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") + _precompile_() + end + + else + @static if v"1.5.0-DEV" <= VERSION <= v"1.5.9" + include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") + _precompile_() + else + include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") + _precompile_() + end + + end + +end # precompile_enclosure From 49d22e713e17f5c50de57319604a6c82a9a43514 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:23:56 +0100 Subject: [PATCH 262/356] minor version bump --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 844630fb9..bd5a02694 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.1.13" +version = "0.2" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 9e62da85478801d7af396529dbc3c924e0bce6ac Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:27:04 +0100 Subject: [PATCH 263/356] add precompile statements --- RecipesBase/src/RecipesBase.jl | 2 ++ RecipesBase/src/precompile.jl | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 RecipesBase/src/precompile.jl diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b5bd97a40..e25365cc2 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -272,6 +272,7 @@ macro recipe(funcexpr::Expr) # now build a function definition for apply_recipe, wrapping the return value in a tuple if needed. # we are creating a vector of RecipeData objects, one per series. funcdef = Expr(:function, func, esc(quote + @nospecialize if RecipesBase._debug_recipes[1] println("apply_recipe args: ", $args) end @@ -433,5 +434,6 @@ function recipetype(s::Val{T}, args...) where T error("No type recipe defined for type $T. You may need to load StatsPlots") end +include("precompile.jl") end # module diff --git a/RecipesBase/src/precompile.jl b/RecipesBase/src/precompile.jl new file mode 100644 index 000000000..3c62e42cd --- /dev/null +++ b/RecipesBase/src/precompile.jl @@ -0,0 +1,9 @@ +function _precompile_() + ccall(:jl_generating_output, Cint, ()) == 1 || return nothing + Base.precompile(Tuple{typeof(RecipesBase.create_kw_body),Expr}) + Base.precompile(Tuple{typeof(RecipesBase.get_function_def),Expr,Array{Any,1}}) + Base.precompile(Tuple{typeof(map),Function,Array{AbstractLayout,1}}) + Base.precompile(Tuple{typeof(map),Function,Array{AbstractLayout,2}}) +end + +_precompile_() \ No newline at end of file From da2324bfdd60a90b49ba10128a9a5181ca9881c9 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:27:42 +0100 Subject: [PATCH 264/356] bump version --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index c75aa8566..a567d6cad 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.1.0" +version = "1.1.1" [compat] julia = "1" From b29df2dcc6cc8ea9bd436a9121363cc02af690a6 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:56:56 +0100 Subject: [PATCH 265/356] add new line at end of file --- RecipesBase/src/precompile.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/precompile.jl b/RecipesBase/src/precompile.jl index 3c62e42cd..49537ca3a 100644 --- a/RecipesBase/src/precompile.jl +++ b/RecipesBase/src/precompile.jl @@ -6,4 +6,4 @@ function _precompile_() Base.precompile(Tuple{typeof(map),Function,Array{AbstractLayout,2}}) end -_precompile_() \ No newline at end of file +_precompile_() From 17265e4c0c19b534fc962bfd574c124d78107b2a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 1 Nov 2020 21:00:19 +0100 Subject: [PATCH 266/356] add recipe for list of NamedTuples --- RecipesPipeline/src/user_recipe.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index a7b99327c..988c2e212 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -333,3 +333,16 @@ end # list of tuples @recipe f(v::AVec{<:Tuple}) = unzip(v) @recipe f(tup::Tuple) = [tup] + +# list of NamedTuples +@recipe function f(ntv::AVec{<:NamedTuple{K, Tuple{S, T}}}) where {K, S, T} + xguide --> string(K[1]) + yguide --> string(K[2]) + return Tuple.(ntv) +end +@recipe function f(ntv::AVec{<:NamedTuple{K, Tuple{R, S, T}}}) where {K, R, S, T} + xguide --> string(K[1]) + yguide --> string(K[2]) + zguide --> string(K[3]) + return Tuple.(ntv) +end \ No newline at end of file From bdab50451b5c6fbdec767ed985e8ae577384af9b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 1 Nov 2020 21:13:13 +0100 Subject: [PATCH 267/356] add newline --- RecipesPipeline/src/user_recipe.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 988c2e212..82424e63f 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -345,4 +345,4 @@ end yguide --> string(K[2]) zguide --> string(K[3]) return Tuple.(ntv) -end \ No newline at end of file +end From 3cf9034a7f7a35b050f4960440acb77d659d4d73 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 9 Nov 2020 18:45:44 +0100 Subject: [PATCH 268/356] update tagbot action --- RecipesBase/.github/workflows/TagBot.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RecipesBase/.github/workflows/TagBot.yml b/RecipesBase/.github/workflows/TagBot.yml index d77d3a0c3..778c06fed 100644 --- a/RecipesBase/.github/workflows/TagBot.yml +++ b/RecipesBase/.github/workflows/TagBot.yml @@ -1,9 +1,12 @@ name: TagBot on: - schedule: - - cron: 0 * * * * + issue_comment: + types: + - created + workflow_dispatch: jobs: TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' runs-on: ubuntu-latest steps: - uses: JuliaRegistries/TagBot@v1 From 1d99d2f04b112065dc6a528921ce2f3cc90da73b Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 1 Nov 2020 21:00:19 +0100 Subject: [PATCH 269/356] add recipe for list of NamedTuples --- RecipesPipeline/src/user_recipe.jl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 992eab235..16e8801d2 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -333,10 +333,22 @@ end @recipe f(v::AVec{<:Tuple}) = unzip(v) @recipe f(tup::Tuple) = [tup] +# list of NamedTuples +@recipe function f(ntv::AVec{<:NamedTuple{K, Tuple{S, T}}}) where {K, S, T} + xguide --> string(K[1]) + yguide --> string(K[2]) + return Tuple.(ntv) +end +@recipe function f(ntv::AVec{<:NamedTuple{K, Tuple{R, S, T}}}) where {K, R, S, T} + xguide --> string(K[1]) + yguide --> string(K[2]) + zguide --> string(K[3]) + return Tuple.(ntv) +end + @specialize function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) (xf, xinv), (yf, yinv) = ((scale_func(s), inverse_scale_func(s)) for s in (xscale, yscale)) xs, ys = PlotUtils.adapted_grid(yf ∘ f ∘ xinv, xf.((xmin, xmax))) xinv.(xs), yinv.(ys) -end \ No newline at end of file From 92a1d10602ca00b6ca0d6a55804ce0a942894bb4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 31 Oct 2020 21:13:57 +0100 Subject: [PATCH 270/356] move `warn_on_recipe_aliases!` from Plots and add some `@nospecialize` --- RecipesPipeline/src/user_recipe.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 16e8801d2..13ff0d8f8 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -352,3 +352,4 @@ function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax) (xf, xinv), (yf, yinv) = ((scale_func(s), inverse_scale_func(s)) for s in (xscale, yscale)) xs, ys = PlotUtils.adapted_grid(yf ∘ f ∘ xinv, xf.((xmin, xmax))) xinv.(xs), yinv.(ys) +end From c0adb7aa9174b89bf6404f6d2f7ecad0f1ed9cca Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 9 Nov 2020 19:04:59 +0100 Subject: [PATCH 271/356] update tagbot action --- RecipesPipeline/.github/workflows/TagBot.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/.github/workflows/TagBot.yml b/RecipesPipeline/.github/workflows/TagBot.yml index f8fd014ef..f49313b66 100644 --- a/RecipesPipeline/.github/workflows/TagBot.yml +++ b/RecipesPipeline/.github/workflows/TagBot.yml @@ -1,9 +1,12 @@ name: TagBot on: - schedule: - - cron: 0 * * * * + issue_comment: + types: + - created + workflow_dispatch: jobs: TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' runs-on: ubuntu-latest steps: - uses: JuliaRegistries/TagBot@v1 From 5460b65701b6458ff3b99b6f7b7bd5a01b3717bd Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 12 Nov 2020 12:25:03 +0100 Subject: [PATCH 272/356] Fix broken histogram and stepbins plotting --- RecipesPipeline/src/series.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index 239ec383f..cd0ced32b 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -94,7 +94,8 @@ _nobigs(v) = v z = _compute_z(x, y, z) if !isnothing(x) && isnothing(z) n = size(x,1) - !isnothing(y) && size(y,1) != n && error("Expects $n elements in each col of y, found $(size(y,1)).") + # Workaround: Allow y to be one element shorter than x to support binning edges in x, e.g. for histograms + !isnothing(y) && (size(y,1) != n && size(y,1) != n - 1) && error("Expects $n elements in each col of y, found $(size(y,1)).") end _nobigs(x), _nobigs(y), _nobigs(z) end From bf1f759c27ae53f0a276a7f84c11285f0427bc1f Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Thu, 12 Nov 2020 12:34:56 +0100 Subject: [PATCH 273/356] Increase package version to v0.2.1 --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index bd5a02694..cbad55a88 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.2" +version = "0.2.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From e892ce8af8b53370db514a1212b8d23a0725427b Mon Sep 17 00:00:00 2001 From: daschw Date: Thu, 12 Nov 2020 12:08:19 +0000 Subject: [PATCH 274/356] Update precompile_*.jl file --- .../linux/1.5/precompile_RecipesPipeline.jl | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl index 4c03bca95..cdaff6046 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl @@ -52,20 +52,21 @@ end function _precompile_() ccall(:jl_generating_output, Cint, ()) == 1 || return nothing Base.precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(RecipesPipeline._scaled_adapted_grid),Tuple{Array{Function,1},Base.RefValue{Symbol},Base.RefValue{Symbol},Float64,Float64}}}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},AbstractArray{T,2} where T}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Array{Function,1},Number,Number}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},RecipesPipeline.GroupBy,Any}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Type{RecipesPipeline.SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Type{SliceIt},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,AbstractArray,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,Surface,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1}}) Base.precompile(Tuple{typeof(RecipesPipeline._map_funcs),Function,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}) - Base.precompile(Tuple{typeof(RecipesPipeline._process_plotrecipes!),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._process_ribbon),Tuple{LinRange{Float64},LinRange{Float64}},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{AbstractArray{Float64,1},1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{Float64,1},1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{T,1} where T,1},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Float64,1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Float64,2},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Function,1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Int64,1},Dict{Symbol,Any}}) @@ -76,16 +77,22 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRange{Int64,Int64},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Array{Int64,2}},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline.recipe_pipeline!),Any,Any,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline.typerecipe_signature_string),typeof(atan)}) - Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Array{Float64,1},Array{Float64,1}},1}}) - Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Float64,Float64,Float64},1}}) - Base.precompile(Tuple{typeof(RecipesPipeline.unzip),Array{Tuple{Int64,Real},1}}) + Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),UnitRange{Int64},Dict{Symbol,Any}}) + Base.precompile(Tuple{typeof(RecipesPipeline.filter_data),Array{Float64,1},Array{Int64,1}}) + Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any,Vararg{Any,N} where N}) + Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{Dates.DateTime,1},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{Float64,1},Array{Float64,1},Surface{Array{Float64,2}}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{String,1},Array{String,1},Surface{Array{Float64,2}}}}}}}}) Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Base.OneTo{Int64},Base.OneTo{Int64},Surface{Array{Int64,2}}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{DataType,RecipesPipeline.Formatted{Array{Int64,1}},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) + Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{RecipesPipeline.Formatted{Array{Int64,1}},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{RecipesPipeline.GroupBy,Array{Float64,1}}}}}}}) Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(setindex!),RecipesPipeline.DefaultsDict,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Symbol}) + Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) + Base.precompile(Tuple{typeof(unzip),Array{Tuple{Array{Float64,1},Array{Float64,1}},1}}) + Base.precompile(Tuple{typeof(unzip),Array{Tuple{Int64,Int64},1}}) + Base.precompile(Tuple{typeof(unzip),Array{Tuple{Int64,Real},1}}) let fbody = try __lookup_kwbody__(which(RecipesPipeline._extract_group_attributes, (Array{String,1},Array{Float64,1},))) catch missing end if !ismissing(fbody) precompile(fbody, (Function,typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1},)) From 30f7b0facb9ddc52e29eb8bab4b904c6086e1bd5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 14 Nov 2020 19:52:32 +0100 Subject: [PATCH 275/356] add TestImages test dependency --- RecipesPipeline/Project.toml | 3 ++- RecipesPipeline/test/runtests.jl | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index cbad55a88..6421886e9 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -30,6 +30,7 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test"] +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages"] diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index e8416f934..68d7019ae 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -13,6 +13,7 @@ using StaticArrays using Statistics using StatsPlots using Test +using TestImages # makie_test_dir = joinpath(@__DIR__, "test_makie") # mkpath(makie_test_dir) From e5ced734e972c6136185085a01f0d794de2d8fbf Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Sun, 15 Nov 2020 11:28:54 -0500 Subject: [PATCH 276/356] refine friendly error (#75) --- RecipesPipeline/src/series.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index cd0ced32b..7099100d1 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -88,14 +88,13 @@ _nobigs(v::AVec{BigFloat}) = map(Float64, v) _nobigs(v::AVec{BigInt}) = map(Int64, v) _nobigs(v) = v -@noinline function _compute_xyz(x, y, z) +@noinline function _compute_xyz(x, y, z, nice_error=false) x = _compute_x(x, y, z) y = _compute_y(x, y, z) z = _compute_z(x, y, z) - if !isnothing(x) && isnothing(z) + if nice_error && isnothing(z) # don't touch 3D plots n = size(x,1) - # Workaround: Allow y to be one element shorter than x to support binning edges in x, e.g. for histograms - !isnothing(y) && (size(y,1) != n && size(y,1) != n - 1) && error("Expects $n elements in each col of y, found $(size(y,1)).") + !isnothing(y) && size(y,1) != n && error("Expects $n elements in each col of y, found $(size(y,1)).") end _nobigs(x), _nobigs(y), _nobigs(z) end @@ -126,7 +125,7 @@ struct SliceIt end # for each series and returns no arguments. @recipe function f(::Type{SliceIt}, x, y, z) @nospecialize - + nice_error = (x isa AbstractVector) && (y isa AbstractMatrix) # only check in the trivial case # handle data with formatting attached if typeof(x) <: Formatted xformatter := x.formatter @@ -161,7 +160,7 @@ struct SliceIt end # add a new series di = copy(plotattributes) xi, yi, zi = xs[mod1(i, mx)], ys[mod1(i, my)], zs[mod1(i, mz)] - di[:x], di[:y], di[:z] = _compute_xyz(xi, yi, zi) + di[:x], di[:y], di[:z] = _compute_xyz(xi, yi, zi, nice_error) # handle fillrange fr = fillranges[mod1(i, mf)] From 80aa1ac42e5a397343e308741b801900af666eef Mon Sep 17 00:00:00 2001 From: Moelf Date: Sun, 15 Nov 2020 16:55:03 +0000 Subject: [PATCH 277/356] Update precompile_*.jl file --- .../precompile/linux/1.5/precompile_RecipesPipeline.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl index cdaff6046..e6198e568 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl @@ -54,6 +54,7 @@ function _precompile_() Base.precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(RecipesPipeline._scaled_adapted_grid),Tuple{Array{Function,1},Base.RefValue{Symbol},Base.RefValue{Symbol},Float64,Float64}}}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},AbstractArray{T,2} where T}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Array{Function,1},Number,Number}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Function,Number,Number}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},RecipesPipeline.GroupBy,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Type{SliceIt},Any,Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,AbstractArray,Any}) @@ -63,6 +64,7 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesPipeline._process_ribbon),Tuple{LinRange{Float64},LinRange{Float64}},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(RecipesPipeline._scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{AbstractArray{Float64,1},1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{Float64,1},1},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{T,1} where T,1},Dict{Symbol,Any}}) @@ -77,7 +79,6 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRange{Int64,Int64},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Array{Int64,2}},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),UnitRange{Int64},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline.filter_data),Array{Float64,1},Array{Int64,1}}) Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any,Vararg{Any,N} where N}) Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any}) From 015dfbb77046f606159be109a464f548074d6116 Mon Sep 17 00:00:00 2001 From: Jeremy Bejanin Date: Sun, 7 Feb 2021 11:59:05 -0500 Subject: [PATCH 278/356] don't stringify argument to `warn_on_recipe_aliases!` early needs matching Plots changes --- RecipesPipeline/src/api.jl | 10 +++++----- RecipesPipeline/src/plot_recipe.jl | 4 ++-- RecipesPipeline/src/series_recipe.jl | 4 ++-- RecipesPipeline/src/type_recipe.jl | 8 ++++---- RecipesPipeline/src/user_recipe.jl | 2 +- RecipesPipeline/src/utils.jl | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index d6c0ee5c7..1981ee8b3 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -8,14 +8,14 @@ Warn if an alias is dedected in `plotattributes` after a recipe of type `recipe_type` is applied to 'args'. `recipe_type` is either `:user`, `:type`, `:plot` or `:series`. """ -function warn_on_recipe_aliases!(plt, plotattributes::AKW, recipe_type, signature_string) end -function warn_on_recipe_aliases!(plt, v::AbstractVector, recipe_type, signature_string) +function warn_on_recipe_aliases!(plt, plotattributes::AKW, recipe_type::Symbol, args) end +function warn_on_recipe_aliases!(plt, v::AbstractVector, recipe_type::Symbol, args) for x in v - warn_on_recipe_aliases!(plt, x, recipe_type, signature_string) + warn_on_recipe_aliases!(plt, x, recipe_type, args) end end -function warn_on_recipe_aliases!(plt, rd::RecipeData, recipe_type, signature_string) - warn_on_recipe_aliases!(plt, rd.plotattributes, recipe_type, signature_string) +function warn_on_recipe_aliases!(plt, rd::RecipeData, recipe_type::Symbol, args) + warn_on_recipe_aliases!(plt, rd.plotattributes, recipe_type, args) end diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 70a511e11..b6e779899 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -31,7 +31,7 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) st = kw[:seriestype] st = kw[:seriestype] = type_alias(plt, st) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - warn_on_recipe_aliases!(plt, datalist, :plot, plotrecipe_signature_string(st)) + warn_on_recipe_aliases!(plt, datalist, :plot, st) for data in datalist preprocess_attributes!(plt, data.plotattributes) if data.plotattributes[:seriestype] == st @@ -49,4 +49,4 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) return end -@specialize \ No newline at end of file +@specialize diff --git a/RecipesPipeline/src/series_recipe.jl b/RecipesPipeline/src/series_recipe.jl index 45289b2f6..f799a9192 100644 --- a/RecipesPipeline/src/series_recipe.jl +++ b/RecipesPipeline/src/series_recipe.jl @@ -48,7 +48,7 @@ function _process_seriesrecipe(plt, plotattributes) # get a sub list of series for this seriestype x, y, z = plotattributes[:x], plotattributes[:y], plotattributes[:z] datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, x, y, z) - warn_on_recipe_aliases!(plt, datalist, :series, seriesrecipe_signature_string(st)) + warn_on_recipe_aliases!(plt, datalist, :series, st) # assuming there was no error, recursively apply the series recipes for data in datalist @@ -67,4 +67,4 @@ function _process_seriesrecipe(plt, plotattributes) nothing end -@specialize \ No newline at end of file +@specialize diff --git a/RecipesPipeline/src/type_recipe.jl b/RecipesPipeline/src/type_recipe.jl index 4013611e6..97cda682a 100644 --- a/RecipesPipeline/src/type_recipe.jl +++ b/RecipesPipeline/src/type_recipe.jl @@ -18,7 +18,7 @@ function _apply_type_recipe(plotattributes, v, letter) plt = plotattributes[:plot_object] preprocess_axis_args!(plt, plotattributes, letter) rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v) - warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, typerecipe_signature_string(v)) + warn_on_recipe_aliases!(plotattributes[:plot_object], plotattributes, :type, v) postprocess_axis_args!(plt, plotattributes, letter) return rdvec[1].args[1] end @@ -31,13 +31,13 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter) preprocess_axis_args!(plt, plotattributes, letter) # First we try to apply an array type recipe. w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1] - warn_on_recipe_aliases!(plt, plotattributes, :type, typerecipe_signature_string(v)) + warn_on_recipe_aliases!(plt, plotattributes, :type, v) # If the type did not change try it element-wise if typeof(v) == typeof(w) isempty(skipmissing(v)) && return Float64[] x = first(skipmissing(v)) args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args - warn_on_recipe_aliases!(plt, plotattributes, :type, typerecipe_signature_string(x)) + warn_on_recipe_aliases!(plt, plotattributes, :type, x) postprocess_axis_args!(plt, plotattributes, letter) if length(args) == 2 && all(arg -> arg isa Function, args) numfunc, formatter = args @@ -73,4 +73,4 @@ _apply_type_recipe( ) = v _apply_type_recipe(plotattributes, v::Nothing, letter) = v -@specialize \ No newline at end of file +@specialize diff --git a/RecipesPipeline/src/user_recipe.jl b/RecipesPipeline/src/user_recipe.jl index 13ff0d8f8..35880a7da 100644 --- a/RecipesPipeline/src/user_recipe.jl +++ b/RecipesPipeline/src/user_recipe.jl @@ -35,7 +35,7 @@ function _process_userrecipes!(plt, plotattributes, args) else rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) - warn_on_recipe_aliases!(plt, rd_list, :user, userrecipe_signature_string(next_series.args...)) + warn_on_recipe_aliases!(plt, rd_list, :user, next_series.args) prepend!(still_to_process, rd_list) end end diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 3a45df70d..f923d41ae 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -229,11 +229,11 @@ _map_funcs(fs::AVec{F}, u::AVec) where {F <: Function} = [map(f, u) for f in fs] @nospecialize -function userrecipe_signature_string(args...) +function userrecipe_signature_string(args) return string("(::", join(string.(typeof.(args)), ", ::"), ")") end typerecipe_signature_string(::T) where T = "(::Type{$T}, ::$T)" plotrecipe_signature_string(st) = "(::Type{Val{:$st}}, ::AbstractPlot)" seriesrecipe_signature_string(st) = "(::Type{Val{:$st}}, x, y, z)" -@specialize \ No newline at end of file +@specialize From f84eb88f2561b9bec8217a6d05a6dbc9cdc58dd8 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 7 Feb 2021 19:50:55 +0100 Subject: [PATCH 279/356] minor release --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 6421886e9..2007cdd01 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.2.1" +version = "0.3.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From ee958b49862b07db73b815150db0b535e7650ecc Mon Sep 17 00:00:00 2001 From: Jeremy Bejanin Date: Tue, 9 Feb 2021 10:26:55 -0500 Subject: [PATCH 280/356] add `@nospecialize` annotations --- RecipesPipeline/src/api.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/api.jl b/RecipesPipeline/src/api.jl index 1981ee8b3..af01c3d46 100644 --- a/RecipesPipeline/src/api.jl +++ b/RecipesPipeline/src/api.jl @@ -8,13 +8,13 @@ Warn if an alias is dedected in `plotattributes` after a recipe of type `recipe_type` is applied to 'args'. `recipe_type` is either `:user`, `:type`, `:plot` or `:series`. """ -function warn_on_recipe_aliases!(plt, plotattributes::AKW, recipe_type::Symbol, args) end -function warn_on_recipe_aliases!(plt, v::AbstractVector, recipe_type::Symbol, args) +function warn_on_recipe_aliases!(plt, plotattributes::AKW, recipe_type::Symbol, @nospecialize(args)) end +function warn_on_recipe_aliases!(plt, v::AbstractVector, recipe_type::Symbol, @nospecialize(args)) for x in v warn_on_recipe_aliases!(plt, x, recipe_type, args) end end -function warn_on_recipe_aliases!(plt, rd::RecipeData, recipe_type::Symbol, args) +function warn_on_recipe_aliases!(plt, rd::RecipeData, recipe_type::Symbol, @nospecialize(args)) warn_on_recipe_aliases!(plt, rd.plotattributes, recipe_type, args) end From 2985fd823dc968aef8ba75c95f2429a5fef5a889 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 9 Feb 2021 18:14:23 +0100 Subject: [PATCH 281/356] release --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 2007cdd01..1c878ee02 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.0" +version = "0.3.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 6cddc83b3d3b9a8e88dba45b5fd82bcb7204350d Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 1 Apr 2021 11:01:09 +0200 Subject: [PATCH 282/356] update CompileBot --- RecipesPipeline/.github/workflows/SnoopCompile.yml | 2 +- RecipesPipeline/deps/SnoopCompile/snoop_bench.jl | 9 +-------- RecipesPipeline/deps/SnoopCompile/snoop_bot.jl | 9 +-------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 3d71a8e62..4827977f8 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: version: # NOTE: the versions below should match those in your botconfig - - '1.5' + - '1' os: # NOTE: should match the os setting of your botconfig - ubuntu-latest arch: diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl index 9f1551b37..30ec6f2c6 100644 --- a/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bench.jl @@ -1,10 +1,3 @@ using CompileBot -snoop_bench( - BotConfig( - "RecipesPipeline", - yml_path= "SnoopCompile.yml", - else_os = "linux", - else_version = "1.5", - ) -) +snoop_bench(BotConfig("RecipesPipeline")) diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl index c5eb2d63d..9a50c18f4 100644 --- a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl @@ -1,10 +1,3 @@ using CompileBot -snoop_bot( - BotConfig( - "RecipesPipeline", - yml_path= "SnoopCompile.yml", - else_os = "linux", - else_version = "1.5", - ) -) +snoop_bot(BotConfig("RecipesPipeline")) From 9c530e9a84b067cbfc40e06b8c0f36fb7878c8b7 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 1 Apr 2021 11:06:44 +0200 Subject: [PATCH 283/356] update TESTCMD in CI --- RecipesPipeline/.github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 31bcc7a4c..3b0f00f80 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -52,10 +52,10 @@ jobs: # TESTCMD - name: Default TESTCMD - run: echo ::set-env name=TESTCMD::"julia" + run: echo "TESTCMD=julia" >> $GITHUB_ENV - name: Ubuntu TESTCMD if: startsWith(matrix.os,'ubuntu') - run: echo ::set-env name=TESTCMD::"xvfb-run --auto-servernum julia" + run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV # Julia Dependencies - name: Install Julia dependencies From 608d9a3710c65703a494749e5c8969c7092eb2aa Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 1 Apr 2021 11:16:41 +0200 Subject: [PATCH 284/356] fix TESTCMD in compilebot action --- RecipesPipeline/.github/workflows/SnoopCompile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 4827977f8..7674c6061 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -40,10 +40,10 @@ jobs: # TESTCMD - name: Default TESTCMD - run: echo ::set-env name=TESTCMD::"julia" + run: echo "TESTCMD=julia" >> $GITHUB_ENV - name: Ubuntu TESTCMD if: startsWith(matrix.os,'ubuntu') - run: echo ::set-env name=TESTCMD::"xvfb-run --auto-servernum julia" + run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV # Generate precompile files - name: Generating precompile files From d17d697a83d7c4ad893da2798f53a2153399c2e5 Mon Sep 17 00:00:00 2001 From: daschw Date: Thu, 1 Apr 2021 09:36:00 +0000 Subject: [PATCH 285/356] Update precompile_*.jl file --- .../precompile/precompile_RecipesPipeline.jl | 106 ++++++++++++++++++ RecipesPipeline/src/precompile_includer.jl | 32 ++---- 2 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl new file mode 100644 index 000000000..00cbe4d03 --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl @@ -0,0 +1,106 @@ +# 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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractMatrix{T} where T}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{T} where T,AbstractVector{T} where T,Function}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Function,Number,Number}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) + Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String},Vector{Float64}}) + Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) + Base.precompile(Tuple{typeof(_process_ribbon),Tuple{LinRange{Float64}, LinRange{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) + Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) + Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Real},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{String},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{T} where T},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(filter_data!),Dict{Symbol, Any},Vector{Int64}}) + Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}}) + let fbody = try __lookup_kwbody__(which(_extract_group_attributes, (Vector{String},Vector{Float64},))) catch missing end + if !ismissing(fbody) + precompile(fbody, (Function,typeof(_extract_group_attributes),Vector{String},Vector{Float64},)) + end + end +end diff --git a/RecipesPipeline/src/precompile_includer.jl b/RecipesPipeline/src/precompile_includer.jl index 10d539b67..854051567 100644 --- a/RecipesPipeline/src/precompile_includer.jl +++ b/RecipesPipeline/src/precompile_includer.jl @@ -2,33 +2,19 @@ should_precompile = true # Don't edit the following! Instead change the script for `snoop_bot`. -ismultios = true -ismultiversion = true +ismultios = false +ismultiversion = false # precompile_enclosure @static if !should_precompile # nothing elseif !ismultios && !ismultiversion - include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") - _precompile_() -else - @static if Sys.islinux() - @static if v"1.5.0-DEV" <= VERSION <= v"1.5.9" - include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") - _precompile_() - else - include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") - _precompile_() - end - - else - @static if v"1.5.0-DEV" <= VERSION <= v"1.5.9" - include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") - _precompile_() - else - include("../deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl") - _precompile_() - end - + @static if isfile(joinpath( + @__DIR__, + "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl", + )) + include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") + _precompile_() end +else end # precompile_enclosure From f98716b367a29b8c716ce2262faecf6d8ca2df31 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 1 Apr 2021 11:41:52 +0200 Subject: [PATCH 286/356] release --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 1c878ee02..434917b8b 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.1" +version = "0.3.2" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 608ff4e32306dd9c5d403440d8bda0ebfb3de727 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 11 May 2021 20:43:56 +0200 Subject: [PATCH 287/356] Update README.md [skip ci] --- RecipesBase/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index a92729947..b0e3de85b 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -4,6 +4,7 @@ [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaPlots.github.io/RecipesBase.jl/dev) [![Build Status](https://travis-ci.org/JuliaPlots/RecipesBase.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/RecipesBase.jl) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots) +[![deps](https://juliahub.com/docs/RecipesBase/deps.svg)](https://juliahub.com/ui/Packages/RecipesBase/8e2Mm?t=2) ### Author: Thomas Breloff (@tbreloff) From cb180f10c33990dbdff55b2d1ed9a6b4c79b911f Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 20 Jun 2021 21:31:50 +0200 Subject: [PATCH 288/356] don't catch all the MethodErrors (#87) * don't catch all the MethodErrors * remove `@show` --- RecipesPipeline/src/plot_recipe.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index b6e779899..06e2db956 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -40,7 +40,7 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) push!(still_to_process, data.plotattributes) end catch err - if isa(err, MethodError) + if err isa MethodError && occursin("plot recipe", err.args) push!(kw_list, kw) else rethrow() From 18b06f71e27cd573d7431e07c7f8ff0d3a540d55 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 23 Jun 2021 10:37:24 +0200 Subject: [PATCH 289/356] 0.3.3 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 434917b8b..de6eeb3cc 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.2" +version = "0.3.3" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 3de401bb2f7937292d73baa381a3385f48f58332 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 5 Jul 2021 01:32:59 +0200 Subject: [PATCH 290/356] add mesh3d for GR --- RecipesPipeline/src/utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index f923d41ae..e510cfd07 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -181,6 +181,7 @@ for st in ( :surface, :volume, :wireframe, + :mesh3d ) @eval needs_3d_axes(::Type{Val{Symbol($(string(st)))}}) = true end From dccfd6e158daae0b42b5085fa8ca716f1f895b80 Mon Sep 17 00:00:00 2001 From: t-bltg <13423344+t-bltg@users.noreply.github.com> Date: Tue, 6 Jul 2021 21:28:03 +0200 Subject: [PATCH 291/356] v0.3.4 --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index de6eeb3cc..ddaa95c87 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.3" +version = "0.3.4" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From ac45a7e5135debfe3a6485729f1a9ae50022238b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 18 Aug 2021 14:01:06 -0500 Subject: [PATCH 292/356] Small improvement in inferrability (#82) --- RecipesBase/src/RecipesBase.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index e25365cc2..b62b6f328 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -108,8 +108,9 @@ function create_kw_body(func_signature::Expr) args = func_signature.args[2:end] kw_body = Expr(:block) cleanup_body = Expr(:block) - if isa(args[1], Expr) && args[1].head == :parameters - for kwpair in args[1].args + arg1 = args[1] + if isa(arg1, Expr) && arg1.head == :parameters + for kwpair in arg1.args k, v = kwpair.args if isa(k, Expr) && k.head == :(::) k = k.args[1] From 37f1ec79e2083ad0c1abe371931ed4fbeeaf6340 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 18 Aug 2021 21:01:52 +0200 Subject: [PATCH 293/356] 1.1.2 [skip ci] --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index a567d6cad..c1fb6bf34 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.1.1" +version = "1.1.2" [compat] julia = "1" From d386b075392efef39e4aa1b38c4edf9ac212a6a7 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Wed, 25 Aug 2021 23:02:21 +0200 Subject: [PATCH 294/356] CI: tentative fix --- RecipesPipeline/.github/workflows/CI.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 3b0f00f80..269aaece7 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -63,7 +63,8 @@ jobs: # Run tests - name: Run tests - run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true);' + run: | + $TESTCMD --project -e 'using Pkg; Pkg.build("Plots"); Pkg.test(coverage=true);' Skip: if: "contains(github.event.head_commit.message, '[skip ci]')" From d9a361daa6729558dd309f1e72fc060e5ecb6d43 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Wed, 25 Aug 2021 23:58:02 +0200 Subject: [PATCH 295/356] CI: add LinearAlgebra (#96) Co-authored-by: t-bltg --- RecipesPipeline/.github/workflows/CI.yml | 2 +- RecipesPipeline/Project.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 269aaece7..7c3bac712 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -64,7 +64,7 @@ jobs: # Run tests - name: Run tests run: | - $TESTCMD --project -e 'using Pkg; Pkg.build("Plots"); Pkg.test(coverage=true);' + $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true);' Skip: if: "contains(github.event.head_commit.message, '[skip ci]')" diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index ddaa95c87..320231bf6 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -31,6 +31,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages"] +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra"] From 6bf92dcd4bf6cb5dcc653b561328473fb3a8ad32 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 26 Aug 2021 08:22:17 -0400 Subject: [PATCH 296/356] Test for error value from `apply_recipe` fallback. (#95) --- RecipesPipeline/src/plot_recipe.jl | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 06e2db956..3630629f2 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -31,15 +31,20 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) st = kw[:seriestype] st = kw[:seriestype] = type_alias(plt, st) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - warn_on_recipe_aliases!(plt, datalist, :plot, st) - for data in datalist - preprocess_attributes!(plt, data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + if !isnothing(datalist) + warn_on_recipe_aliases!(plt, datalist, :plot, st) + for data in datalist + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + end + push!(still_to_process, data.plotattributes) end - push!(still_to_process, data.plotattributes) + else + push!(kw_list, kw) end catch err + # the try/catch block can be removed when Plots.jl makes the compensating change if err isa MethodError && occursin("plot recipe", err.args) push!(kw_list, kw) else From 9516e7c9d0f81bf12c831425015412d617c7376c Mon Sep 17 00:00:00 2001 From: t-bltg Date: Thu, 26 Aug 2021 16:49:50 +0200 Subject: [PATCH 297/356] v0.3.5 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 320231bf6..dfe5ddf20 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.4" +version = "0.3.5" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 672d4798a9791790946fd107759589c570681dce Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 28 Aug 2021 13:04:02 +0200 Subject: [PATCH 298/356] Add `Downloads` test dependency Complement https://github.com/JuliaPlots/Plots.jl/pull/3766 --- RecipesPipeline/Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index dfe5ddf20..5c540985b 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -32,6 +32,7 @@ StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra"] +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads"] From 02c99ff961de0c07842ba1f396ce55de84f7c14d Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 28 Aug 2021 07:32:53 -0400 Subject: [PATCH 299/356] Remove try/catch needed for compatibility with Plots.jl v1.21.0 and earlier (#97) --- RecipesPipeline/src/plot_recipe.jl | 35 +++++++++++------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 3630629f2..5f6916094 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -1,4 +1,4 @@ -# # Plot Recipes +# Plot Recipes @nospecialize @@ -27,29 +27,20 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) push!(kw_list, kw) return end - try - st = kw[:seriestype] - st = kw[:seriestype] = type_alias(plt, st) - datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - if !isnothing(datalist) - warn_on_recipe_aliases!(plt, datalist, :plot, st) - for data in datalist - preprocess_attributes!(plt, data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") - end - push!(still_to_process, data.plotattributes) + st = kw[:seriestype] + st = kw[:seriestype] = type_alias(plt, st) + datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) + if !isnothing(datalist) + warn_on_recipe_aliases!(plt, datalist, :plot, st) + for data in datalist + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") end - else - push!(kw_list, kw) - end - catch err - # the try/catch block can be removed when Plots.jl makes the compensating change - if err isa MethodError && occursin("plot recipe", err.args) - push!(kw_list, kw) - else - rethrow() + push!(still_to_process, data.plotattributes) end + else + push!(kw_list, kw) end return end From 655f2f534c21b33bf52994290158ef0fba3e56d4 Mon Sep 17 00:00:00 2001 From: Mike Keehan <21029749+mdkeehan@users.noreply.github.com> Date: Sat, 28 Aug 2021 23:54:33 +1200 Subject: [PATCH 300/356] Improve groups perf from O(MxN) to O(M) (#98) --- RecipesPipeline/Project.toml | 3 +- RecipesPipeline/src/group.jl | 16 +++++++---- RecipesPipeline/test/runtests.jl | 11 +++++--- RecipesPipeline/test/test_group.jl | 44 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 RecipesPipeline/test/test_group.jl diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 5c540985b..37a51c7bc 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -33,6 +33,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads"] +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads", "BenchmarkTools"] \ No newline at end of file diff --git a/RecipesPipeline/src/group.jl b/RecipesPipeline/src/group.jl index 778846226..6acfbe6f5 100644 --- a/RecipesPipeline/src/group.jl +++ b/RecipesPipeline/src/group.jl @@ -8,15 +8,19 @@ end # this is when given a vector-type of values to group by function _extract_group_attributes(v::AVec, args...; legend_entry = string) - group_labels = collect(unique(sort(v))) - n = length(group_labels) - if n > 100 - @warn("You created n=$n groups... Is that intended?") + res = Dict{eltype(v),Vector{Int}}() + for (i,label) in enumerate(v) + if haskey(res,label) + push!(res[label],i) + else + res[label] = [i] + end end - group_indices = Vector{Int}[filter(i -> v[i] == glab, eachindex(v)) for glab in group_labels] + group_labels = sort(collect(keys(res))) + group_indices = [res[i] for i in group_labels] + GroupBy(map(legend_entry, group_labels), group_indices) end - legend_entry_from_tuple(ns::Tuple) = join(ns, ' ') # this is when given a tuple of vectors of values to group by diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 68d7019ae..6fbd397fe 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -22,11 +22,14 @@ using TestImages # @testset "Makie integration" begin cd(makie_test_dir) do # include("makie.jl") # end end - @testset "Plots tests" begin - for i in eachindex(Plots._examples) - if i ∉ Plots._backend_skips[:gr] - @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot + @testset "Plots" begin + for i in eachindex(Plots._examples) + if i ∉ Plots._backend_skips[:gr] + @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot + end end end + @testset "Group" begin + include("test_group.jl") end end diff --git a/RecipesPipeline/test/test_group.jl b/RecipesPipeline/test/test_group.jl new file mode 100644 index 000000000..63b24ff7d --- /dev/null +++ b/RecipesPipeline/test/test_group.jl @@ -0,0 +1,44 @@ +using Test +using BenchmarkTools +using RecipesPipeline + +function _extract_group_attributes_old_slow_known_good_implementation(v, args...; legend_entry = string) + group_labels = collect(unique(sort(v))) + n = length(group_labels) + #if n > 100 + # @warn("You created n=$n groups... Is that intended?") + #end + group_indices = Vector{Int}[filter(i -> v[i] == glab, eachindex(v)) for glab in group_labels] + RecipesPipeline.GroupBy(map(legend_entry, group_labels), group_indices) +end + +sc = [ "C","C","C","A", "A", "A","B","B","D"] +mc = rand([ "xx"*"$(i%6)" for i in 1:6],300) +mp = rand([ "xx"*"$(i%73)" for i in 1:73],1000) +lp = [ "xx"*"$(i%599)" for i in 1:2000] + +@testset "All" begin + @testset "Correctness" begin + res1 = _extract_group_attributes_old_slow_known_good_implementation(sc) + res2 = RecipesPipeline._extract_group_attributes(sc) + @test res1.group_labels == res2.group_labels + @test res1.group_indices == res2.group_indices + end + @testset "Correctness (medium)" begin + res1 = _extract_group_attributes_old_slow_known_good_implementation(mc) + res2 = RecipesPipeline._extract_group_attributes(mc) + @test res1.group_labels == res2.group_labels + @test res1.group_indices == res2.group_indices + end + @testset "Performance (medium)" begin + t1 = @benchmark res1 = _extract_group_attributes_old_slow_known_good_implementation(mp) + t2 = @benchmark res2 = RecipesPipeline._extract_group_attributes(mp) + @test !BenchmarkTools.isregression(judge(median(t2),median(t1))) + end + @testset "Performance (large ish)" begin + t1 = @benchmark res1 = _extract_group_attributes_old_slow_known_good_implementation(lp) + t2 = @benchmark res2 = RecipesPipeline._extract_group_attributes(lp) + @test BenchmarkTools.isimprovement(judge(median(t2),median(t1))) + end +end + From 001c22ee61f455fd2556648122ecbfb2a3c39f81 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 28 Aug 2021 14:07:34 +0200 Subject: [PATCH 301/356] Update MakieRecipes URL --- RecipesPipeline/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/README.md b/RecipesPipeline/README.md index 80297d6ec..89518ef94 100644 --- a/RecipesPipeline/README.md +++ b/RecipesPipeline/README.md @@ -10,10 +10,10 @@ [![Codecov](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/RecipesPipeline.jl) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://julialang.zulipchat.com/#narrow/stream/236493-plots) -#### [WIP] An implementation of the recipe pipeline from Plots +#### An implementation of the recipe pipeline from Plots This package was factored out of Plots.jl to allow any other plotting package to use the recipe pipeline. In short, the extremely lightweight RecipesBase.jl package can be depended on by any package to define "recipes": plot specifications of user-defined types, as well as custom plot types. RecipePipeline.jl contains the machinery to translate these recipes to full specifications for a plot. -The package is intended to be used by consumer plotting packages, and is currently used by [Plots.jl](https://github.com/JuliaPlots/Plots.jl) (v.1.1.0 and above) and [MakieRecipes.jl](https://github.com/JuliaPlots/MakieRecipes.jl), a package that bridges RecipesBase recipes to [Makie.jl](https://github.com/JuliaPlots/Makie.jl). +The package is intended to be used by consumer plotting packages, and is currently used by [Plots.jl](https://github.com/JuliaPlots/Plots.jl) (v.1.1.0 and above) and [MakieRecipes.jl](https://github.com/JuliaPlots/Makie.jl/tree/master/MakieRecipes), a package that bridges RecipesBase recipes to [Makie.jl](https://github.com/JuliaPlots/Makie.jl). Current functionality: ```julia From 467663300b4886aecf6960045215e96c5fd50133 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 28 Aug 2021 14:18:08 +0200 Subject: [PATCH 302/356] Update precompile_*.jl file (#91) --- .../precompile/precompile_RecipesPipeline.jl | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl index 00cbe4d03..52bfea34b 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl @@ -13,57 +13,6 @@ macro warnpcfail(ex::Expr) 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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractMatrix{T} where T}) @@ -92,15 +41,9 @@ function _precompile_() Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{T} where T},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(filter_data!),Dict{Symbol, Any},Vector{Int64}}) Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}}) - let fbody = try __lookup_kwbody__(which(_extract_group_attributes, (Vector{String},Vector{Float64},))) catch missing end - if !ismissing(fbody) - precompile(fbody, (Function,typeof(_extract_group_attributes),Vector{String},Vector{Float64},)) - end - end end From 0250a8be446990f9c32011d18eac6ee63d71c6a7 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 28 Aug 2021 14:18:45 +0200 Subject: [PATCH 303/356] v0.3.6 [skip ci] --- RecipesPipeline/Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 37a51c7bc..4f1f539ff 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.5" +version = "0.3.6" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" @@ -36,4 +36,4 @@ Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads", "BenchmarkTools"] \ No newline at end of file +test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads", "BenchmarkTools"] From 4489fd5039225d987f1b1873559d824d900610ba Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 30 Aug 2021 20:21:53 +0200 Subject: [PATCH 304/356] Revert try/catch for patch version --- RecipesPipeline/src/plot_recipe.jl | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 5f6916094..9ac405ed4 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -27,21 +27,28 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) push!(kw_list, kw) return end - st = kw[:seriestype] - st = kw[:seriestype] = type_alias(plt, st) - datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - if !isnothing(datalist) - warn_on_recipe_aliases!(plt, datalist, :plot, st) - for data in datalist - preprocess_attributes!(plt, data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + try + st = kw[:seriestype] + st = kw[:seriestype] = type_alias(plt, st) + datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) + if !isnothing(datalist) + warn_on_recipe_aliases!(plt, datalist, :plot, st) + for data in datalist + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") + end + push!(still_to_process, data.plotattributes) end - push!(still_to_process, data.plotattributes) + else + push!(kw_list, kw) + end + catch err + if err isa MethodError && occursin("plot recipe", err.args) + push!(kw_list, kw) + else + rethrow() end - else - push!(kw_list, kw) - end return end From c04cca14e0ff21a793e09c03437d6bedbb9b9e36 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 30 Aug 2021 20:37:16 +0200 Subject: [PATCH 305/356] v0.3.7 (#101) [skip ci] --- RecipesPipeline/Project.toml | 2 +- RecipesPipeline/src/plot_recipe.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 4f1f539ff..fd3e507a5 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.6" +version = "0.3.7" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index 9ac405ed4..d988cd896 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -49,6 +49,7 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) else rethrow() end + end return end From 40060beb8f3f8d2f55339a82f0055ab022073b29 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 30 Aug 2021 22:52:26 +0200 Subject: [PATCH 306/356] v0.4.0 (#102) [skip ci] --- RecipesPipeline/Project.toml | 10 +++++----- RecipesPipeline/src/plot_recipe.jl | 32 +++++++++++------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index fd3e507a5..be6bee892 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.3.7" +version = "0.4.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" @@ -16,24 +16,24 @@ RecipesBase = "0.8, 1.0" julia = "1" [extras] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" [targets] test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads", "BenchmarkTools"] diff --git a/RecipesPipeline/src/plot_recipe.jl b/RecipesPipeline/src/plot_recipe.jl index d988cd896..5f6916094 100644 --- a/RecipesPipeline/src/plot_recipe.jl +++ b/RecipesPipeline/src/plot_recipe.jl @@ -27,28 +27,20 @@ function _process_plotrecipe(plt, kw, kw_list, still_to_process) push!(kw_list, kw) return end - try - st = kw[:seriestype] - st = kw[:seriestype] = type_alias(plt, st) - datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - if !isnothing(datalist) - warn_on_recipe_aliases!(plt, datalist, :plot, st) - for data in datalist - preprocess_attributes!(plt, data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") - end - push!(still_to_process, data.plotattributes) + st = kw[:seriestype] + st = kw[:seriestype] = type_alias(plt, st) + datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) + if !isnothing(datalist) + warn_on_recipe_aliases!(plt, datalist, :plot, st) + for data in datalist + preprocess_attributes!(plt, data.plotattributes) + if data.plotattributes[:seriestype] == st + error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") end - else - push!(kw_list, kw) - end - catch err - if err isa MethodError && occursin("plot recipe", err.args) - push!(kw_list, kw) - else - rethrow() + push!(still_to_process, data.plotattributes) end + else + push!(kw_list, kw) end return end From 1e0bfdcbefaf29f7c2d245b35c310b4fe84959d5 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Tue, 14 Sep 2021 10:19:11 -0400 Subject: [PATCH 307/356] Avoid Vararg UnionAll dispatch (#104) * Avoid Vararg UnionAll dispatch Fixes https://github.com/JuliaPlots/RecipesPipeline.jl/issues/103 * fix fix Co-authored-by: Simon Christ --- RecipesPipeline/src/utils.jl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index e510cfd07..7286d6dcc 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -208,13 +208,7 @@ inverse_scale_func(scale::Symbol) = # ## Unzip # -------------------------------- -for i in 2:4 - @eval begin - unzip(v::AVec{<:Tuple{Vararg{T, $i} where T}}) = - $(Expr(:tuple, (:([t[$j] for t in v]) for j in 1:i)...)) - end -end - +unzip(v::AVec{<:Tuple}) = tuple((([t[j] for t in v]) for j in 1:length(v[1]))...) # -------------------------------- # ## Map functions on vectors From 890b9bf9a1ffc52dacb517d90fee5622fa0571d7 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 14 Sep 2021 16:50:06 +0200 Subject: [PATCH 308/356] 0.4.1 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index be6bee892..3bb557b94 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.4.0" +version = "0.4.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 5fdd9ac7f53168f77ca08589b0768c16be5a3eef Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 23 Nov 2021 15:58:27 +0100 Subject: [PATCH 309/356] move layout macro from plots (#85) --- RecipesBase/src/RecipesBase.jl | 137 +++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index b62b6f328..126e683e1 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -6,6 +6,7 @@ export @series, @userplot, @shorthands, + @layout, RecipeData, AbstractBackend, AbstractPlot, @@ -16,6 +17,9 @@ abstract type AbstractBackend end abstract type AbstractPlot{T<:AbstractBackend} end abstract type AbstractLayout end +const KW = Dict{Symbol,Any} +const AKW = AbstractDict{Symbol,Any} + # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.plot since RecipesBase is the common # dependency of the Plots ecosystem @@ -32,6 +36,8 @@ function animate end # can add their own definition of RecipesBase.is_key_supported(k::Symbol) function is_key_supported end +function grid end + # a placeholder to establish the name so that other packages (Plots.jl for example) # can add their own definition of RecipesBase.group_as_matrix(t) group_as_matrix(t) = false @@ -435,6 +441,137 @@ function recipetype(s::Val{T}, args...) where T error("No type recipe defined for type $T. You may need to load StatsPlots") 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 = Matrix(undef, 1, $(length(expr.args))) + $( + [ + :(cell[1, $i] = $(create_grid(v))) for + (i, v) in enumerate(expr.args) + ]... + ) + cell + end + ) + + elseif expr.head == :curly + create_grid_curly(expr) + else + # if it's something else, just return that (might be an existing layout?) + esc(expr) + end +end + +function create_grid_vcat(expr::Expr) + rowsizes = map(rowsize, expr.args) + rmin, rmax = extrema(rowsizes) + if rmin > 0 && rmin == rmax + # we have a grid... build the whole thing + # note: rmin is the number of columns + nr = length(expr.args) + nc = rmin + body = Expr(:block) + for r in 1:nr + arg = expr.args[r] + if isrow(arg) + for (c, item) in enumerate(arg.args) + push!(body.args, :(cell[$r, $c] = $(create_grid(item)))) + end + else + push!(body.args, :(cell[$r, 1] = $(create_grid(arg)))) + end + end + :( + let cell = Matrix(undef, $nr, $nc) + $body + cell + end + ) + else + # otherwise just build one row at a time + :( + let cell = Matrix(undef, $(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) + :(( + 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) + :((label = $(QuoteNode(s)), blank = $(s == :_))) +end + +macro layout(mat::Expr) + create_grid(mat) +end include("precompile.jl") end # module From ac27e789a9d604fa689a0cb42e93b78f6202d8c7 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 23 Nov 2021 16:00:39 +0100 Subject: [PATCH 310/356] 1.2.0 [skip ci] --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index c1fb6bf34..6e60e1b34 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.1.2" +version = "1.2.0" [compat] julia = "1" From 7af02484cb92c4c32b6e70fbf566294cb2b5f5c1 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 25 Nov 2021 10:12:52 +0100 Subject: [PATCH 311/356] remove pct --- RecipesBase/Project.toml | 2 +- RecipesBase/src/RecipesBase.jl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index 6e60e1b34..f6a94275e 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.2.0" +version = "1.2.1" [compat] julia = "1" diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 126e683e1..980d7efcb 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -452,9 +452,9 @@ function add_layout_pct!(kw::AKW, v::Expr, idx::Integer, nidx::Integer) if length(v.args) == 3 && isa(num, Number) units = v.args[3] if units == :h - return kw[:h] = num * pct + return kw[:h] = num elseif units == :w - return kw[:w] = num * pct + return kw[:w] = num elseif units in (:pct, :px, :mm, :cm, :inch) idx == 1 && (kw[:w] = v) (idx == 2 || nidx == 1) && (kw[:h] = v) @@ -467,8 +467,8 @@ 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) + idx == 1 && (kw[:w] = v) + (idx == 2 || nidx == 1) && (kw[:h] = v) end isrow(v) = isa(v, Expr) && v.head in (:hcat, :row) From fedd54366826a60cb153769f5e41ddc6742aeca6 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 25 Nov 2021 10:13:39 +0100 Subject: [PATCH 312/356] 1.2.1 [skip ci] --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index f6a94275e..67b355e68 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.2.1" +version = "1.2.1`" [compat] julia = "1" From 7645dfbed077f7828902c873cfb4d5ece7e8f319 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 25 Nov 2021 10:15:11 +0100 Subject: [PATCH 313/356] Update Project.toml --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index 67b355e68..f6a94275e 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.2.1`" +version = "1.2.1" [compat] julia = "1" From b312fe659ebfaaf7e312770f3e58eee5d23b4b4c Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 12 Jan 2022 14:10:51 +0100 Subject: [PATCH 314/356] respect defaults for fillrange and ribbon (#106) * respect defaults for fillrange and ribbon * remove fillrange and ribbon handling from RecipesPipeline * update ci * set version --- RecipesPipeline/.github/workflows/CI.yml | 8 +++-- .../.github/workflows/SnoopCompile.yml | 3 +- RecipesPipeline/Project.toml | 2 +- .../linux/1.5/precompile_RecipesPipeline.jl | 1 - .../precompile/precompile_RecipesPipeline.jl | 1 - .../deps/SnoopCompile/snoop_bot.jl | 8 ++++- RecipesPipeline/src/series.jl | 32 ------------------- 7 files changed, 16 insertions(+), 39 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 7c3bac712..09d14bee8 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -2,6 +2,7 @@ name: ci on: push: + - master pull_request: defaults: @@ -21,8 +22,8 @@ jobs: fail-fast: false matrix: version: - - '1' - - 'nightly' + - '1.6' # LTS + - '1.7' # latest stable os: - ubuntu-latest - windows-latest @@ -30,6 +31,9 @@ jobs: arch: - x64 # - x86 + include: + - version: 'nightly' + os: ubuntu-latest steps: diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 7674c6061..349e104b3 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -20,7 +20,8 @@ jobs: fail-fast: false matrix: version: # NOTE: the versions below should match those in your botconfig - - '1' + - '1.6' # ⎤ + - '1.7' # ⎦ <<< keep these versions in sync with deps/SnoopCompile/snoop_bot_config.jl os: # NOTE: should match the os setting of your botconfig - ubuntu-latest arch: diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 3bb557b94..9586cf620 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.4.1" +version = "0.5.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl index e6198e568..8cecf3eef 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl @@ -61,7 +61,6 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,Surface,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1}}) Base.precompile(Tuple{typeof(RecipesPipeline._map_funcs),Function,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}) - Base.precompile(Tuple{typeof(RecipesPipeline._process_ribbon),Tuple{LinRange{Float64},LinRange{Float64}},Dict{Symbol,Any}}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(RecipesPipeline._scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl index 52bfea34b..0d2878f88 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl @@ -26,7 +26,6 @@ function _precompile_() Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String},Vector{Float64}}) Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) - Base.precompile(Tuple{typeof(_process_ribbon),Tuple{LinRange{Float64}, LinRange{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl index 9a50c18f4..7f6e18121 100644 --- a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl @@ -1,3 +1,9 @@ using CompileBot -snoop_bot(BotConfig("RecipesPipeline")) +botconfig = BotConfig( + "RecipesPipeline", + version = [v"1.6", v"1.7"], # <<< keep versions in sync with .github/workflows/SnoopCompile.yml + # else_version = v"1.8", +) + +snoop_bot(botconfig) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index 7099100d1..f621c6f8f 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -52,21 +52,6 @@ function _series_data_vector(v::AMat{<:DataPoint}, plotattributes) end end -# -------------------------------------------------------------------- -# Fillranges & ribbons - - -_process_fillrange(range::Number, plotattributes) = [range] -_process_fillrange(range, plotattributes) = _series_data_vector(range, plotattributes) - -_process_ribbon(ribbon::Number, plotattributes) = [ribbon] -_process_ribbon(ribbon, plotattributes) = _series_data_vector(ribbon, plotattributes) -# ribbon as a tuple: (lower_ribbons, upper_ribbons) -_process_ribbon(ribbon::Tuple{S, T}, plotattributes) where {S, T} = collect(zip( - _series_data_vector(ribbon[1], plotattributes), - _series_data_vector(ribbon[2], plotattributes), -)) - # -------------------------------------------------------------------- @@ -118,8 +103,6 @@ _compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing! # ensure we dispatch to the slicer struct SliceIt end -# TODO: Should ribbon and fillrange be handled by the plotting package? - # The `SliceIt` recipe finishes user and type recipe processing. # It splits processed data into individual series data, stores in copied `plotattributes` # for each series and returns no arguments. @@ -144,13 +127,6 @@ struct SliceIt end ys = _series_data_vector(y, plotattributes) zs = _series_data_vector(z, plotattributes) - fr = pop!(plotattributes, :fillrange, nothing) - fillranges = _process_fillrange(fr, plotattributes) - mf = length(fillranges) - - rib = pop!(plotattributes, :ribbon, nothing) - ribbons = _process_ribbon(rib, plotattributes) - mr = length(ribbons) mx = length(xs) my = length(ys) @@ -162,14 +138,6 @@ struct SliceIt end xi, yi, zi = xs[mod1(i, mx)], ys[mod1(i, my)], zs[mod1(i, mz)] di[:x], di[:y], di[:z] = _compute_xyz(xi, yi, zi, nice_error) - # handle fillrange - fr = fillranges[mod1(i, mf)] - di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr - - # handle ribbons - rib = ribbons[mod1(i, mr)] - di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib - push!(series_list, RecipeData(di, ())) end end From 0f5fc7f190f92198659c42fab295263d64bc11d9 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 12 Jan 2022 14:15:35 +0100 Subject: [PATCH 315/356] Update CI.yml --- RecipesPipeline/.github/workflows/CI.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 09d14bee8..46697f1ac 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -2,7 +2,8 @@ name: ci on: push: - - master + branches: + - master pull_request: defaults: From 472d62d155b472f55c386a1b3cec97c9c90f1fcb Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 20 Jan 2022 14:08:54 +0100 Subject: [PATCH 316/356] move documentation to gh-actions --- .../.github/workflows/Documentation.yml | 29 +++++++++++++++ RecipesBase/.travis.yml | 30 ---------------- RecipesBase/appveyor.yml | 36 ------------------- 3 files changed, 29 insertions(+), 66 deletions(-) create mode 100644 RecipesBase/.github/workflows/Documentation.yml delete mode 100644 RecipesBase/.travis.yml delete mode 100644 RecipesBase/appveyor.yml diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml new file mode 100644 index 000000000..9e13ca7fd --- /dev/null +++ b/RecipesBase/.github/workflows/Documentation.yml @@ -0,0 +1,29 @@ +name: Documentation + +on: + push: + branches: + - master + tags: '*' + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@latest + with: + version: '1.6' + - name: Install dependencies + run: + - apt-get update -y + - apt-get install -y qt5-default + - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + - name: Build and deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token + run: + - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); + Pkg.instantiate()' + - xvfb-run julia --project=docs/ docs/make.jl diff --git a/RecipesBase/.travis.yml b/RecipesBase/.travis.yml deleted file mode 100644 index 457839ec2..000000000 --- a/RecipesBase/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Documentation: http://docs.travis-ci.com/user/languages/julia/ -language: julia -os: - - linux - - osx -julia: - - 1.0 - - 1.4 - - nightly -notifications: - email: false -# uncomment the following lines to override the default test script -# script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'import Pkg; Pkg.clone(pwd()); Pkg.build("RecipesBase"); Pkg.test("RecipesBase"; coverage=true)' - -jobs: - include: - - stage: "Documentation" - julia: 1.4 - os: linux - addons: - apt: - packages: - - qt5-default - script: - - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); - Pkg.instantiate()' - - xvfb-run julia --project=docs/ docs/make.jl - after_success: skip diff --git a/RecipesBase/appveyor.yml b/RecipesBase/appveyor.yml deleted file mode 100644 index cc15d5721..000000000 --- a/RecipesBase/appveyor.yml +++ /dev/null @@ -1,36 +0,0 @@ -environment: - matrix: - - julia_version: 1.1 - - julia_version: latest - -platform: - - x86 # 32-bit - - x64 # 64-bit - -## uncomment the following lines to allow failures on nightly julia -## (tests will run but not make your overall status red) -#matrix: -# allow_failures: -# - julia_version: latest - -branches: - only: - - master - - /release-.*/ - -notifications: - - provider: Email - on_build_success: false - on_build_failure: false - on_build_status_changed: false - -install: - - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) - -build_script: - - echo "%JL_BUILD_SCRIPT%" - - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" - -test_script: - - echo "%JL_TEST_SCRIPT%" - - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" From 7ae933930be470b83fc20a33921ff9e8dcf2fa81 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 20 Jan 2022 14:11:10 +0100 Subject: [PATCH 317/356] update run commands --- RecipesBase/.github/workflows/Documentation.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml index 9e13ca7fd..d5d982007 100644 --- a/RecipesBase/.github/workflows/Documentation.yml +++ b/RecipesBase/.github/workflows/Documentation.yml @@ -16,14 +16,14 @@ jobs: with: version: '1.6' - name: Install dependencies - run: - - apt-get update -y - - apt-get install -y qt5-default - - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + run: | + apt-get update -y + apt-get install -y qt5-default + julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - name: Build and deploy env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token - run: - - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); + run: | + julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - xvfb-run julia --project=docs/ docs/make.jl + xvfb-run julia --project=docs/ docs/make.jl From 5de679f46f56ff1135cd7dfe1eb73526584d365d Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 20 Jan 2022 14:12:53 +0100 Subject: [PATCH 318/356] Update Documentation.yml --- RecipesBase/.github/workflows/Documentation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml index d5d982007..687aa2cc4 100644 --- a/RecipesBase/.github/workflows/Documentation.yml +++ b/RecipesBase/.github/workflows/Documentation.yml @@ -17,8 +17,8 @@ jobs: version: '1.6' - name: Install dependencies run: | - apt-get update -y - apt-get install -y qt5-default + sudo apt-get update -y + sudo apt-get install -y qt5-default julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - name: Build and deploy env: From 34cb0653d0ede001cf0505342bbb75fd963efd71 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 23 Feb 2022 21:02:31 +0100 Subject: [PATCH 319/356] Allow `NanMath` 1.0 - bump version (#108) Co-authored-by: t-bltg --- .../.github/workflows/CompatHelper.yml | 17 +++++++++++++++++ RecipesPipeline/Project.toml | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 RecipesPipeline/.github/workflows/CompatHelper.yml diff --git a/RecipesPipeline/.github/workflows/CompatHelper.yml b/RecipesPipeline/.github/workflows/CompatHelper.yml new file mode 100644 index 000000000..d4d64580a --- /dev/null +++ b/RecipesPipeline/.github/workflows/CompatHelper.yml @@ -0,0 +1,17 @@ +name: CompatHelper + +on: + schedule: + - cron: '00 00 * * *' + +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }} # optional + run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 9586cf620..df3af9137 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.5.0" +version = "0.5.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" @@ -10,7 +10,7 @@ PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] -NaNMath = "0.3" +NaNMath = "0.3, 1" PlotUtils = "0.6.5, 1" RecipesBase = "0.8, 1.0" julia = "1" From 2d78415e851356a8777ac54bebea038d07c68f33 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Wed, 23 Mar 2022 16:02:11 +0100 Subject: [PATCH 320/356] Fix `unzip` for empty vectors (#110) --- RecipesPipeline/.github/workflows/CI.yml | 9 ++++-- RecipesPipeline/src/utils.jl | 2 +- RecipesPipeline/test/runtests.jl | 37 +++++++++++++++--------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 46697f1ac..719964b31 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -68,8 +68,13 @@ jobs: # Run tests - name: Run tests - run: | - $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true);' + run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true)' + + # Codecov + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v2 + with: + file: lcov.info Skip: if: "contains(github.event.head_commit.message, '[skip ci]')" diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 7286d6dcc..3087b58f1 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -208,7 +208,7 @@ inverse_scale_func(scale::Symbol) = # ## Unzip # -------------------------------- -unzip(v::AVec{<:Tuple}) = tuple((([t[j] for t in v]) for j in 1:length(v[1]))...) +unzip(v::AVec{<:Tuple}) = map(x->getfield.(v, x), fieldnames(eltype(v))) # -------------------------------- # ## Map functions on vectors diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 6fbd397fe..524c28d48 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -15,21 +15,32 @@ using StatsPlots using Test using TestImages -# makie_test_dir = joinpath(@__DIR__, "test_makie") -# mkpath(makie_test_dir) +@testset "unzip" begin + x, y, z = unzip([(1., 2., 3.), (1., 2., 3.)]) + @test all(x .== 1.) && all(y .== 2.) && all(z .== 3.) + x, y, z = unzip(Tuple{Float64, Float64, Float64}[]) + @test isempty(x) && isempty(y) && isempty(z) +end + +@testset "group" begin + include("test_group.jl") +end -@testset "RecipesPipeline.jl" begin - # @testset "Makie integration" begin cd(makie_test_dir) do - # include("makie.jl") - # end end - @testset "Plots" begin - for i in eachindex(Plots._examples) - if i ∉ Plots._backend_skips[:gr] - @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot - end +@testset "plots" begin + for i in eachindex(Plots._examples) + if i ∉ Plots._backend_skips[:gr] + @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot end end - @testset "Group" begin - include("test_group.jl") +end + +#= +makie_test_dir = joinpath(@__DIR__, "test_makie") +mkpath(makie_test_dir) + +@testset "Makie integration" begin + cd(makie_test_dir) do + include("makie.jl") end end +=# From c4fa63c23984a321a61beb01112f30b811638e17 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Wed, 23 Mar 2022 16:02:50 +0100 Subject: [PATCH 321/356] 0.5.2 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index df3af9137..adf63cf9b 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.5.1" +version = "0.5.2" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 3eb33dd7df77744e22e7471703b378b7178f7957 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Mon, 28 Mar 2022 23:53:11 +0900 Subject: [PATCH 322/356] update url with https://docs.juliaplots.org/stable/generated/supported/#Keyword-Arguments (#89) --- RecipesBase/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/README.md b/RecipesBase/README.md index b0e3de85b..f559309b5 100644 --- a/RecipesBase/README.md +++ b/RecipesBase/README.md @@ -46,7 +46,7 @@ Really there's very little that *couldn't* be mapped to a useful visualization. I challenge you to create the pictures that are worth a thousand words. For more information about Plots, see [the docs](http://juliaplots.github.io/), and be sure to reference -the [supported keywords](http://docs.juliaplots.org/latest/supported/#keyword-arguments). +the [supported keywords](https://docs.juliaplots.org/stable/generated/supported/#Keyword-Arguments). For additional examples of recipes in the wild, see [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl). Ask questions on [gitter](https://gitter.im/tbreloff/Plots.jl) or in the issues. From 2514f831886da65d427bce961002665403bf072b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 9 Jul 2022 18:17:22 +0200 Subject: [PATCH 323/356] Update precompile_*.jl file (#109) Co-authored-by: t-bltg --- .../1.6/precompile_RecipesPipeline.jl | 52 ++++++++++++++++++ .../1.7/precompile_RecipesPipeline.jl | 53 +++++++++++++++++++ RecipesPipeline/src/precompile_includer.jl | 31 +++++++++-- 3 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl create mode 100644 RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl new file mode 100644 index 000000000..94f130446 --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl @@ -0,0 +1,52 @@ +# 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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractMatrix{T} where T}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{T} where T,AbstractVector{T} where T,Function}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Function,Number,Number}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) + Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) + Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) + Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) + Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) + Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Real},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{String},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{T} where T},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) + Base.precompile(Tuple{typeof(setindex!),DefaultsDict,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64, Float64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}}) + isdefined(RecipesPipeline, Symbol("#11#12")) && Base.precompile(Tuple{getfield(RecipesPipeline, Symbol("#11#12")),Int64}) +end diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl new file mode 100644 index 000000000..522869ebf --- /dev/null +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl @@ -0,0 +1,53 @@ +# 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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractMatrix}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector,AbstractVector,Function}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractVector{<:Tuple}}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Function,Number,Number}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) + Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Vector{Float64},UnitRange{Int64},Bool}) + Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) + Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}) + Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) + Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) + Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) + Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Real},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{String},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{Float64}},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64, Float64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) + Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}}) + isdefined(RecipesPipeline, Symbol("#11#12")) && Base.precompile(Tuple{getfield(RecipesPipeline, Symbol("#11#12")),Int64}) +end diff --git a/RecipesPipeline/src/precompile_includer.jl b/RecipesPipeline/src/precompile_includer.jl index 854051567..4c740bf62 100644 --- a/RecipesPipeline/src/precompile_includer.jl +++ b/RecipesPipeline/src/precompile_includer.jl @@ -3,18 +3,39 @@ should_precompile = true # Don't edit the following! Instead change the script for `snoop_bot`. ismultios = false -ismultiversion = false +ismultiversion = true # precompile_enclosure @static if !should_precompile # nothing elseif !ismultios && !ismultiversion - @static if isfile(joinpath( - @__DIR__, - "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl", - )) + @static if isfile( + joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl"), + ) include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") _precompile_() end else + @static if v"1.6.0-DEV" <= VERSION <= v"1.6.9" + @static if isfile( + joinpath( + @__DIR__, + "../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.jl", + ), + ) + include("../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.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_RecipesPipeline.jl", + ), + ) + include("../deps/SnoopCompile/precompile//1.7/precompile_RecipesPipeline.jl") + _precompile_() + end + else + end end # precompile_enclosure From ecbc492b38c5ad443dfbe15ab6a0c197649fbbf7 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 18:26:23 +0200 Subject: [PATCH 324/356] run snoopcompile on pust to master only --- RecipesPipeline/.github/workflows/SnoopCompile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 349e104b3..09dec2f2d 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -3,7 +3,7 @@ name: SnoopCompile on: push: branches: - # - 'master' # NOTE: to run the bot only on pushes to master + - 'master' # NOTE: to run the bot only on pushes to master defaults: run: From 413c81f77dbd07e39c37df3ee49450d3c7e56af1 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 18:27:11 +0200 Subject: [PATCH 325/356] update compat bounds (#111) --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index adf63cf9b..fe609496f 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -12,7 +12,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" [compat] NaNMath = "0.3, 1" PlotUtils = "0.6.5, 1" -RecipesBase = "0.8, 1.0" +RecipesBase = "0.8, 1" julia = "1" [extras] From 4df32cc385e4b7f33dc32a9ec16797d4c83830b8 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 18:29:40 +0200 Subject: [PATCH 326/356] 0.6.0 [skip ci] --- RecipesPipeline/Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index fe609496f..94ed6a12f 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.5.2" +version = "0.6.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" @@ -13,7 +13,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" NaNMath = "0.3, 1" PlotUtils = "0.6.5, 1" RecipesBase = "0.8, 1" -julia = "1" +julia = "1.6" [extras] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" From 9f9035bd4b03e05203e7985de4ddfb0f7c75427a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 9 Jul 2022 18:56:18 +0200 Subject: [PATCH 327/356] Update precompile_*.jl file (#112) Co-authored-by: t-bltg --- .../precompile/1.6/precompile_RecipesPipeline.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl index 94f130446..08f326973 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl @@ -24,26 +24,20 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) - Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) - Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(_series_data_vector),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(_series_data_vector),Vector{Int64},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Real},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{String},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Vector{T} where T},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) - Base.precompile(Tuple{typeof(setindex!),DefaultsDict,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Symbol}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Float64, Float64, Float64}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Int64}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) From f619899938dc7476c59d955135da04e2d4384df3 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 18:57:50 +0200 Subject: [PATCH 328/356] `SnoopCompile` labels --- RecipesPipeline/.github/workflows/SnoopCompile.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 09dec2f2d..555b21964 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -69,15 +69,17 @@ jobs: uses: actions/download-artifact@v2 - name: CompileBot postprocess - run: julia -e 'using Pkg; Pkg.add( PackageSpec(name = "CompileBot", version = "1") ); using CompileBot; CompileBot.postprocess();' + run: julia -e 'using Pkg; Pkg.add(PackageSpec(name = "CompileBot", version = "1")); using CompileBot; CompileBot.postprocess();' - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: Update precompile_*.jl file - title: "[AUTO] Update precompiles" - labels: SnoopCompile + title: "[AUTO] Update precompiles [skip ci]" + labels: | + SnoopCompile + no changelog branch: "SnoopCompile_AutoPR" From 22adc11d92d09c3798c9c7649903738798213851 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Sun, 10 Jul 2022 04:06:00 +0900 Subject: [PATCH 329/356] use ssh key for `TagBot` (#91) --- RecipesBase/.github/workflows/TagBot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/RecipesBase/.github/workflows/TagBot.yml b/RecipesBase/.github/workflows/TagBot.yml index 778c06fed..f49313b66 100644 --- a/RecipesBase/.github/workflows/TagBot.yml +++ b/RecipesBase/.github/workflows/TagBot.yml @@ -12,3 +12,4 @@ jobs: - uses: JuliaRegistries/TagBot@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} From 196ce034363c2ff1ce151f9de35d553d69944002 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Sun, 10 Jul 2022 04:06:41 +0900 Subject: [PATCH 330/356] fix julia scripts in markdown (#90) * add missing language specification in md * replace type with struct --- RecipesBase/docs/src/internals.md | 2 +- RecipesBase/docs/src/types.md | 10 +++++----- RecipesBase/src/RecipesBase.jl | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/RecipesBase/docs/src/internals.md b/RecipesBase/docs/src/internals.md index 46c91a3c1..057d36607 100644 --- a/RecipesBase/docs/src/internals.md +++ b/RecipesBase/docs/src/internals.md @@ -9,7 +9,7 @@ defines RecipesBase.apply_recipe(plotattributes, args...; kwargs...) ``` returning a `Vector{RecipeData}` where `RecipeData` holds the `plotattributes` Dict and the arguments returned in [`@recipe`](@ref) or in [`@series`](@ref). -``` +```julia struct RecipeData plotattributes::AbstractDict{Symbol,Any} args::Tuple diff --git a/RecipesBase/docs/src/types.md b/RecipesBase/docs/src/types.md index c69c96f7e..a69ed9b19 100644 --- a/RecipesBase/docs/src/types.md +++ b/RecipesBase/docs/src/types.md @@ -104,11 +104,11 @@ We have already seen an example for a user recipe in the syntax section above. User recipes can also be used to define a custom visualization without necessarily wishing to plot a custom type. For this purpose we can create a type to dispatch on. The [`@userplot`](@ref) macro is a convenient way to do this. -``` +```julia @userplot MyPlot ``` expands to -``` +```julia mutable struct MyPlot args end @@ -119,7 +119,7 @@ myplot!(args...; kw...) = plot!(MyPlot(args); kw...) To check `args` type, define a struct with type parameters. -``` +```julia @userplot struct MyPlot{T<:Tuple{AbstractVector}} args::T end @@ -259,11 +259,11 @@ We can define a seriestype `:yscaleplot`, that automatically shows data with a l end ``` We can call it with `plot(...; ..., seriestype = :yscaleplot)` or we can define a shorthand with the [`@shorthands`](@ref) macro. -``` +```julia @shorthands myseries ``` expands to -``` +```julia export myseries, myseries! myseries(args...; kw...) = plot(args...; kw..., seriestype = :myseries) myseries!(args...; kw...) = plot!(args...; kw..., seriestype = :myseries) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 980d7efcb..f69c8a484 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -219,11 +219,11 @@ should replace the current arguments. An example: -``` +```julia using RecipesBase # Our custom type that we want to display -type T end +struct T end @recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) markershape --> :auto, :require @@ -301,7 +301,7 @@ end """ Meant to be used inside a recipe to add additional RecipeData objects to the list: -``` +```julia @recipe function f(::T) # everything get this setting linecolor --> :red @@ -334,7 +334,7 @@ end """ You can easily define your own plotting recipes with convenience methods: -``` +```julia @userplot GroupHist @recipe function f(gh::GroupHist) From 3ec21c8e7da45cc7d92ee080af288054646468eb Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 21:51:22 +0200 Subject: [PATCH 331/356] fix `SnoopCompile` (#113) * update compat bounds * run snoop on master only * update precompile --- RecipesPipeline/.github/workflows/CI.yml | 7 +- .../.github/workflows/SnoopCompile.yml | 13 ++- RecipesPipeline/Project.toml | 2 +- .../1.6/precompile_RecipesPipeline.jl | 4 + .../1.7/precompile_RecipesPipeline.jl | 4 +- .../linux/1.5/precompile_RecipesPipeline.jl | 101 ------------------ .../deps/SnoopCompile/snoop_bot.jl | 4 +- RecipesPipeline/src/precompile_includer.jl | 38 +++---- 8 files changed, 31 insertions(+), 142 deletions(-) delete mode 100644 RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index 719964b31..c28adb1b3 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -15,6 +15,7 @@ jobs: if: "!contains(github.event.head_commit.message, '[skip ci]')" env: GKS_ENCODING: "utf8" + GKSwstype: "nul" name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -39,7 +40,7 @@ jobs: steps: # Setup environment - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: julia-actions/setup-julia@latest with: version: ${{ matrix.version }} @@ -71,8 +72,8 @@ jobs: run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true)' # Codecov - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v2 + - uses: julia-actions/julia-processcoverage@latest + - uses: codecov/codecov-action@v3 with: file: lcov.info diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml index 555b21964..2ec9fc19f 100644 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ b/RecipesPipeline/.github/workflows/SnoopCompile.yml @@ -28,16 +28,15 @@ jobs: - x64 steps: # Setup environment - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: julia-actions/setup-julia@latest with: version: ${{ matrix.version }} - name: Install dependencies run: | - 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();' - + julia --project -e 'using Pkg; Pkg.instantiate()' + julia -e 'using Pkg; Pkg.add(PackageSpec(name = "CompileBot", version = "1")); Pkg.develop(path=pwd()); using CompileBot; CompileBot.addtestdep()' # TESTCMD - name: Default TESTCMD @@ -55,7 +54,7 @@ jobs: run: $TESTCMD --project -e 'include("deps/SnoopCompile/snoop_bench.jl")' # NOTE: optional, if have benchmark file - name: Upload all - uses: actions/upload-artifact@v2.0.1 + uses: actions/upload-artifact@v3 with: path: ./ @@ -64,9 +63,9 @@ jobs: needs: SnoopCompile runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download all - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 - name: CompileBot postprocess run: julia -e 'using Pkg; Pkg.add(PackageSpec(name = "CompileBot", version = "1")); using CompileBot; CompileBot.postprocess();' diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 94ed6a12f..587026186 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -26,8 +26,8 @@ Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl index 08f326973..565cc9c35 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl @@ -24,14 +24,18 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),StepRange{Int64, Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),Vector{Int64},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Real},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{String},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Union{Missing, Int64}},Dict{Symbol, Any}}) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl index 522869ebf..eb1a31fee 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl @@ -22,19 +22,17 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{SliceIt},Any,Any,Any}) + Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{typeof(sin)},typeof(sin)}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) - Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Vector{Float64},UnitRange{Int64},Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) - Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(_series_data_vector),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl deleted file mode 100644 index 8cecf3eef..000000000 --- a/RecipesPipeline/deps/SnoopCompile/precompile/linux/1.5/precompile_RecipesPipeline.jl +++ /dev/null @@ -1,101 +0,0 @@ -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{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(RecipesPipeline._scaled_adapted_grid),Tuple{Array{Function,1},Base.RefValue{Symbol},Base.RefValue{Symbol},Float64,Float64}}}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},AbstractArray{T,2} where T}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Array{Function,1},Number,Number}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Function,Number,Number}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},RecipesPipeline.GroupBy,Any}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol,Any},Type{SliceIt},Any,Any,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,AbstractArray,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline._apply_type_recipe),Any,Surface,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1}}) - Base.precompile(Tuple{typeof(RecipesPipeline._map_funcs),Function,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}) - Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipe),Any,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline._process_seriesrecipes!),Any,Any}) - Base.precompile(Tuple{typeof(RecipesPipeline._scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{AbstractArray{Float64,1},1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{Float64,1},1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Array{T,1} where T,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Float64,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Float64,2},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Function,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Int64,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Real,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{String,1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Array{Union{Missing, Int64},1},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Int64,Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),StepRange{Int64,Int64},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline._series_data_vector),Surface{Array{Int64,2}},Dict{Symbol,Any}}) - Base.precompile(Tuple{typeof(RecipesPipeline.filter_data),Array{Float64,1},Array{Int64,1}}) - Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any,Vararg{Any,N} where N}) - Base.precompile(Tuple{typeof(RecipesPipeline.userrecipe_signature_string),Any}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{Dates.DateTime,1},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{Float64,1},Array{Float64,1},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Array{String,1},Array{String,1},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{Base.OneTo{Int64},Base.OneTo{Int64},Surface{Array{Int64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{DataType,RecipesPipeline.Formatted{Array{Int64,1}},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{RecipesPipeline.Formatted{Array{Int64,1}},UnitRange{Int64},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{RecipesPipeline.GroupBy,Array{Float64,1}}}}}}}) - Base.precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(string),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(typeof),Tuple{Tuple{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Surface{Array{Float64,2}}}}}}}}) - Base.precompile(Tuple{typeof(recipe_pipeline!),Any,Any,Any}) - Base.precompile(Tuple{typeof(unzip),Array{Tuple{Array{Float64,1},Array{Float64,1}},1}}) - Base.precompile(Tuple{typeof(unzip),Array{Tuple{Int64,Int64},1}}) - Base.precompile(Tuple{typeof(unzip),Array{Tuple{Int64,Real},1}}) - let fbody = try __lookup_kwbody__(which(RecipesPipeline._extract_group_attributes, (Array{String,1},Array{Float64,1},))) catch missing end - if !ismissing(fbody) - precompile(fbody, (Function,typeof(RecipesPipeline._extract_group_attributes),Array{String,1},Array{Float64,1},)) - end - end -end diff --git a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl index 7f6e18121..772472946 100644 --- a/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl +++ b/RecipesPipeline/deps/SnoopCompile/snoop_bot.jl @@ -2,8 +2,8 @@ using CompileBot botconfig = BotConfig( "RecipesPipeline", - version = [v"1.6", v"1.7"], # <<< keep versions in sync with .github/workflows/SnoopCompile.yml - # else_version = v"1.8", + version = ["1.6", "1.7"], # <<< keep versions in sync with .github/workflows/SnoopCompile.yml + # else_version = "1.8", ) snoop_bot(botconfig) diff --git a/RecipesPipeline/src/precompile_includer.jl b/RecipesPipeline/src/precompile_includer.jl index 4c740bf62..d1a6b2267 100644 --- a/RecipesPipeline/src/precompile_includer.jl +++ b/RecipesPipeline/src/precompile_includer.jl @@ -1,4 +1,4 @@ -should_precompile = true +should_precompile = true # Don't edit the following! Instead change the script for `snoop_bot`. @@ -8,34 +8,22 @@ ismultiversion = true @static if !should_precompile # nothing elseif !ismultios && !ismultiversion - @static if isfile( - joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl"), - ) + @static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl")) include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") _precompile_() end else - @static if v"1.6.0-DEV" <= VERSION <= v"1.6.9" - @static if isfile( - joinpath( - @__DIR__, - "../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.jl", - ), - ) - include("../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.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_RecipesPipeline.jl", - ), - ) - include("../deps/SnoopCompile/precompile//1.7/precompile_RecipesPipeline.jl") - _precompile_() - end - else + @static if v"1.6.0-DEV" <= VERSION <= v"1.6.9" + @static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.jl")) + include("../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.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_RecipesPipeline.jl")) + include("../deps/SnoopCompile/precompile//1.7/precompile_RecipesPipeline.jl") + _precompile_() + end +else end end # precompile_enclosure From e387a2f16d3e4ffbd9e8bc7ffd7abaf1d9095e07 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 9 Jul 2022 22:31:09 +0200 Subject: [PATCH 332/356] Update precompile_*.jl file (#114) Co-authored-by: t-bltg --- .../1.6/precompile_RecipesPipeline.jl | 1 + RecipesPipeline/src/precompile_includer.jl | 38 ++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl index 565cc9c35..5777ecfc3 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl @@ -26,6 +26,7 @@ function _precompile_() Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) + Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) diff --git a/RecipesPipeline/src/precompile_includer.jl b/RecipesPipeline/src/precompile_includer.jl index d1a6b2267..4c740bf62 100644 --- a/RecipesPipeline/src/precompile_includer.jl +++ b/RecipesPipeline/src/precompile_includer.jl @@ -1,4 +1,4 @@ -should_precompile = true +should_precompile = true # Don't edit the following! Instead change the script for `snoop_bot`. @@ -8,22 +8,34 @@ ismultiversion = true @static if !should_precompile # nothing elseif !ismultios && !ismultiversion - @static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl")) + @static if isfile( + joinpath(@__DIR__, "../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl"), + ) include("../deps/SnoopCompile/precompile/precompile_RecipesPipeline.jl") _precompile_() end else - @static if v"1.6.0-DEV" <= VERSION <= v"1.6.9" - @static if isfile(joinpath(@__DIR__, "../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.jl")) - include("../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.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_RecipesPipeline.jl")) - include("../deps/SnoopCompile/precompile//1.7/precompile_RecipesPipeline.jl") - _precompile_() - end -else + @static if v"1.6.0-DEV" <= VERSION <= v"1.6.9" + @static if isfile( + joinpath( + @__DIR__, + "../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.jl", + ), + ) + include("../deps/SnoopCompile/precompile//1.6/precompile_RecipesPipeline.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_RecipesPipeline.jl", + ), + ) + include("../deps/SnoopCompile/precompile//1.7/precompile_RecipesPipeline.jl") + _precompile_() + end + else end end # precompile_enclosure From 8309431acd33e11457380ae7acd78a5410239de3 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 9 Jul 2022 22:38:53 +0200 Subject: [PATCH 333/356] 0.6.1 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 587026186..84583e12d 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.0" +version = "0.6.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 59ca2e7c42aaa645b993160659ec658d37f8faf4 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Mon, 11 Jul 2022 18:26:45 +0200 Subject: [PATCH 334/356] fix plotting `Union{Missing,Real}` arrays (#116) --- RecipesPipeline/src/series.jl | 14 +++++++++++--- RecipesPipeline/test/runtests.jl | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/RecipesPipeline/src/series.jl b/RecipesPipeline/src/series.jl index f621c6f8f..2adcd4ec5 100644 --- a/RecipesPipeline/src/series.jl +++ b/RecipesPipeline/src/series.jl @@ -10,9 +10,17 @@ _prepare_series_data(::Nothing) = nothing _prepare_series_data(t::Tuple{T, T}) where {T <: Number} = t _prepare_series_data(f::Function) = f _prepare_series_data(ar::AbstractRange{<:Number}) = ar -function _prepare_series_data(a::AbstractArray{<:MaybeNumber}) - f = isimmutable(a) ? replace : replace! - a = f(x -> ismissing(x) || isinf(x) ? NaN : x, map(float, a)) +function _prepare_series_data(a::AbstractArray{T}) where {T<:MaybeNumber} + # Get a non-missing AbstractFloat type for the array + # There may be a better way to do this? + F = typeof(float(zero(nonmissingtype(T)))) + # Create a new array with this type to write to + float_a = similar(a, F) + # Replace missing and inf values with NaN + broadcast!(float_a, a) do x + ismissing(x) || isinf(x) ? NaN : x + end + return float_a end _prepare_series_data(a::AbstractArray{<:Missing}) = fill(NaN, axes(a)) _prepare_series_data(a::AbstractArray{<:MaybeString}) = diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 524c28d48..ff3f15567 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -15,6 +15,29 @@ using StatsPlots using Test using TestImages +import RecipesPipeline: _prepare_series_data + +@testset "_prepare_series_data" begin + @test_throws ErrorException _prepare_series_data(:test) + @test _prepare_series_data(nothing) === nothing + @test _prepare_series_data((1.0, 2.0)) === (1.0, 2.0) + @test _prepare_series_data(identity) === identity + @test _prepare_series_data(1:5:10) === 1:5:10 + a = ones(Union{Missing,Float64}, 100, 100); + sd = _prepare_series_data(a) + @test sd == a + @test eltype(sd) == Float64 + a .= missing + sd = _prepare_series_data(a) + @test eltype(sd) == Float64 + @test all(isnan, sd) + a = fill(missing, 100, 100) + sd = _prepare_series_data(a) + @test eltype(sd) == Float64 + @test all(isnan, sd) + # TODO String, Volume etc +end + @testset "unzip" begin x, y, z = unzip([(1., 2., 3.), (1., 2., 3.)]) @test all(x .== 1.) && all(y .== 2.) && all(z .== 3.) From 45845e5923f03118b7ea2a699faffa7eb8966628 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 19:03:13 +0200 Subject: [PATCH 335/356] Update precompile_*.jl file (#115) Co-authored-by: t-bltg --- .../SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl index 5777ecfc3..4a9bbefd0 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.6/precompile_RecipesPipeline.jl @@ -27,12 +27,13 @@ function _precompile_() Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) Base.precompile(Tuple{typeof(_map_funcs),Function,StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}) + Base.precompile(Tuple{typeof(_prepare_series_data),Matrix{Union{Missing, Float64}}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) Base.precompile(Tuple{typeof(_series_data_vector),Int64,Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Matrix{Float64},Dict{Symbol, Any}}) - Base.precompile(Tuple{typeof(_series_data_vector),StepRange{Int64, Int64},Dict{Symbol, Any}}) + Base.precompile(Tuple{typeof(_series_data_vector),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Surface{Matrix{Int64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{AbstractVector{Float64}},Dict{Symbol, Any}}) Base.precompile(Tuple{typeof(_series_data_vector),Vector{Function},Dict{Symbol, Any}}) From a78073989feb83f6a7c5954b88bb5526820b1acf Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 11 Jul 2022 19:03:37 +0200 Subject: [PATCH 336/356] 0.6.2 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 84583e12d..d92355631 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.1" +version = "0.6.2" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 5bd12ab8c93db1c7b973a6071d0938f31310a266 Mon Sep 17 00:00:00 2001 From: MrHenning <5331081+MrHenning@users.noreply.github.com> Date: Fri, 29 Jul 2022 10:49:46 +0200 Subject: [PATCH 337/356] fix formatters (#118) --- RecipesPipeline/src/recipes.jl | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/RecipesPipeline/src/recipes.jl b/RecipesPipeline/src/recipes.jl index ce78801d3..2672f9c1b 100644 --- a/RecipesPipeline/src/recipes.jl +++ b/RecipesPipeline/src/recipes.jl @@ -3,8 +3,24 @@ # ------------------------------------------------- # ## Dates & Times -dateformatter(dt) = string(Date(Dates.UTD(dt))) -datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) +function epochdays2datetime(fractionaldays::Real)::DateTime + days = floor(fractionaldays) + dayfraction = fractionaldays - days + missing_ms = Millisecond(round(Millisecond(Day(1)).value * dayfraction)) + DateTime(Dates.epochdays2date(days)) + missing_ms +end + +epochdays2epochms(x) = Dates.datetime2epochms(epochdays2datetime(x)) + +function dateformatter(dt::Integer) + string(Date(Dates.UTD(dt))) +end + +function dateformatter(dt::Real) + string(DateTime(Dates.UTM(epochdays2epochms(dt)))) +end + +datetimeformatter(dt) = string(DateTime(Dates.UTM(round(dt)))) timeformatter(t) = string(Dates.Time(Dates.Nanosecond(round(t)))) @recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) From c9951fa54766de70f73faf7001172d6f63e1f9bb Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 29 Jul 2022 10:50:51 +0200 Subject: [PATCH 338/356] 0.6.3 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index d92355631..d79d39326 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.2" +version = "0.6.3" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 228e8c3273a091147d9a74058a9298d40d865b74 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 29 Jul 2022 14:55:11 +0200 Subject: [PATCH 339/356] Update precompile_*.jl file (#117) Co-authored-by: BeastyBlacksmith --- .../1.7/precompile_RecipesPipeline.jl | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl index eb1a31fee..008136e2c 100644 --- a/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl +++ b/RecipesPipeline/deps/SnoopCompile/precompile/1.7/precompile_RecipesPipeline.jl @@ -13,6 +13,57 @@ macro warnpcfail(ex::Expr) 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{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},AbstractMatrix}) @@ -22,12 +73,13 @@ function _precompile_() Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},GroupBy,Any}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{SliceIt},Any,Any,Any}) - Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Type{typeof(sin)},typeof(sin)}) Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),AbstractDict{Symbol, Any},Vector{Function},Number,Number}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,AbstractArray,Any}) Base.precompile(Tuple{typeof(_apply_type_recipe),Any,Surface,Any}) Base.precompile(Tuple{typeof(_compute_xyz),Vector{Float64},Function,Nothing,Bool}) + Base.precompile(Tuple{typeof(_compute_xyz),Vector{String},Vector{String},Nothing,Bool}) Base.precompile(Tuple{typeof(_extract_group_attributes),Vector{String}}) + Base.precompile(Tuple{typeof(_prepare_series_data),Matrix{Union{Missing, Float64}}}) Base.precompile(Tuple{typeof(_process_seriesrecipe),Any,Any}) Base.precompile(Tuple{typeof(_process_seriesrecipes!),Any,Any}) Base.precompile(Tuple{typeof(_scaled_adapted_grid),Function,Symbol,Symbol,Float64,Irrational{:π}}) @@ -48,4 +100,9 @@ function _precompile_() Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Int64, Real}}}) Base.precompile(Tuple{typeof(unzip),Vector{Tuple{Vector{Float64}, Vector{Float64}}}}) isdefined(RecipesPipeline, Symbol("#11#12")) && Base.precompile(Tuple{getfield(RecipesPipeline, Symbol("#11#12")),Int64}) + let fbody = try __lookup_kwbody__(which(_extract_group_attributes, (Vector{String},Vector{Float64},))) catch missing end + if !ismissing(fbody) + precompile(fbody, (Function,typeof(_extract_group_attributes),Vector{String},Vector{Float64},)) + end +end end From fba7a888bd1014a3509311e1f6efa2b6788bc417 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Tue, 30 Aug 2022 15:15:29 +0200 Subject: [PATCH 340/356] Create invalidations.yml (#93) This is based on https://github.com/julia-actions/julia-invalidations. Adding such checks came up in https://discourse.julialang.org/t/potential-performance-regressions-in-julia-1-8-for-special-un-precompiled-type-dispatches-and-how-to-fix-them/86359. I suggest to add this check here since this package is widely used as a dependency. --- .../.github/workflows/invalidations.yml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 RecipesBase/.github/workflows/invalidations.yml diff --git a/RecipesBase/.github/workflows/invalidations.yml b/RecipesBase/.github/workflows/invalidations.yml new file mode 100644 index 000000000..af366665c --- /dev/null +++ b/RecipesBase/.github/workflows/invalidations.yml @@ -0,0 +1,33 @@ +name: Invalidations +on: pull_request + +jobs: + evaluate: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@v1 + with: + version: '1' + - uses: actions/checkout@v2 + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-invalidations@v1 + id: invs_pr + + - uses: actions/checkout@v2 + with: + ref: 'master' + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-invalidations@v1 + id: invs_master + + - name: Report invalidation counts + run: | + echo "Invalidations on master: ${{ steps.invs_master.outputs.total }} (${{ steps.invs_master.outputs.deps }} via deps)" + echo "This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)" + shell: bash + - name: PR doesn't increase number of invalidations + run: | + if (( ${{ steps.invs_pr.outputs.total }} > ${{ steps.invs_master.outputs.total }} )); then + exit 1 + fi + shell: bash From 09ea075cda8e5c2061cc76be4bebdd1861c5a190 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 27 Sep 2022 13:19:25 +0200 Subject: [PATCH 341/356] rework precompilation using `SnoopPrecompile` - document `@layout` (#94) * document `@layout` * rewok precompile statements using `SnoopPrecompile` * add ci * bump julia to `1.6` for failing CI --- RecipesBase/.github/workflows/ci.yml | 49 +++++++++++++++++++++++++ RecipesBase/Project.toml | 8 +++- RecipesBase/src/RecipesBase.jl | 55 ++++++++++++++++++++++++++-- RecipesBase/src/precompile.jl | 9 ----- 4 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 RecipesBase/.github/workflows/ci.yml delete mode 100644 RecipesBase/src/precompile.jl diff --git a/RecipesBase/.github/workflows/ci.yml b/RecipesBase/.github/workflows/ci.yml new file mode 100644 index 000000000..533cd3fc4 --- /dev/null +++ b/RecipesBase/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + CI: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + env: + GKS_ENCODING: "utf8" + GKSwstype: "nul" + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - '1.6' # lowest declared compat in `Project.toml` - lastest LTS + - '1' + os: [ubuntu-latest, windows-latest, macOS-latest] + arch: [x64] + include: + - os: ubuntu-latest + prefix: xvfb-run # julia-actions/julia-runtest/blob/master/README.md + + steps: + - uses: actions/checkout@v3 + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-runtest@latest + with: + prefix: ${{ matrix.prefix }} # for `xvfb-run` + - uses: julia-actions/julia-processcoverage@latest + - uses: codecov/codecov-action@v3 + with: + file: lcov.info + + Skip: + if: contains(github.event.head_commit.message, '[skip ci]') + runs-on: ubuntu-latest + steps: + - name: Skip CI 🚫 + run: echo skip ci diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index f6a94275e..d3c3d3185 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -3,12 +3,16 @@ uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] version = "1.2.1" +[deps] +SnoopPrecompile = "66db9d55-30c0-4569-8b51-7e840670fc0c" + [compat] -julia = "1" +SnoopPrecompile = "1" +julia = "1.6" [extras] Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Random"] +test = ["Random", "Test"] diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index f69c8a484..133c59f4c 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -1,6 +1,7 @@ - module RecipesBase +using SnoopPrecompile + export @recipe, @series, @@ -569,9 +570,57 @@ function create_grid(s::Symbol) :((label = $(QuoteNode(s)), blank = $(s == :_))) end +""" + @layout mat + +Generate the subplots layout from a matrix of symbols (where subplots can span multiple rows or columns). +Precise sizing can be achieved with curly brackets, otherwise the free space is equally split between the plot areas of subplots. +You can use the `_` character (underscore) to ignore plots in the layout (blank plots). + +# Examples + +```jldoctest +julia> @layout [a b; c] +2×1 Matrix{Any}: + Any[(label = :a, blank = false) (label = :b, blank = false)] + (label = :c, blank = false) + +julia> @layout [a{0.3w}; b{0.2h}] +2×1 Matrix{Any}: + (label = :a, width = 0.3, height = :auto) + (label = :b, width = :auto, height = 0.2) + +julia> @layout [_ ° _; ° ° °; ° ° °] +3×3 Matrix{Any}: + (label = :_, blank = true) … (label = :_, blank = true) + (label = :°, blank = false) (label = :°, blank = false) + (label = :°, blank = false) (label = :°, blank = false) + +``` +""" macro layout(mat::Expr) create_grid(mat) end -include("precompile.jl") -end # module +@precompile_setup begin + struct __RecipesBasePrecompileType end + @precompile_all_calls begin + @layout [a b; c] + @layout [a{0.3w}; b{0.2h}] + @layout [_ ° _; ° ° °; ° ° °] + # @userplot __RecipesBasePrecompileType # fails (export statements) + @recipe f(::__RecipesBasePrecompileType) = begin + @series begin + markershape --> :auto, :require + markercolor --> customcolor, :force + xrotation --> 5 + zrotation --> 6, :quiet + fillcolor := :green + ones(1) + end + zeros(1) + end + end +end + +end diff --git a/RecipesBase/src/precompile.jl b/RecipesBase/src/precompile.jl deleted file mode 100644 index 49537ca3a..000000000 --- a/RecipesBase/src/precompile.jl +++ /dev/null @@ -1,9 +0,0 @@ -function _precompile_() - ccall(:jl_generating_output, Cint, ()) == 1 || return nothing - Base.precompile(Tuple{typeof(RecipesBase.create_kw_body),Expr}) - Base.precompile(Tuple{typeof(RecipesBase.get_function_def),Expr,Array{Any,1}}) - Base.precompile(Tuple{typeof(map),Function,Array{AbstractLayout,1}}) - Base.precompile(Tuple{typeof(map),Function,Array{AbstractLayout,2}}) -end - -_precompile_() From 1245d2a9f95a949e98a70b9689210d43d9357348 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 27 Sep 2022 13:20:25 +0200 Subject: [PATCH 342/356] 1.3.0 --- RecipesBase/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/Project.toml b/RecipesBase/Project.toml index d3c3d3185..5e266ddb1 100644 --- a/RecipesBase/Project.toml +++ b/RecipesBase/Project.toml @@ -1,7 +1,7 @@ name = "RecipesBase" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" author = ["Tom Breloff (@tbreloff)"] -version = "1.2.1" +version = "1.3.0" [deps] SnoopPrecompile = "66db9d55-30c0-4569-8b51-7e840670fc0c" From 8bf34294e538a46cf36d10cc2ae6934517ec9952 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 1 Oct 2022 02:52:22 -0400 Subject: [PATCH 343/356] more efficient `DefaultsDict` iteration (#121) --- RecipesPipeline/src/utils.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 3087b58f1..7768f32d2 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -33,9 +33,7 @@ function Base.delete!(dd::DefaultsDict, k) end Base.length(dd::DefaultsDict) = length(union(keys(dd.explicit), keys(dd.defaults))) function Base.iterate(dd::DefaultsDict) - exp_keys = keys(dd.explicit) - def_keys = setdiff(keys(dd.defaults), exp_keys) - key_list = collect(Iterators.flatten((exp_keys, def_keys))) + key_list = union!(collect(keys(dd.explicit)), keys(dd.defaults)) iterate(dd, (key_list, 1)) end function Base.iterate(dd::DefaultsDict, (key_list, i)) From 9f32df87cc2ecfb286b8b7ef0ac40a27af4caea3 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 1 Oct 2022 09:02:18 +0200 Subject: [PATCH 344/356] bump julia version in `ci` (#122) --- RecipesPipeline/.github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml index c28adb1b3..a550ea420 100644 --- a/RecipesPipeline/.github/workflows/CI.yml +++ b/RecipesPipeline/.github/workflows/CI.yml @@ -25,7 +25,7 @@ jobs: matrix: version: - '1.6' # LTS - - '1.7' # latest stable + - '1.8' # latest stable os: - ubuntu-latest - windows-latest From 7e53ead0735073f296a5b41e1b7209aa1d078677 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 1 Oct 2022 09:02:39 +0200 Subject: [PATCH 345/356] 0.6.4 --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index d79d39326..434c170fd 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.3" +version = "0.6.4" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From c11fc68b271c7bc6a5e4aad69ee3489559b4633a Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 1 Oct 2022 11:28:40 -0400 Subject: [PATCH 346/356] Add methods to access separate keysets of the DefaultsDict (#124) --- RecipesPipeline/src/RecipesPipeline.jl | 4 +++- RecipesPipeline/src/utils.jl | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/src/RecipesPipeline.jl b/RecipesPipeline/src/RecipesPipeline.jl index 2bf23af1b..522508f16 100644 --- a/RecipesPipeline/src/RecipesPipeline.jl +++ b/RecipesPipeline/src/RecipesPipeline.jl @@ -26,7 +26,9 @@ export SliceIt, unzip, dateformatter, datetimeformatter, - timeformatter + timeformatter, + explicitkeys, + defaultkeys # API export warn_on_recipe_aliases, splittable_attribute, diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 7768f32d2..5de461a80 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -60,6 +60,8 @@ reset_kw!(d::AKW, k) = delete!(d, k) pop_kw!(d::AKW, k) = pop!(d, k) pop_kw!(d::AKW, k, default) = pop!(d, k, default) +explicitkeys(dd::DefaultsDict) = keys(dd.explicit) +defaultkeys(dd::DefaultsDict) = keys(dd.defaults) # -------------------------------- # ## 3D types From 0d575675b795a7aa0a064feaa54ad856e0eb7a56 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 1 Oct 2022 11:29:34 -0400 Subject: [PATCH 347/356] bump version [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index 434c170fd..cdc94d0d1 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.4" +version = "0.6.5" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 948fdfba6a014901e7e460a2e9518cc90c23c462 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 1 Oct 2022 16:01:30 -0400 Subject: [PATCH 348/356] DefaultsDict - correctness and performance tweaks for large numbers of series (#126) --- RecipesPipeline/src/utils.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/RecipesPipeline/src/utils.jl b/RecipesPipeline/src/utils.jl index 5de461a80..dfeecda57 100644 --- a/RecipesPipeline/src/utils.jl +++ b/RecipesPipeline/src/utils.jl @@ -30,6 +30,7 @@ end function Base.delete!(dd::DefaultsDict, k) haskey(dd.explicit, k) && delete!(dd.explicit, k) haskey(dd.defaults, k) && delete!(dd.defaults, k) + return dd end Base.length(dd::DefaultsDict) = length(union(keys(dd.explicit), keys(dd.defaults))) function Base.iterate(dd::DefaultsDict) @@ -50,7 +51,10 @@ isdefault(dd::DefaultsDict, k) = !is_explicit(dd, k) && haskey(dd.defaults, k) Base.setindex!(dd::DefaultsDict, v, k) = dd.explicit[k] = v # Reset to default value and return dict -reset_kw!(dd::DefaultsDict, k) = is_explicit(dd, k) ? delete!(dd.explicit, k) : dd +function reset_kw!(dd::DefaultsDict, k) + is_explicit(dd, k) && delete!(dd.explicit, k) + return dd +end # Reset to default value and return old value pop_kw!(dd::DefaultsDict, k) = is_explicit(dd, k) ? pop!(dd.explicit, k) : dd.defaults[k] pop_kw!(dd::DefaultsDict, k, default) = From 72f17ab066aa74fc86467a986cf2f9dcb593bb80 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 1 Oct 2022 16:04:34 -0400 Subject: [PATCH 349/356] 0.6.6 [skip ci] --- RecipesPipeline/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index cdc94d0d1..faed1028f 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -1,7 +1,7 @@ name = "RecipesPipeline" uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" authors = ["Michael Krabbe Borregaard "] -version = "0.6.5" +version = "0.6.6" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 807654d9d7670224d4d9e9bd82e47d2704a5812c Mon Sep 17 00:00:00 2001 From: Ryan <25192197+singularitti@users.noreply.github.com> Date: Sun, 2 Oct 2022 04:36:59 -0400 Subject: [PATCH 350/356] Fix a deprecated syntax in docs of macro `@recipe` (#95) --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index 133c59f4c..d44aaff2d 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -226,7 +226,7 @@ using RecipesBase # Our custom type that we want to display struct T end -@recipe function plot{N<:Integer}(t::T, n::N = 1; customcolor = :green) +@recipe function plot(t::T, n::Integer = 1; customcolor = :green) markershape --> :auto, :require markercolor --> customcolor, :force xrotation --> 5 From 6a527f5cd451c8dccd93d308299a61cac8f931f8 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sun, 2 Oct 2022 11:04:25 +0200 Subject: [PATCH 351/356] fix broken docs --- RecipesBase/src/RecipesBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecipesBase/src/RecipesBase.jl b/RecipesBase/src/RecipesBase.jl index d44aaff2d..da65e6d8f 100644 --- a/RecipesBase/src/RecipesBase.jl +++ b/RecipesBase/src/RecipesBase.jl @@ -579,7 +579,7 @@ You can use the `_` character (underscore) to ignore plots in the layout (blank # Examples -```jldoctest +```julia-repl julia> @layout [a b; c] 2×1 Matrix{Any}: Any[(label = :a, blank = false) (label = :b, blank = false)] From be2dbe4b4d94d93c2b23a86c36630d669ac634cb Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 4 Oct 2022 10:48:28 +0200 Subject: [PATCH 352/356] add common `CI` --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ec6c7abc..c95a6e6d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,10 +5,6 @@ on: branches: [master] pull_request: -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - defaults: run: shell: bash @@ -20,7 +16,6 @@ jobs: GKS_ENCODING: "utf8" GKSwstype: "nul" PYTHON: "Conda" # for `PyPlot` - name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.version == 'nightly' }} @@ -31,17 +26,16 @@ jobs: - '1.6' # LTS (minimal declared julia compat in `Project.toml`) - '1.8' # latest stable os: [ubuntu-latest, windows-latest, macos-latest] - arch: - - x64 + arch: [x64] include: - os: ubuntu-latest prefix: xvfb-run # julia-actions/julia-runtest/blob/master/README.md - os: ubuntu-latest prefix: xvfb-run - version: '1.7' + version: '1.7' # only test intermediate relase on `ubuntu` # - os: ubuntu-latest # prefix: xvfb-run - # version: 'nightly' + # version: 'nightly' steps: - uses: actions/checkout@v3 @@ -49,15 +43,17 @@ jobs: with: version: ${{ matrix.version }} - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-buildpkg@latest - - name: Ubuntu LaTeX dependencies - if: startsWith(matrix.os, 'ubuntu') + - name: test upstream RecipesBase + shell: julia --project=@. --color=yes {0} run: | - sudo apt-get -y update - sudo apt-get -y install gnuplot poppler-utils texlive-{latex-base,latex-extra,luatex} - sudo fc-cache -vr + using Pkg; Pkg.develop(path="RecipesBase"); Pkg.test("RecipesBase") - - uses: julia-actions/julia-buildpkg@latest + - name: test upstream RecipesPipeline + shell: julia --project=@. --color=yes {0} + run: | + using Pkg; Pkg.develop(path="RecipesPipeline"); Pkg.test("RecipesPipeline") - name: PyPlot dependencies shell: julia --project=@. --color=yes {0} @@ -71,15 +67,23 @@ jobs: Conda.add("matplotlib") Conda.list() + - name: Ubuntu LaTeX dependencies + if: startsWith(matrix.os, 'ubuntu') + run: | + sudo apt-get -y update + sudo apt-get -y install gnuplot poppler-utils texlive-{latex-base,latex-extra,luatex} + sudo fc-cache -vr + - uses: julia-actions/julia-runtest@latest with: prefix: ${{ matrix.prefix }} # for `xvfb-run` - name: Run downstream tests if: startsWith(matrix.os, 'ubuntu') - run: | - xvfb-run julia -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("StatsPlots"); Pkg.test("StatsPlots")' - xvfb-run julia -e 'using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("GraphRecipes"); Pkg.test("GraphRecipes")' + shell: xvfb-run julia --project=@. --color=yes {0} + run: | + using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("StatsPlots"); Pkg.test("StatsPlots") + using Pkg; Pkg.activate(tempdir()); Pkg.develop(path=abspath(".")); Pkg.add("GraphRecipes"); Pkg.test("GraphRecipes") - uses: julia-actions/julia-processcoverage@latest if: startsWith(matrix.os, 'ubuntu') From cd5fa892242f24cb09f3e609fb2bc0d707555253 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 4 Oct 2022 11:08:02 +0200 Subject: [PATCH 353/356] update `RecipesPipeline` tests --- RecipesPipeline/Project.toml | 18 +---- RecipesPipeline/test/makie.jl | 117 ----------------------------- RecipesPipeline/test/runtests.jl | 26 +------ RecipesPipeline/test/test_group.jl | 4 - 4 files changed, 2 insertions(+), 163 deletions(-) delete mode 100644 RecipesPipeline/test/makie.jl diff --git a/RecipesPipeline/Project.toml b/RecipesPipeline/Project.toml index faed1028f..6a38c7ccf 100644 --- a/RecipesPipeline/Project.toml +++ b/RecipesPipeline/Project.toml @@ -17,23 +17,7 @@ julia = "1.6" [extras] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" -ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" -Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" [targets] -test = ["Distributions", "FileIO", "GeometryBasics", "Images", "ImageMagick", "OffsetArrays", "Plots", "Random", "RDatasets", "SparseArrays", "StaticArrays", "Statistics", "StatsPlots", "Test", "TestImages", "LinearAlgebra", "Downloads", "BenchmarkTools"] +test = ["BenchmarkTools", "Test"] diff --git a/RecipesPipeline/test/makie.jl b/RecipesPipeline/test/makie.jl deleted file mode 100644 index 84d3cc107..000000000 --- a/RecipesPipeline/test/makie.jl +++ /dev/null @@ -1,117 +0,0 @@ -using AbstractPlotting, CairoMakie -using MakieRecipes -using MakieRecipes.RecipesBase -using MarketData, TimeSeries - -# ## The simplest example model - -const i = Ref(0) - -macro test_and_save(arg) - return quote - i[] += 1 - @test_nowarn save("test_$(i[]).png", $arg) - end -end - - -struct T end - -RecipesBase.@recipe function plot(::T, n = 1; customcolor = :green) - markershape --> :auto # if markershape is unset, make it :auto - markercolor := customcolor # force markercolor to be customcolor - xrotation --> 45 # if xrotation is unset, make it 45 - zrotation --> 90 # if zrotation is unset, make it 90 - rand(10,n) # return the arguments (input data) for the next recipe -end - -@test_and_save recipeplot(T(); seriestype = :path) - -# ## Testing out series decomposition - -sc = Scene() -@test_and_save recipeplot!(sc, rand(10, 2); seriestype = :scatter) -@test_and_save recipeplot!(sc, 1:10, rand(10, 1); seriestype = :path) - -# ## Distributions - -# ### - -# ## Differential Equations - -using OrdinaryDiffEq, StochasticDiffEq, DiffEqNoiseProcess - -# ### A simple exponential growth model - -f(u,p,t) = 1.01.*u -u0 = [1/2, 1] -tspan = (0.0,1.0) -prob = ODEProblem(f,u0,tspan) -sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_and_save recipeplot(sol) - -# ### Matrix DiffEq - -A = [1. 0 0 -5 - 4 -2 4 -3 - -4 0 0 1 - 5 -2 2 3] -u0 = rand(4,2) -tspan = (0.0,1.0) -f(u,p,t) = A*u -prob = ODEProblem(f,u0,tspan) -sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8) -@test_and_save recipeplot(sol) - -# ### Stochastic DiffEq - -f(du,u,p,t) = (du .= u) -g(du,u,p,t) = (du .= u) -u0 = rand(4,2) - -W = WienerProcess(0.0,0.0,0.0) -prob = SDEProblem(f,g,u0,(0.0,1.0),noise=W) -sol = solve(prob,SRIW1()) -@test_and_save recipeplot(sol) - -# ## Phylogenetic tree -using Phylo -assetpath = joinpath(dirname(pathof(MakieRecipes)), "..", "docs", "src", "assets") -hummer = open(t -> parsenewick(t, NamedPolytomousTree), joinpath(assetpath, "hummingbirds.tree")) -evolve(tree) = Phylo.map_depthfirst((val, node) -> val + randn(), 0., tree, Float64) -trait = evolve(hummer) - -scp = recipeplot!( - Scene(scale_plot = false, show_axis = false), - hummer; - treetype = :fan, - line_z = trait, - linewidth = 5, - showtips = false, - cgrad = :RdYlBu, - seriestype = :path -) - -# ## GraphRecipes -using GraphRecipes - -# ### Julia AST with GraphRecipes - -code = quote - function mysum(list) - out = 0 - for value in list - out += value - end - out - end -end - -@test_and_save recipeplot(code; fontsize = 12, shorten = 0.01, axis_buffer = 0.15, nodeshape = :rect) - -# ### Type tree with GraphRecipes - -@test_and_save recipeplot(AbstractFloat; method = :tree, fontsize = 10) - -# Timeseries with market data -@test_and_save recipeplot(MarketData.ohlc; seriestype = :path) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index ff3f15567..3c83667fd 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -1,19 +1,6 @@ -using Distributions -using FileIO -using GeometryBasics -using ImageMagick -using Images -using OffsetArrays -using Plots -using Random using RecipesPipeline -using RDatasets -using SparseArrays -using StaticArrays -using Statistics -using StatsPlots +using BenchmarkTools using Test -using TestImages import RecipesPipeline: _prepare_series_data @@ -56,14 +43,3 @@ end end end end - -#= -makie_test_dir = joinpath(@__DIR__, "test_makie") -mkpath(makie_test_dir) - -@testset "Makie integration" begin - cd(makie_test_dir) do - include("makie.jl") - end -end -=# diff --git a/RecipesPipeline/test/test_group.jl b/RecipesPipeline/test/test_group.jl index 63b24ff7d..d2bd83c32 100644 --- a/RecipesPipeline/test/test_group.jl +++ b/RecipesPipeline/test/test_group.jl @@ -1,7 +1,3 @@ -using Test -using BenchmarkTools -using RecipesPipeline - function _extract_group_attributes_old_slow_known_good_implementation(v, args...; legend_entry = string) group_labels = collect(unique(sort(v))) n = length(group_labels) From a36b583a334044bb47ce08cc1eae0e5bc23b06c3 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 4 Oct 2022 11:12:01 +0200 Subject: [PATCH 354/356] remove un-needed files --- .../.github/workflows/CompatHelper.yml | 19 - .../.github/workflows/Documentation.yml | 29 -- RecipesBase/.github/workflows/TagBot.yml | 15 - RecipesBase/.github/workflows/ci.yml | 49 --- .../.github/workflows/invalidations.yml | 33 -- RecipesBase/.gitignore | 6 - RecipesBase/docs/Project.toml | 4 - RecipesBase/docs/make.jl | 21 - RecipesBase/docs/src/api.md | 3 - RecipesBase/docs/src/index.md | 15 - RecipesBase/docs/src/internals.md | 149 ------- RecipesBase/docs/src/syntax.md | 121 ------ RecipesBase/docs/src/types.md | 401 ------------------ RecipesPipeline/.github/workflows/CI.yml | 85 ---- .../.github/workflows/CompatHelper.yml | 17 - .../.github/workflows/SnoopCompile.yml | 90 ---- RecipesPipeline/.github/workflows/TagBot.yml | 15 - RecipesPipeline/.github/workflows/docs.yml | 24 -- RecipesPipeline/.gitignore | 6 - RecipesPipeline/docs/.gitignore | 2 - RecipesPipeline/docs/Project.toml | 6 - RecipesPipeline/docs/make.jl | 48 --- RecipesPipeline/docs/src/api.md | 18 - RecipesPipeline/docs/src/index.md | 7 - RecipesPipeline/docs/src/recipes.md | 10 - RecipesPipeline/docs/src/reference.md | 4 - 26 files changed, 1197 deletions(-) delete mode 100644 RecipesBase/.github/workflows/CompatHelper.yml delete mode 100644 RecipesBase/.github/workflows/Documentation.yml delete mode 100644 RecipesBase/.github/workflows/TagBot.yml delete mode 100644 RecipesBase/.github/workflows/ci.yml delete mode 100644 RecipesBase/.github/workflows/invalidations.yml delete mode 100644 RecipesBase/.gitignore delete mode 100644 RecipesBase/docs/Project.toml delete mode 100644 RecipesBase/docs/make.jl delete mode 100644 RecipesBase/docs/src/api.md delete mode 100644 RecipesBase/docs/src/index.md delete mode 100644 RecipesBase/docs/src/internals.md delete mode 100644 RecipesBase/docs/src/syntax.md delete mode 100644 RecipesBase/docs/src/types.md delete mode 100644 RecipesPipeline/.github/workflows/CI.yml delete mode 100644 RecipesPipeline/.github/workflows/CompatHelper.yml delete mode 100644 RecipesPipeline/.github/workflows/SnoopCompile.yml delete mode 100644 RecipesPipeline/.github/workflows/TagBot.yml delete mode 100644 RecipesPipeline/.github/workflows/docs.yml delete mode 100644 RecipesPipeline/.gitignore delete mode 100644 RecipesPipeline/docs/.gitignore delete mode 100644 RecipesPipeline/docs/Project.toml delete mode 100644 RecipesPipeline/docs/make.jl delete mode 100644 RecipesPipeline/docs/src/api.md delete mode 100644 RecipesPipeline/docs/src/index.md delete mode 100644 RecipesPipeline/docs/src/recipes.md delete mode 100644 RecipesPipeline/docs/src/reference.md diff --git a/RecipesBase/.github/workflows/CompatHelper.yml b/RecipesBase/.github/workflows/CompatHelper.yml deleted file mode 100644 index dd821e683..000000000 --- a/RecipesBase/.github/workflows/CompatHelper.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: CompatHelper - -on: - schedule: - - cron: '00 00 * * *' - -jobs: - CompatHelper: - runs-on: ubuntu-latest - steps: - - uses: julia-actions/setup-julia@latest - with: - version: 1.3 - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/RecipesBase/.github/workflows/Documentation.yml b/RecipesBase/.github/workflows/Documentation.yml deleted file mode 100644 index 687aa2cc4..000000000 --- a/RecipesBase/.github/workflows/Documentation.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Documentation - -on: - push: - branches: - - master - tags: '*' - pull_request: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@latest - with: - version: '1.6' - - name: Install dependencies - run: | - sudo apt-get update -y - sudo apt-get install -y qt5-default - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - name: Build and deploy - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token - run: | - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); - Pkg.instantiate()' - xvfb-run julia --project=docs/ docs/make.jl diff --git a/RecipesBase/.github/workflows/TagBot.yml b/RecipesBase/.github/workflows/TagBot.yml deleted file mode 100644 index f49313b66..000000000 --- a/RecipesBase/.github/workflows/TagBot.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: TagBot -on: - issue_comment: - types: - - created - workflow_dispatch: -jobs: - TagBot: - if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' - runs-on: ubuntu-latest - steps: - - uses: JuliaRegistries/TagBot@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/RecipesBase/.github/workflows/ci.yml b/RecipesBase/.github/workflows/ci.yml deleted file mode 100644 index 533cd3fc4..000000000 --- a/RecipesBase/.github/workflows/ci.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: CI - -on: - push: - branches: [master] - pull_request: - -jobs: - CI: - if: "!contains(github.event.head_commit.message, '[skip ci]')" - env: - GKS_ENCODING: "utf8" - GKSwstype: "nul" - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - version: - - '1.6' # lowest declared compat in `Project.toml` - lastest LTS - - '1' - os: [ubuntu-latest, windows-latest, macOS-latest] - arch: [x64] - include: - - os: ubuntu-latest - prefix: xvfb-run # julia-actions/julia-runtest/blob/master/README.md - - steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@latest - with: - version: ${{ matrix.version }} - arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 - - uses: julia-actions/julia-buildpkg@latest - - uses: julia-actions/julia-runtest@latest - with: - prefix: ${{ matrix.prefix }} # for `xvfb-run` - - uses: julia-actions/julia-processcoverage@latest - - uses: codecov/codecov-action@v3 - with: - file: lcov.info - - Skip: - if: contains(github.event.head_commit.message, '[skip ci]') - runs-on: ubuntu-latest - steps: - - name: Skip CI 🚫 - run: echo skip ci diff --git a/RecipesBase/.github/workflows/invalidations.yml b/RecipesBase/.github/workflows/invalidations.yml deleted file mode 100644 index af366665c..000000000 --- a/RecipesBase/.github/workflows/invalidations.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Invalidations -on: pull_request - -jobs: - evaluate: - runs-on: ubuntu-latest - steps: - - uses: julia-actions/setup-julia@v1 - with: - version: '1' - - uses: actions/checkout@v2 - - uses: julia-actions/julia-buildpkg@latest - - uses: julia-actions/julia-invalidations@v1 - id: invs_pr - - - uses: actions/checkout@v2 - with: - ref: 'master' - - uses: julia-actions/julia-buildpkg@latest - - uses: julia-actions/julia-invalidations@v1 - id: invs_master - - - name: Report invalidation counts - run: | - echo "Invalidations on master: ${{ steps.invs_master.outputs.total }} (${{ steps.invs_master.outputs.deps }} via deps)" - echo "This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)" - shell: bash - - name: PR doesn't increase number of invalidations - run: | - if (( ${{ steps.invs_pr.outputs.total }} > ${{ steps.invs_master.outputs.total }} )); then - exit 1 - fi - shell: bash diff --git a/RecipesBase/.gitignore b/RecipesBase/.gitignore deleted file mode 100644 index 6c6fbf5b3..000000000 --- a/RecipesBase/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.jl.cov -*.jl.*.cov -*.jl.mem -Manifest.toml -docs/build/ -dev/ diff --git a/RecipesBase/docs/Project.toml b/RecipesBase/docs/Project.toml deleted file mode 100644 index 72f258639..000000000 --- a/RecipesBase/docs/Project.toml +++ /dev/null @@ -1,4 +0,0 @@ -[deps] -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" diff --git a/RecipesBase/docs/make.jl b/RecipesBase/docs/make.jl deleted file mode 100644 index 5300b2154..000000000 --- a/RecipesBase/docs/make.jl +++ /dev/null @@ -1,21 +0,0 @@ -using Documenter, RecipesBase, Plots - -makedocs( - sitename = "RecipesBase.jl", - format = Documenter.HTML( - prettyurls = get(ENV, "CI", nothing) == "true" - ), - pages = [ - "Home" => "index.md", - "Recipe Syntax" => "syntax.md", - "Recipe Types" => "types.md", - "Internals" => "internals.md", - "Library" => "api.md" - ], - modules = [RecipesBase] -) - -deploydocs( - repo = "github.com/JuliaPlots/RecipesBase.jl.git", - push_preview = true, -) diff --git a/RecipesBase/docs/src/api.md b/RecipesBase/docs/src/api.md deleted file mode 100644 index 8d25af306..000000000 --- a/RecipesBase/docs/src/api.md +++ /dev/null @@ -1,3 +0,0 @@ -```@autodocs -Modules = [RecipesBase] -``` diff --git a/RecipesBase/docs/src/index.md b/RecipesBase/docs/src/index.md deleted file mode 100644 index 97f1320ac..000000000 --- a/RecipesBase/docs/src/index.md +++ /dev/null @@ -1,15 +0,0 @@ -# RecipesBase.jl - -**Author: Thomas Breloff (@tbreloff)** - -RecipesBase is a lightweight Package without dependencies that allows to define custom visualizations with the [`@recipe`](@ref) macro. - -Package developers and users can define recipes to tell [Plots.jl](https://github.com/JuliaPlots/Plots.jl) how to plot custom types without depending on it. -Furthermore, recipes can be used for complex visualizations and new series types. -Plots, for example, uses recipes internally to define histograms or bar plots. -[StatsPlots.jl](https://github.com/JuliaPlots/StatsPlots.jl) and [GraphRecipes.jl](https://github.com/JuliaPlots/GraphRecipes.jl) extend Plots functionality for statistical plotting and visualization of graphs. - -RecipesBase exports the [`@recipe`](@ref) macro which provides a nice syntax for defining plot recipes. -Under the hood [`@recipe`](@ref) defines a new method for `RecipesBase.apply_recipe` which is called recursively in Plots at different stages of the argument processing pipeline. -This way other packages can communicate with Plots, i.e. define custom plotting recipes, only depending on RecipesBase. -Furthermore, the convenience macros [`@series`](@ref), [`@userplot`](@ref) and [`@shorthands`](@ref) are exported by RecipesBase. diff --git a/RecipesBase/docs/src/internals.md b/RecipesBase/docs/src/internals.md deleted file mode 100644 index 057d36607..000000000 --- a/RecipesBase/docs/src/internals.md +++ /dev/null @@ -1,149 +0,0 @@ -## RecipesBase - -The [`@recipe`](@ref) macro defines a new method for `RecipesBase.apply_recipe`. -```julia -@recipe function f(args...; kwargs...) -``` -defines -```julia -RecipesBase.apply_recipe(plotattributes, args...; kwargs...) -``` -returning a `Vector{RecipeData}` where `RecipeData` holds the `plotattributes` Dict and the arguments returned in [`@recipe`](@ref) or in [`@series`](@ref). -```julia -struct RecipeData - plotattributes::AbstractDict{Symbol,Any} - args::Tuple -end -``` -This function sets and overwrites entries in `plotattributes` and possibly adds new series. -- `attr --> val` translates to `haskey(plotattributes, :attr) || plotattributes[:attr] = val` -- `attr := val` sets `plotattributes[:attr] = val`. -- [`@series`](@ref) allows to add new series within [`@recipe`](@ref). It copies `plotattributes` from [`@recipe`](@ref), applies the replacements defined in its code block and returns corresponding new `RecipeData` object. - !!! info - [`@series`](@ref) have to be defined as a code block with `begin` and `end` statements. - ```julia - @series begin - ... - end - ``` - -So `RecipesBase.apply_recipe(plotattributes, args...; kwargs...)` returns a `Vector{RecipeData}`. -Plots can then recursively apply it again on the `plotattributes` and `args` of the elements of this vector, dispatching on a different signature. - - -## Plots - -The standard plotting commands -```julia -plot(args...; plotattributes...) -plot!(args...; plotattributes...) -``` -and shorthands like `scatter` or `bar` call the core internal plotting function `Plots._plot!`. -```julia -Plots._plot!(plt::Plot, plotattributes::AbstractDict{Symbol, Any}, args::Tuple) -``` - -In the following we will go through the major steps of the preprocessing pipeline implemented in `Plots._plot!`. - -#### Preprocess `plotattributes` -Before `Plots._plot!` is called and after each recipe is applied, `preprocessArgs!` preprocesses the `plotattributes` Dict. -It replaces aliases, expands magic arguments, and converts some attribute types. -- `lc = nothing` is replaced by `linecolor = RGBA(0, 0, 0, 0)`. -- `marker = (:red, :circle, 8)` expands to `markercolor = :red`, `markershape = :circle` and `markersize = 8`. - -#### Process User Recipes - -In the first step, `_process_userrecipe` is called. - -```julia -kw_list = _process_userrecipes(plt, plotattributes, args) -``` -It converts the user-provided `plotattributes` to a vector of `RecipeData`. -It recursively applies `RecipesBase.apply_recipe` on the fields of the first element of the `RecipeData` vector and prepends the resulting `RecipeData` vector to it. -If the `args` of an element are empty, it extracts `plotattributes` and adds it to a Vector of Dicts `kw_list`. -When all `RecipeData` elements are fully processed, `kw_list` is returned. - -#### Process Type Recipes - -After user recipes are processed, at some point in the recursion above args is of the form `(y, )`, `(x, y)` or `(x, y, z)`. -Plots defines recipes for these signatures. -The two argument version, for example, looks like this. - -```julia -@recipe function f(x, y) - did_replace = false - newx = _apply_type_recipe(plotattributes, x) - x === newx || (did_replace = true) - newy = _apply_type_recipe(plotattributes, y) - y === newy || (did_replace = true) - if did_replace - newx, newy - else - SliceIt, x, y, nothing - end -end -``` - -It recursively calls `_apply_type_recipe` on each argument until none of the arguments is replaced. -`_apply_type_recipe` applies the type recipe with the corresponding signature and for vectors it tries to apply the recipe element-wise. -When no argument is changed by `_apply_type_recipe`, the fallback `SliceIt` recipe is applied, which adds the data to `plotattributes` and returns `RecipeData` with empty args. - -#### Process Plot Recipes - -At this stage all arguments have been processed to something Plots supports. -In `_plot!` we have a `Vector{Dict}` `kw_list` with an entry for each series and already populated `:x`, `:y` and `:z` keys. -Now `_process_plotrecipe` is called until all plot recipes are processed. - -```julia -still_to_process = kw_list -kw_list = KW[] -while !isempty(still_to_process) - next_kw = popfirst!(still_to_process) - _process_plotrecipe(plt, next_kw, kw_list, still_to_process) -end -``` - -If no series type is set in the Dict, `_process_plotrecipe` pushes it to `kw_list` and returns. -Otherwise it tries to call `RecipesBase.apply_recipe` with the plot recipe signature. -If there is a method for this signature and the seriestype has changed by applying the recipe, the new `plotattributes` are appended to `still_to_process`. -If there is no method for the current plot recipe signature, we append the current Dict to `kw_list` and rely on series recipe processing. - -After all plot recipes have been applied, the plot and subplots are set-up. -```julia -_plot_setup(plt, plotattributes, kw_list) -_subplot_setup(plt, plotattributes, kw_list) -``` - -#### Process Series Recipes - -We are almost finished. -Now the series defaults are populated and `_process_seriesrecipe` is called for each series . - -```julia -for kw in kw_list - # merge defaults - series_attr = Attr(kw, _series_defaults) - _process_seriesrecipe(plt, series_attr) -end -``` - -If the series type is natively supported by the backend, we finalize processing and pass the series along to the backend. -Otherwise, the series recipe for the current series type is applied and `_process_seriesrecipe` is called again for the `plotattributes` in each returned `RecipeData` object. -Here we have to check again that the series type changed. -Due to this recursive processing, complex series types can be built up by simple blocks. -For example if we add an `@show st` in `_process_seriesrecipe` and plot a histogram, we go through the following series types: - -```julia -plot(histogram(randn(1000))) -``` -```julia -st = :histogram -st = :barhist -st = :barbins -st = :bar -st = :shape -``` -```@example -using Plots # hide -plot(histogram(randn(1000))) #hide -``` diff --git a/RecipesBase/docs/src/syntax.md b/RecipesBase/docs/src/syntax.md deleted file mode 100644 index 21c439534..000000000 --- a/RecipesBase/docs/src/syntax.md +++ /dev/null @@ -1,121 +0,0 @@ -```@setup syntax -using Plots, Random -Random.seed!(100) -default(legend = :topleft, markerstrokecolor = :auto, markersize = 6) -``` - -# Recipes Syntax - -The syntax in the [`@recipe`](@ref) macro is best explained using an example. -Suppose, we have a custom type storing the results of a simulation `x` and `y` and a measure `ε` for the maximum error in `y`. - -```@example syntax -struct Result - x::Vector{Float64} - y::Vector{Float64} - ε::Vector{Float64} -end -``` - -If we want to plot the `x` and `y` values of such a result with an error band given by `ε`, we could run something like -```@example syntax -res = Result(1:10, cumsum(rand(10)), cumsum(rand(10)) / 5) - -using Plots - -# plot the error band as invisible line with fillrange -plot( - res.x, - res.y .+ res.ε, - xlabel = "x", - ylabel = "y", - fill = (res.y .- res.ε, :lightgray, 0.5), - linecolor = nothing, - primary = false, # no legend entry -) - -# add the data to the plots -plot!(res.x, res.y, marker = :diamond) -``` - -Instead of typing this plot command over and over for different results we can define a **user recipe** to tell Plots what to do with input of the type `Result`. -Here is an example for such a user recipe with the additional feature to highlight datapoints with a maximal error above a certain threshold `ε_max`. - -```@example syntax -@recipe function f(r::Result; ε_max = 0.5) - # set a default value for an attribute with `-->` - xlabel --> "x" - yguide --> "y" - markershape --> :diamond - # add a series for an error band - @series begin - # force an argument with `:=` - seriestype := :path - # ignore series in legend and color cycling - primary := false - linecolor := nothing - fillcolor := :lightgray - fillalpha := 0.5 - fillrange := r.y .- r.ε - # ensure no markers are shown for the error band - markershape := :none - # return series data - r.x, r.y .+ r.ε - end - # get the seriescolor passed by the user - c = get(plotattributes, :seriescolor, :auto) - # highlight big errors, otherwise use the user-defined color - markercolor := ifelse.(r.ε .> ε_max, :red, c) - # return data - r.x, r.y -end -``` - -Let's walk through this recipe step by step. -First, the function signature in the recipe definition determines the recipe type, in this case a user recipe. -The function name `f` in is irrelevant and can be replaced by any other function name. -[`@recipe`](@ref) does not use it. -In the recipe body we can set default values for [Plots attributes](http://docs.juliaplots.org/latest/attributes/). -``` -attr --> val -``` -This will set `attr` to `val` unless it is specified otherwise by the user in the plot command. -``` -plot(args...; kw..., attr = otherval) -``` -Similarly we can force an attribute value with `:=`. -``` -attr := val -``` -This overwrites whatever the user passed to `plot` for `attr` and sets it to `val`. -!!! tip - It is strongly recommended to avoid using attribute aliases in recipes as this might lead to unexpected behavior in some cases. - In the recipe above `xlabel` is used as aliases for `xguide`. - When the recipe is used Plots will show a warning and hint to the default attribute name. - They can also be found in the attribute tables under http://docs.juliaplots.org/latest/attributes/. - -We use the [`@series`](@ref) macro to add a new series for the error band to the plot. -Within an [`@series`](@ref) block we can use the same syntax as above to force or set default values for attributes. - -In [`@recipe`](@ref) we have access to `plotattributes`. This is an `AbstractDict` storing the attributes that have been already processed at the current stage in the Plots pipeline. -For user recipes, which are called early in the pipeline, this mostly contains the keyword arguments provided by the user in the `plot` command. -In our example we want to highlight data points with an error above a certain threshold by changing the marker color. -For all other data points we set the marker color to whatever is the default or has been provided as keyword argument. -We can do this by getting the `seriescolor` from `plotattributes` and defaulting to `auto` if it has not been specified by the user. - -Finally, in both, [`@recipe`](@ref)s and [`@series`](@ref) blocks we return the data we wish to pass on to Plots (or the next recipe). - -!!! compat - With RecipesBase 1.0 the `return` statement is allowed in [`@recipe`](@ref) and [`@series`](@ref). - -With the recipe above we can now plot `Result`s with just - -```@example syntax -plot(res) -``` - -or - -```@example syntax -scatter(res, ε_max = 0.7, color = :green, marker = :star) -``` diff --git a/RecipesBase/docs/src/types.md b/RecipesBase/docs/src/types.md deleted file mode 100644 index a69ed9b19..000000000 --- a/RecipesBase/docs/src/types.md +++ /dev/null @@ -1,401 +0,0 @@ -```@setup types -using Plots, Random -Random.seed!(100) -default(legend = :topleft, markerstrokecolor = :auto, markersize = 6) -``` - -# Recipe Types - -## Overview - -There are four main types of recipes which are determined by the signature of the [`@recipe`](@ref) macro. - -### User Recipes - -```julia -@recipe function f(custom_arg_1::T, custom_arg_2::S, ...; ...) -``` - -!!! tip - [`@userplot`](@ref) provides a convenient way to create a custom type to dispatch on and defines custom plotting functions. - ```julia - @userplot MyPlot - @recipe function f(mp::MyPlot; ...) - ... - end - ``` - Now we can plot with: - ```julia - myplot(args...; kw...) - myplot!(args...; kw...) - ``` - -### Type Recipes - -```julia -@recipe function f(::Type{T}, val::T) where T -``` - -!!! compat - With RecipesBase 1.0 type recipes are aware of the current axis (`:x`, `:y`, `:z`). - ```julia - @recipe function f(::Type{MyType}, val::MyType) - guide --> "My Guide" - ... - end - ``` - This only sets the guide for the axes with `MyType`. - For more complex type recipes the current axis letter can be accessed in [`@recipe`](@ref) with `plotattributes[:letter]`. - -!!! compat - With RecipesBase 1.0 type recipes of the form - ```julia - @recipe function f(::Type{T}, val::T) where T <: AbstractArray{MyType} - ``` - for `AbstractArray`s of custom types are supported too. - -!!! info - User recipes and type recipes must return either - - an `AbstractArray{<:V}` where `V` is a *valid type*, - - two functions, or - - nothing - - A *valid type* is either a Plots *datapoint* or a type that can be handled by another user recipe or type recipe. - Plots *datapoints* are all subtypes of `Union{AbstractString, Missing}` and `Union{Number, Missing}`. - - If two functions are returned the former should tell Plots how to convert from `T` to a *datapoint* and the latter how to convert from *datapoint* to string for tick label formatting. - -### Plot Recipes - -```julia -@recipe function f(::Type{Val{:myplotrecipename}}, plt::AbstractPlot; ...) -``` - -### Series Recipes - -```julia -@recipe function f(::Type{Val{:myseriesrecipename}}, x, y, z; ...) -``` - -!!! tip - The [`@shorthands`](@ref) macro provides a convenient way to define plotting functions for custom plot recipes or series recipes. - ```julia - @shorthands myseriestype - @recipe function f(::Type{Val{:myseriestype}}, x, y, z; ...) - ... - end - ``` - This allows to plot with: - ```julia - myseriestype(args...; kw...) - myseriestype!(args...; kw...) - ``` - -!!! warning - Plot recipes and series recipes have to set the `seriestype` attribute. - -## User Recipes -User recipes are called early in the processing pipeline and allow designing custom visualizations. -```julia -@recipe function f(custom_arg_1::T, custom_arg_2::S, ...; ...) -``` - -We have already seen an example for a user recipe in the syntax section above. -User recipes can also be used to define a custom visualization without necessarily wishing to plot a custom type. -For this purpose we can create a type to dispatch on. -The [`@userplot`](@ref) macro is a convenient way to do this. -```julia -@userplot MyPlot -``` -expands to -```julia -mutable struct MyPlot - args -end -export myplot, myplot! -myplot(args...; kw...) = plot(MyPlot(args); kw...) -myplot!(args...; kw...) = plot!(MyPlot(args); kw...) -``` - -To check `args` type, define a struct with type parameters. - -```julia -@userplot struct MyPlot{T<:Tuple{AbstractVector}} - args::T -end -``` - -We can use this to define a user recipe for a pie plot. -```@example types -# defines mutable struct `UserPie` and sets shorthands `userpie` and `userpie!` -@userplot UserPie -@recipe function f(up::UserPie) - y = up.args[end] # extract y from the args - # if we are passed two args, we use the first as labels - labels = length(up.args) == 2 ? up.args[1] : eachindex(y) - framestyle --> :none - aspect_ratio --> true - s = sum(y) - θ = 0 - # add a shape for each piece of pie - for i in 1:length(y) - # determine the angle until we stop - θ_new = θ + 2π * y[i] / s - # calculate the coordinates - coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] - @series begin - seriestype := :shape - label --> string(labels[i]) - coords - end - θ = θ_new - end - # we already added all shapes in @series so we don't want to return a series - # here. (Technically we are returning an empty series which is not added to - # the legend.) - primary := false - () -end -``` - -Now we can just use the recipe like this: - -```@example types -userpie('A':'D', rand(4)) -``` - -## Type Recipes -Type recipes define one-to-one mappings from custom types to something Plots supports -```julia -@recipe function f(::Type{T}, val::T) where T -``` - -Suppose we have a custom wrapper for vectors. - -```@example types -struct MyWrapper - v::Vector -end -``` -We can tell Plots to just use the wrapped vector for plotting in a type recipe. -```@example types -@recipe f(::Type{MyWrapper}, mw::MyWrapper) = mw.v -``` -Now Plots knows what to do when it sees a `MyWrapper`. -```@example types -mw = MyWrapper(cumsum(rand(10))) -plot(mw) -``` -Due to the recursive application of type recipes they even compose automatically. -```@example types -struct MyOtherWrapper - w -end - -@recipe f(::Type{MyOtherWrapper}, mow::MyOtherWrapper) = mow.w - -mow = MyOtherWrapper(mw) -plot(mow) -``` -If we want an element-wise conversion of custom types we can define a conversion function to a type that Plots supports (`Real`, `AbstractString`) and a formatter for the tick labels. -Consider the following simple time type. -```@example types -struct MyTime - h::Int - m::Int -end - -# show e.g. `MyTime(1, 30)` as "01:30" -time_string(mt) = join((lpad(string(c), 2, "0") for c in (mt.h, mt.m)), ":") -# map a `MyTime` object to the number of minutes that have passed since midnight. -# this is the actual data Plots will use. -minutes_since_midnight(mt) = 60 * mt.h + mt.m -# convert the minutes passed since midnight to a nice string showing `MyTime` -formatter(n) = time_string(MyTime(divrem(n, 60)...)) - -# define the recipe (it must return two functions) -@recipe f(::Type{MyTime}, mt::MyTime) = (minutes_since_midnight, formatter) -``` -Now we can plot vectors of `MyTime` automatically with the correct tick labelling. -`DateTime`s and `Char`s are implemented with such a type recipe in Plots for example. - -```@example types -times = MyTime.(0:23, rand(0:59, 24)) -vals = log.(1:24) - -plot(times, vals) -``` -Again everything composes nicely. -```@example types -plot(MyWrapper(vals), MyOtherWrapper(times)) -``` - -## Plot Recipes -Plot recipes are called after all input data is processed by type recipes but before the plot and subplots are set-up. They allow to build series with custom layouts and set plot-wide attributes. -```julia -@recipe function f(::Type{Val{:myplotrecipename}}, plt::AbstractPlot; ...) -``` - -Plot recipes define a new series type. -They are applied after type recipes. -Hence, standard Plots types can be assumed for input data `:x`, `:y` and `:z` in `plotattributes`. -Plot recipes can access plot and subplot attributes before they are processed, for example to build layouts. -Both, plot recipes and series recipes must change the series type. -Otherwise we get a warning that we would run into a StackOverflow error. - -We can define a seriestype `:yscaleplot`, that automatically shows data with a linear y scale in one subplot and with a logarithmic yscale in another one. -```@example types -@recipe function f(::Type{Val{:yscaleplot}}, plt::AbstractPlot) - x, y = plotattributes[:x], plotattributes[:y] - layout := (1, 2) - for (i, scale) in enumerate((:linear, :log)) - @series begin - title --> string(scale, " scale") - seriestype := :path - subplot := i - yscale := scale - end - end -end -``` -We can call it with `plot(...; ..., seriestype = :yscaleplot)` or we can define a shorthand with the [`@shorthands`](@ref) macro. -```julia -@shorthands myseries -``` -expands to -```julia -export myseries, myseries! -myseries(args...; kw...) = plot(args...; kw..., seriestype = :myseries) -myseries!(args...; kw...) = plot!(args...; kw..., seriestype = :myseries) -``` -So let's try the `yscaleplot` plot recipe. -```@example types -@shorthands yscaleplot - -yscaleplot((1:10).^2) -``` -Magically the composition with type recipes works again. -```@example types -yscaleplot(MyWrapper(times), MyOtherWrapper((1:24).^2)) -``` -## Series Recipes -Series recipes are applied recursively until the current backend supports a series type. They are used for example to convert the input data of a bar plot to the coordinates of the shapes that define the bars. -```julia -@recipe function f(::Type{Val{:myseriesrecipename}}, x, y, z; ...) -``` - -If we want to call the `userpie` recipe with a custom type we run into errors. -```julia -userpie(MyWrapper(rand(4))) -``` -```julia -ERROR: MethodError: no method matching keys(::MyWrapper) -Stacktrace: - [1] eachindex(::MyWrapper) at ./abstractarray.jl:209 -``` -Furthermore, if we want to show multiple pie charts in different subplots, we don't get what we expect either -```@example types -userpie(rand(4, 2), layout = 2) -``` -We could overcome these issues by implementing the required `AbstractArray` methods for `MyWrapper` (instead of the type recipe) and by more carefully dealing with different series in the `userpie` recipe. -However, the simpler approach is writing the pie recipe as a series recipe and relying on Plots' processing pipeline. -```@example types -@recipe function f(::Type{Val{:seriespie}}, x, y, z) - framestyle --> :none - aspect_ratio --> true - s = sum(y) - θ = 0 - for i in eachindex(y) - θ_new = θ + 2π * y[i] / s - coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] - @series begin - seriestype := :shape - label --> string(x[i]) - x := first.(coords) - y := last.(coords) - end - θ = θ_new - end -end -@shorthands seriespie -``` -Here we use the already processed values `x` and `y` to calculate the shape coordinates for each pie piece, update `x` and `y` with these coordinates and set the series type to `:shape`. -```@example types -seriespie(rand(4)) -``` -This automatically works together with type recipes ... -```@example types -seriespie(MyWrapper(rand(4))) -``` -... or with layouts -```@example types -seriespie(rand(4, 2), layout = 2) -``` - -## Remarks - -Plot recipes and series recipes are actually very similar. -In fact, a pie recipe could be also implemented as a plot recipe by acessing the data through `plotattributes`. - -```@example types -@recipe function f(::Type{Val{:plotpie}}, plt::AbstractPlot) - y = plotattributes[:y] - labels = plotattributes[:x] - framestyle --> :none - aspect_ratio --> true - s = sum(y) - θ = 0 - for i in 1:length(y) - θ_new = θ + 2π * y[i] / s - coords = [(0.0, 0.0); Plots.partialcircle(θ, θ_new, 50)] - @series begin - seriestype := :shape - label --> string(labels[i]) - x := first.(coords) - y := last.(coords) - end - θ = θ_new - end -end -@shorthands plotpie - -plotpie(rand(4, 2), layout = (1, 2)) -``` -The series recipe syntax is just a little nicer in this case. - -!!! info - Here's subtle difference between these recipe types: - Plot recipes are applied in any case while series are only applied if the backend does not support the series type natively. - -Let's try it the other way around and implement our `yscaleplot` recipe as a series recipe. - -```@example types -@recipe function f(::Type{Val{:yscaleseries}}, x, y, z) - layout := (1, 2) - for (i, scale) in enumerate((:linear, :log)) - @series begin - title --> string(scale, " scale") - seriestype := :path - subplot := i - yscale := scale - end - end -end -@shorthands yscaleseries -``` -That looks a little nicer than the plot recipe version as well. -Let's try to plot. -```julia -yscaleseries((1:10).^2) -``` -```julia -MethodError: Cannot `convert` an object of type Int64 to an object of type Plots.Subplot{Plots.GRBackend} -Closest candidates are: - convert(::Type{T}, !Matched::T) where T at essentials.jl:168 - Plots.Subplot{Plots.GRBackend}(::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any) where T<:RecipesBase.AbstractBackend at /home/daniel/.julia/packages/Plots/rNwM4/src/types.jl:88 -``` - -That is because the plot and subplots have already been built before the series recipe is applied. - -!!! tip - For everything that modifies plot-wide attributes plot recipes have to be used, otherwise series recipes are recommended. diff --git a/RecipesPipeline/.github/workflows/CI.yml b/RecipesPipeline/.github/workflows/CI.yml deleted file mode 100644 index a550ea420..000000000 --- a/RecipesPipeline/.github/workflows/CI.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: ci - -on: - push: - branches: - - master - pull_request: - -defaults: - run: - shell: bash - -jobs: - CI: - if: "!contains(github.event.head_commit.message, '[skip ci]')" - env: - GKS_ENCODING: "utf8" - GKSwstype: "nul" - - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.version == 'nightly' }} - strategy: - fail-fast: false - matrix: - version: - - '1.6' # LTS - - '1.8' # latest stable - os: - - ubuntu-latest - - windows-latest - - macos-latest - arch: - - x64 - # - x86 - include: - - version: 'nightly' - os: ubuntu-latest - - steps: - - # Setup environment - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@latest - with: - version: ${{ matrix.version }} - - name: Cache artifacts - uses: actions/cache@v1 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- - - # TESTCMD - - name: Default TESTCMD - run: echo "TESTCMD=julia" >> $GITHUB_ENV - - name: Ubuntu TESTCMD - if: startsWith(matrix.os,'ubuntu') - run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV - - # Julia Dependencies - - name: Install Julia dependencies - uses: julia-actions/julia-buildpkg@latest - - # Run tests - - name: Run tests - run: $TESTCMD --project -e 'using Pkg; Pkg.test(coverage=true)' - - # Codecov - - uses: julia-actions/julia-processcoverage@latest - - uses: codecov/codecov-action@v3 - with: - file: lcov.info - - Skip: - if: "contains(github.event.head_commit.message, '[skip ci]')" - runs-on: ubuntu-latest - steps: - - name: Skip CI 🚫 - run: echo skip ci diff --git a/RecipesPipeline/.github/workflows/CompatHelper.yml b/RecipesPipeline/.github/workflows/CompatHelper.yml deleted file mode 100644 index d4d64580a..000000000 --- a/RecipesPipeline/.github/workflows/CompatHelper.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: CompatHelper - -on: - schedule: - - cron: '00 00 * * *' - -jobs: - CompatHelper: - runs-on: ubuntu-latest - steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }} # optional - run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/RecipesPipeline/.github/workflows/SnoopCompile.yml b/RecipesPipeline/.github/workflows/SnoopCompile.yml deleted file mode 100644 index 2ec9fc19f..000000000 --- a/RecipesPipeline/.github/workflows/SnoopCompile.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: SnoopCompile - -on: - push: - branches: - - 'master' # NOTE: to run the bot only on pushes to master - -defaults: - run: - shell: bash - -jobs: - SnoopCompile: - if: "!contains(github.event.head_commit.message, '[skip ci]')" - env: - GKS_ENCODING: "utf8" - - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - version: # NOTE: the versions below should match those in your botconfig - - '1.6' # ⎤ - - '1.7' # ⎦ <<< keep these versions in sync with deps/SnoopCompile/snoop_bot_config.jl - os: # NOTE: should match the os setting of your botconfig - - ubuntu-latest - arch: - - x64 - steps: - # Setup environment - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@latest - with: - version: ${{ matrix.version }} - - - name: Install dependencies - run: | - julia --project -e 'using Pkg; Pkg.instantiate()' - julia -e 'using Pkg; Pkg.add(PackageSpec(name = "CompileBot", version = "1")); Pkg.develop(path=pwd()); using CompileBot; CompileBot.addtestdep()' - - # TESTCMD - - name: Default TESTCMD - run: echo "TESTCMD=julia" >> $GITHUB_ENV - - name: Ubuntu TESTCMD - if: startsWith(matrix.os,'ubuntu') - run: echo "TESTCMD=xvfb-run --auto-servernum julia" >> $GITHUB_ENV - - # Generate precompile files - - name: Generating precompile files - run: $TESTCMD --project -e 'include("deps/SnoopCompile/snoop_bot.jl")' # NOTE: must match path - - # Run benchmarks - - name: Running Benchmark - run: $TESTCMD --project -e 'include("deps/SnoopCompile/snoop_bench.jl")' # NOTE: optional, if have benchmark file - - - name: Upload all - uses: actions/upload-artifact@v3 - with: - path: ./ - - Create_PR: - if: "!contains(github.event.head_commit.message, '[skip ci]')" - needs: SnoopCompile - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Download all - uses: actions/download-artifact@v3 - - - name: CompileBot postprocess - run: julia -e 'using Pkg; Pkg.add(PackageSpec(name = "CompileBot", version = "1")); using CompileBot; CompileBot.postprocess();' - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Update precompile_*.jl file - title: "[AUTO] Update precompiles [skip ci]" - labels: | - SnoopCompile - no changelog - branch: "SnoopCompile_AutoPR" - - - Skip: - if: "contains(github.event.head_commit.message, '[skip ci]')" - runs-on: ubuntu-latest - steps: - - name: Skip CI 🚫 - run: echo skip ci diff --git a/RecipesPipeline/.github/workflows/TagBot.yml b/RecipesPipeline/.github/workflows/TagBot.yml deleted file mode 100644 index f49313b66..000000000 --- a/RecipesPipeline/.github/workflows/TagBot.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: TagBot -on: - issue_comment: - types: - - created - workflow_dispatch: -jobs: - TagBot: - if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' - runs-on: ubuntu-latest - steps: - - uses: JuliaRegistries/TagBot@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/RecipesPipeline/.github/workflows/docs.yml b/RecipesPipeline/.github/workflows/docs.yml deleted file mode 100644 index d0cff7c65..000000000 --- a/RecipesPipeline/.github/workflows/docs.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Documentation - -on: - push: - branches: - - master - tags: '*' - pull_request: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@latest - with: - version: 1 - - name: Install dependencies - run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - name: Build and deploy - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token - DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key - run: julia --project=docs/ docs/make.jl diff --git a/RecipesPipeline/.gitignore b/RecipesPipeline/.gitignore deleted file mode 100644 index 1388e96ac..000000000 --- a/RecipesPipeline/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.jl.*.cov -*.jl.cov -*.jl.mem -.DS_Store -/Manifest.toml -/dev/ diff --git a/RecipesPipeline/docs/.gitignore b/RecipesPipeline/docs/.gitignore deleted file mode 100644 index a303fff20..000000000 --- a/RecipesPipeline/docs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -site/ diff --git a/RecipesPipeline/docs/Project.toml b/RecipesPipeline/docs/Project.toml deleted file mode 100644 index d06c370df..000000000 --- a/RecipesPipeline/docs/Project.toml +++ /dev/null @@ -1,6 +0,0 @@ -[deps] -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" - -[compat] -Literate = "2" diff --git a/RecipesPipeline/docs/make.jl b/RecipesPipeline/docs/make.jl deleted file mode 100644 index eafd6a423..000000000 --- a/RecipesPipeline/docs/make.jl +++ /dev/null @@ -1,48 +0,0 @@ -using Documenter -using RecipesPipeline -using Literate - -# create literate versions of the source files -filepath = joinpath(@__DIR__, "..", "src") -files = joinpath.(filepath, readdir(filepath)) - -Literate.markdown.(files, joinpath(@__DIR__, "src", "generated"); documenter = false) - -makedocs( - sitename = "RecipesPipeline.jl", - format = Documenter.HTML( - prettyurls = get(ENV, "CI", nothing) == "true" - ), - pages = [ - "index.md", - "Developer manual" => [ - "Public API" => "api.md", - "Recipes" => "recipes.md" - ], - "Reference" => "reference.md", - "Source code" => joinpath.("generated", - [ - "RecipesPipeline.md", - "api.md", - "user_recipe.md", - "plot_recipe.md", - "type_recipe.md", - "series_recipe.md", - "group.md", - "recipes.md", - "series.md", - "group.md", - "utils.md" - ] - ), - ], - modules = [RecipesPipeline] -) - -# Documenter can also automatically deploy documentation to gh-pages. -# See "Hosting Documentation" and deploydocs() in the Documenter manual -# for more information. -deploydocs( - repo = "github.com/JuliaPlots/RecipesPipeline.jl", - push_preview = true -) diff --git a/RecipesPipeline/docs/src/api.md b/RecipesPipeline/docs/src/api.md deleted file mode 100644 index 2896860ed..000000000 --- a/RecipesPipeline/docs/src/api.md +++ /dev/null @@ -1,18 +0,0 @@ -### API - -```@autodocs -Modules = [RecipesPipeline] -Pages = [ - "api.jl" -] -Private = false -``` - -### Utility functions - -```@autodocs -Modules = [RecipesPipeline] -Pages = [ - "utils.jl" -] -``` diff --git a/RecipesPipeline/docs/src/index.md b/RecipesPipeline/docs/src/index.md deleted file mode 100644 index 289969c77..000000000 --- a/RecipesPipeline/docs/src/index.md +++ /dev/null @@ -1,7 +0,0 @@ -# RecipesPipeline.jl - -Documentation for RecipesPipeline.jl - -```@docs -recipe_pipeline!(plt, plotattributes, args) -``` diff --git a/RecipesPipeline/docs/src/recipes.md b/RecipesPipeline/docs/src/recipes.md deleted file mode 100644 index 381c648a0..000000000 --- a/RecipesPipeline/docs/src/recipes.md +++ /dev/null @@ -1,10 +0,0 @@ -## Recipes processing - -```@autodocs -Modules = [RecipesPipeline] -Pages = [ - "user_recipe.jl", - "plot_recipe.jl", - "series_recipe.jl" -] -``` diff --git a/RecipesPipeline/docs/src/reference.md b/RecipesPipeline/docs/src/reference.md deleted file mode 100644 index d68550791..000000000 --- a/RecipesPipeline/docs/src/reference.md +++ /dev/null @@ -1,4 +0,0 @@ -## Reference - -```@index -``` From 29d5c5a71b0eddba3d17b379c3152cb6de7bd1c6 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 4 Oct 2022 11:13:42 +0200 Subject: [PATCH 355/356] restore `concurrency` --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c95a6e6d6..103b34528 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,10 @@ on: branches: [master] pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + defaults: run: shell: bash From 7f2669160cb6d221e0fd66685c94e5e11ab9d079 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Tue, 4 Oct 2022 11:20:21 +0200 Subject: [PATCH 356/356] remove `Plots` tests from `RecipesPipeline` --- RecipesPipeline/test/runtests.jl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/RecipesPipeline/test/runtests.jl b/RecipesPipeline/test/runtests.jl index 3c83667fd..fa91ba169 100644 --- a/RecipesPipeline/test/runtests.jl +++ b/RecipesPipeline/test/runtests.jl @@ -35,11 +35,3 @@ end @testset "group" begin include("test_group.jl") end - -@testset "plots" begin - for i in eachindex(Plots._examples) - if i ∉ Plots._backend_skips[:gr] - @test Plots.test_examples(:gr, i, disp=false) isa Plots.Plot - end - end -end