Compare commits

..

7 Commits

Author SHA1 Message Date
github-actions[bot] 6d3604ed80 Update precompile_*.jl file (#3010)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2020-09-27 20:42:16 +02:00
Simon Christ 574f93208f Merge branch 'bbs/NaNHeatmap' of https://github.com/JuliaPlots/Plots.jl into bbs/NaNHeatmap 2020-09-26 21:32:06 +02:00
Simon Christ 3b082f88d1 add a dimensionalty check 2020-09-26 21:31:52 +02:00
github-actions[bot] 95f91e18f9 Update precompile_*.jl file (#3008)
Co-authored-by: BeastyBlacksmith <BeastyBlacksmith@users.noreply.github.com>
2020-09-26 21:06:29 +02:00
Simon Christ 1be0b76940 remove show 2020-09-25 23:19:15 +02:00
Simon Christ 2b4cd34377 fix histogram2D 2020-09-25 23:14:51 +02:00
Simon Christ ab820a5b76 fix NaNHeatmaps 2020-09-25 22:57:27 +02:00
35 changed files with 887 additions and 981 deletions
+3 -3
View File
@@ -40,7 +40,7 @@ jobs:
- name: Install dependencies
run: |
julia --project -e 'using Pkg; Pkg.instantiate();'
julia -e 'using Pkg; Pkg.add( PackageSpec(url="https://github.com/aminya/CompileBot.jl", rev = "master") ); Pkg.develop(PackageSpec(; path=pwd())); using CompileBot; CompileBot.addtestdep();'
julia -e 'using Pkg; Pkg.add( PackageSpec(url="https://github.com/aminya/SnoopCompileBot.jl", rev = "master") ); Pkg.develop(PackageSpec(; path=pwd())); using SnoopCompileBot; SnoopCompileBot.addtestdep();'
# TESTCMD
@@ -72,8 +72,8 @@ jobs:
- name: Download all
uses: actions/download-artifact@v2
- name: CompileBot postprocess
run: julia -e 'using Pkg; Pkg.add( PackageSpec(url="https://github.com/aminya/CompileBot.jl", rev = "master") ); using CompileBot; CompileBot.postprocess();'
- name: SnoopCompileBot postprocess
run: julia -e 'using Pkg; Pkg.add( PackageSpec(url="https://github.com/aminya/SnoopCompileBot.jl", rev = "master") ); using SnoopCompileBot; SnoopCompileBot.postprocess();'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
-7
View File
@@ -1,7 +0,0 @@
[plotly]
git-tree-sha1 = "f03dd0451a05a5fdbbcb3e548998a9d7a1ab6368"
lazy = true
[[plotly.download]]
url = "https://cdn.plot.ly/plotly-1.54.2.min.js"
sha256 = "487f1da6b7a1f127de59af8a65bb3fe2c63d709f011afea82896bdce28ecc0f8"
+1 -4
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.6.12"
version = "1.6.5"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@@ -13,11 +13,9 @@ GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
GeometryTypes = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
@@ -41,7 +39,6 @@ GR = "0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52"
GeometryBasics = "0.2, 0.3.1"
GeometryTypes = "0.7, 0.8"
JSON = "0.21, 1"
Latexify = "0.14"
Measures = "0.3"
NaNMath = "0.3"
PGFPlotsX = "1.2.0"
@@ -226,6 +226,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -315,6 +315,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
File diff suppressed because it is too large Load Diff
@@ -227,6 +227,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -285,6 +285,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -285,6 +285,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -226,6 +226,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -317,6 +317,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
@@ -286,6 +286,7 @@ function _precompile_()
Base.precompile(Tuple{typeof(Plots.slice_arg),Array{Symbol,2},Int64})
Base.precompile(Tuple{typeof(Plots.slice_arg),Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Int64})
Base.precompile(Tuple{typeof(Plots.straightline_data),Tuple{Float64,Float64},Tuple{Float64,Float64},Array{Float64,1},Array{Float64,1},Int64})
Base.precompile(Tuple{typeof(Plots.transpose_z),Plots.Series,Array{Float64,2},Bool})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{Complex{Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{GeometryBasics.Point{2,Float64},1}})
Base.precompile(Tuple{typeof(RecipesBase.apply_recipe),Dict{Symbol,Any},Array{OHLC,1}})
+1 -1
View File
@@ -1,4 +1,4 @@
using CompileBot
using SnoopCompileBot
snoop_bench(
BotConfig(
+1 -1
View File
@@ -1,4 +1,4 @@
using CompileBot
using SnoopCompileBot
snoop_bot(
BotConfig(
+18
View File
@@ -0,0 +1,18 @@
#TODO: download https://cdn.plot.ly/plotly-1.54.2.min.js to deps/ if it doesn't exist
file_path = ""
if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true"
global file_path
local_fn = joinpath(dirname(@__FILE__), "plotly-1.54.2.min.js")
if !isfile(local_fn)
@info("Cannot find deps/plotly-1.54.2.min.js... downloading latest version.")
download("https://cdn.plot.ly/plotly-1.54.2.min.js", local_fn)
isfile(local_fn) && (file_path = local_fn)
else
file_path = local_fn
end
end
open("deps.jl", "w") do io
println(io, "const plotly_local_file_path = $(repr(file_path))")
end
+15 -10
View File
@@ -10,7 +10,7 @@ using Reexport
import GeometryTypes, GeometryBasics
using Dates, Printf, Statistics, Base64, LinearAlgebra, Random
using SparseArrays
import SparseArrays: AbstractSparseMatrix, findnz
using FFMPEG
@@ -25,6 +25,17 @@ import JSON
using Requires
if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl"))
include(joinpath(@__DIR__, "..", "deps", "deps.jl"))
else
# This is a bit dirty, but I don't really see why anyone should be forced
# to build Plots, while it will just include exactly the below line
# as long as `ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true"` is not set.
# If the above env is set + `plotly_local_file_path == ""``,
# it will warn in the __init__ function to run build
const plotly_local_file_path = ""
end
export
grid,
bbox,
@@ -154,12 +165,6 @@ const BBox = Measures.Absolute2DBox
# allow pixels and percentages
const px = AbsoluteLength(0.254)
const pct = Length{:pct, Float64}(1.0)
Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
Base.:/(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value / m1.value)
export BBox, BoundingBox, mm, cm, inch, px, pct, pt, w, h
end
@@ -189,9 +194,9 @@ import RecipesPipeline: SliceIt,
include("types.jl")
include("utils.jl")
include("components.jl")
include("axes.jl")
include("args.jl")
include("components.jl")
include("themes.jl")
include("plot.jl")
include("pipeline.jl")
@@ -224,8 +229,8 @@ let PlotOrSubplot = Union{Plot, Subplot}
global xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
global ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
global zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
global xticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; xticks = ticks, kw...)
global yticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; yticks = ticks, kw...)
global xticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) where {T<:Real} = plot!(plt; xticks = ticks, kw...)
global yticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) where {T<:Real} = plot!(plt; yticks = ticks, kw...)
global xticks!(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...)
global yticks!(plt::PlotOrSubplot,
+14 -131
View File
@@ -1,34 +1,21 @@
function makeplural(s::Symbol)
str = string(s)
if last(str) != 's'
return Symbol(string(s,"s"))
end
return s
end
function make_non_underscore(s::Symbol)
str = string(s)
str = replace(str, "_" => "")
return Symbol(str)
end
const _keyAliases = Dict{Symbol,Symbol}()
function add_aliases(sym::Symbol, aliases::Symbol...)
for alias in aliases
if haskey(_keyAliases, alias) || alias === sym
return nothing
if haskey(_keyAliases, alias)
error("Already an alias $alias => $(_keyAliases[alias])... can't also alias $sym")
end
_keyAliases[alias] = sym
end
return nothing
end
function add_non_underscore_aliases!(aliases::Dict{Symbol,Symbol})
for (k,v) in aliases
s = string(k)
if '_' in s
aliases[make_non_underscore(k)] = v
aliases[Symbol(replace(s, "_" => ""))] = v
end
end
end
@@ -37,7 +24,7 @@ function add_non_underscore_aliases!(aliases::Dict{Symbol,Symbol}, args::Vector{
for arg in args
s = string(arg)
if '_' in s
aliases[make_non_underscore(arg)] = arg
aliases[Symbol(replace(s, "_" => ""))] = arg
end
end
end
@@ -124,31 +111,6 @@ const _styleAliases = Dict{Symbol,Symbol}(
:ddd => :dashdotdot,
)
const _shape_keys = Symbol[
:circle,
:rect,
:star5,
:diamond,
:hexagon,
:cross,
:xcross,
:utriangle,
:dtriangle,
:rtriangle,
:ltriangle,
:pentagon,
:heptagon,
:octagon,
:star4,
:star6,
:star7,
:star8,
:vline,
:hline,
:+,
:x,
]
const _allMarkers = vcat(:none, :auto, _shape_keys) #sort(collect(keys(_shapes))))
const _markerAliases = Dict{Symbol,Symbol}(
:n => :none,
@@ -318,6 +280,8 @@ const _series_defaults = KW(
:show_empty_bins => false, # should empty bins in 2D histogram be colored as zero (otherwise they are transparent)
:contours => false, # add contours to 3d surface and wireframe plots
:contour_labels => false,
:match_dimensions => false, # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196
# this ONLY effects whether or not the z-matrix is transposed for a heatmap display!
:subplot => :auto, # which subplot(s) does this series belong to?
:series_annotations => nothing, # a list of annotations which apply to the coordinates of this series
:primary => true, # when true, this "counts" as a series for color selection, etc. the main use is to allow
@@ -529,7 +493,7 @@ const _all_series_args = sort(union([_series_args; _magic_series_args]))
const _all_plot_args = _plot_args
const _all_args =
sort(union([_all_axis_args; _all_subplot_args; _all_series_args; _all_plot_args]))
sort([_all_axis_args; _all_subplot_args; _all_series_args; _all_plot_args])
is_subplot_attr(k) = k in _all_subplot_args
is_series_attr(k) = k in _all_series_args
@@ -540,6 +504,9 @@ RecipesBase.is_key_supported(k::Symbol) = is_attr_supported(k)
is_default_attribute(k) = k in _internal_args || k in _all_args || is_axis_attr_noletter(k)
# -----------------------------------------------------------------------------
makeplural(s::Symbol) = Symbol(string(s,"s"))
autopick_ignore_none_auto(arr::AVec, idx::Integer) = _cycle(setdiff(arr, [:none, :auto]), idx)
autopick_ignore_none_auto(notarr, idx::Integer) = notarr
@@ -662,6 +629,7 @@ add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized)
add_aliases(:show_empty_bins, :showemptybins, :showempty, :show_empty)
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
add_aliases(:match_dimensions, :transpose, :transpose_z)
add_aliases(:subplot, :sp, :subplt, :splt)
add_aliases(:projection, :proj)
add_aliases(:titlelocation, :title_location, :title_loc, :titleloc, :title_position, :title_pos, :titlepos, :titleposition, :title_align, :title_alignment)
@@ -681,10 +649,10 @@ add_aliases(:contour_labels, :contourlabels, :clabels, :clabs)
add_aliases(:warn_on_unsupported, :warn)
# add all pluralized forms to the _keyAliases dict
for arg in _all_args
add_aliases(arg, makeplural(arg))
for arg in keys(_series_defaults)
_keyAliases[makeplural(arg)] = arg
end
# add all non_underscored forms to the _keyAliases
add_non_underscore_aliases!(_keyAliases)
# -----------------------------------------------------------------------------
@@ -1567,16 +1535,8 @@ function _update_subplot_args(plt::Plot, sp::Subplot, plotattributes_in, subplot
_update_subplot_periphery(sp, anns)
_update_subplot_colors(sp)
lims_warned = false
for letter in (:x, :y, :z)
_update_axis(plt, sp, plotattributes_in, letter, subplot_index)
lk = Symbol(letter, :lims)
# warn against using `Range` in x,y,z lims
if !lims_warned && haskey(plotattributes_in, lk) && plotattributes_in[lk] isa AbstractRange
@warn("lims should be a Tuple, not $(typeof(plotattributes_in[lk])).")
lims_warned = true
end
end
end
@@ -1732,80 +1692,3 @@ function _series_index(plotattributes, sp)
end
return idx
end
#--------------------------------------------------
## inspired by Base.@kwdef
macro add_attributes( level, expr )
expr = macroexpand(__module__, expr) # to expand @static
expr isa Expr && expr.head === :struct || error("Invalid usage of @add_attributes")
T = expr.args[2]
if T isa Expr && T.head === :<:
T = T.args[1]
end
key_args = Any[]
value_args = Any[]
_splitdef!(expr.args[3], value_args, key_args)
insert_block = Expr(:block)
for (key, value) in zip(key_args, value_args)
# e.g. _series_defualts[key] = value
exp_key = Symbol(lowercase(string(T)), "_", key)
pl_key = makeplural(exp_key)
push!(insert_block.args, Expr(
:(=), Expr(:ref, Symbol("_", level, "_defaults"), QuoteNode(exp_key)), value
))
push!(insert_block.args, :(
add_aliases($(QuoteNode(exp_key)), $(QuoteNode(pl_key)))
))
push!(insert_block.args, :(
add_aliases($(QuoteNode(exp_key)), $(QuoteNode(make_non_underscore(exp_key))))
))
push!(insert_block.args, :(
add_aliases($(QuoteNode(exp_key)), $(QuoteNode(make_non_underscore(pl_key))))
))
end
return quote
$expr
$insert_block
end |> esc
end
function _splitdef!(blk, value_args, key_args)
for i in eachindex(blk.args)
ei = blk.args[i]
if ei isa Symbol
# var
continue
elseif ei isa Expr
if ei.head === :(=)
lhs = ei.args[1]
if lhs isa Symbol
# var = defexpr
var = lhs
elseif lhs isa Expr && lhs.head === :(::) && lhs.args[1] isa Symbol
# var::T = defexpr
var = lhs.args[1]
else
# something else, e.g. inline inner constructor
# F(...) = ...
continue
end
defexpr = ei.args[2] # defexpr
push!(value_args, defexpr)
push!(key_args, var)
blk.args[i] = lhs
elseif ei.head === :(::) && ei.args[1] isa Symbol
# var::Typ
var = ei.args[1]
push!(value_args, var)
push!(key_args, var)
elseif ei.head === :block
# can arise with use of @static inside type decl
_kwdef!(ei, value_args, key_args)
end
end
end
blk
end
+9 -3
View File
@@ -316,6 +316,7 @@ const _gr_attr = merge_with_base_supported([
:layout,
:title, :window_title,
:guide, :lims, :ticks, :scale, :flip,
:match_dimensions,
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
:titlefontrotation, :titlefontcolor,
:legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign,
@@ -366,10 +367,10 @@ is_marker_supported(::GRBackend, shape::Shape) = true
function _initialize_backend(pkg::PlotlyBackend)
try
@eval Main begin
import PlotlyBase
import ORCA
end
catch
@info "For saving to png with the Plotly backend PlotlyBase has to be installed."
@info "For saving to png with the Plotly backend ORCA has to be installed."
end
end
@@ -471,6 +472,7 @@ const _pgfplots_attr = merge_with_base_supported([
:polar,
# :normalize, :weights, :contours,
:aspect_ratio,
# :match_dimensions,
:tick_direction,
:framestyle,
:camera,
@@ -486,7 +488,7 @@ const _pgfplots_scale = [:identity, :ln, :log2, :log10]
function _initialize_backend(pkg::PlotlyJSBackend)
@eval Main begin
import PlotlyJS
import PlotlyJS, ORCA
export PlotlyJS
end
end
@@ -539,6 +541,7 @@ const _pyplot_attr = merge_with_base_supported([
:polar,
:normalize, :weights,
:contours, :aspect_ratio,
:match_dimensions,
:clims,
:inset_subplots,
:dpi,
@@ -624,6 +627,7 @@ const _hdf5_attr = merge_with_base_supported([
:polar,
:normalize, :weights,
:contours, :aspect_ratio,
:match_dimensions,
:clims,
:inset_subplots,
:dpi,
@@ -696,6 +700,7 @@ const _inspectdr_attr = merge_with_base_supported([
:polar,
# :normalize, :weights,
# :contours, :aspect_ratio,
:match_dimensions,
# :clims,
# :inset_subplots,
:dpi,
@@ -756,6 +761,7 @@ const _pgfplotsx_attr = merge_with_base_supported([
:ticks,
:scale,
:flip,
:match_dimensions,
:titlefontfamily,
:titlefontsize,
:titlefonthalign,
+7 -7
View File
@@ -1332,8 +1332,6 @@ function gr_label_ticks(sp, letter, ticks)
end
end
function gr_label_ticks(sp, letter, ticks::Nothing) end
function gr_label_ticks_3d(sp, letter, ticks)
near_letter = letter in (:x, :z) ? :y : :x
far_letter = letter in (:x, :y) ? :z : :x
@@ -1488,12 +1486,14 @@ function gr_add_series(sp, series)
GR.savestate()
x, y, z = (handle_surface(series[letter]) for letter in (:x, :y, :z))
x, y, z = series[:x], series[:y], series[:z]
xscale, yscale = sp[:xaxis][:scale], sp[:yaxis][:scale]
frng = series[:fillrange]
# recompute data
if ispolar(sp) && z === nothing
if typeof(z) <: Surface
z = transpose_z(series, z.surf, false)
elseif ispolar(sp)
rmin, rmax = axis_limits(sp, :y)
if frng !== nothing
_, frng = convert_to_polar(x, frng, (rmin, rmax))
@@ -1535,8 +1535,7 @@ function gr_add_series(sp, series)
dmin, dmax = GR.gr3.volume(y.v, 0)
elseif st in (:heatmap, :image)
if !ispolar(series)
# `z` is already transposed, so we need to reverse before passing its size.
x, y = heatmap_edges(x, xscale, y, yscale, reverse(size(z)))
x, y = heatmap_edges(x, xscale, y, yscale, size(z))
end
if st === :heatmap
gr_draw_heatmap(series, x, y, z, clims)
@@ -1733,7 +1732,7 @@ function gr_draw_heatmap(series, x, y, z, clims)
else
phimin, phimax = 0.0, 360.0 # nonuniform polar array is not yet supported in GR.jl
nx, ny = length(series[:x]), length(series[:y])
xmin, xmax, ymin, ymax = gr_xy_axislims(series[:subplot])
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
GR.setwindow(-ymax, ymax, -ymax, ymax)
if ymin > 0
@warn "'ymin[1] > 0' (rmin) is not yet supported."
@@ -1750,6 +1749,7 @@ function gr_draw_heatmap(series, x, y, z, clims)
end
function gr_draw_image(series, x, y, z, clims)
z = transpose_z(series, series[:z].surf, true)'
w, h = size(z)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
@@ -1,14 +1,14 @@
function plotlybase_syncplot(plt::Plot)
plt.o = PlotlyBase.Plot()
traces = PlotlyBase.GenericTrace[]
plt.o = ORCA.PlotlyBase.Plot()
traces = ORCA.PlotlyBase.GenericTrace[]
for series_dict in plotly_series(plt)
plotly_type = pop!(series_dict, :type)
push!(traces, PlotlyBase.GenericTrace(plotly_type; series_dict...))
push!(traces, ORCA.PlotlyBase.GenericTrace(plotly_type; series_dict...))
end
PlotlyBase.addtraces!(plt.o, traces...)
ORCA.PlotlyBase.addtraces!(plt.o, traces...)
layout = plotly_layout(plt)
w, h = plt[:size]
PlotlyBase.relayout!(plt.o, layout, width = w, height = h)
ORCA.PlotlyBase.relayout!(plt.o, layout, width = w, height = h)
return plt.o
end
@@ -19,5 +19,5 @@ for (mime, fmt) in (
"image/eps" => "eps",
)
@eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyBackend}) =
PlotlyBase.savefig(io, plotlybase_syncplot(plt), format = $fmt)
ORCA.PlotlyBase.savefig(io, plotlybase_syncplot(plt), format = $fmt)
end
+1 -5
View File
@@ -1,6 +1,5 @@
using Contour: Contour
using UUIDs
using Latexify
Base.@kwdef mutable struct PGFPlotsXPlot
is_created::Bool = false
was_shown::Bool = false
@@ -646,7 +645,7 @@ pgfx_series_arguments(series, opt, range) = (arg[range] for arg in pgfx_series_a
function pgfx_series_arguments(series, opt)
st = series[:seriestype]
return if st in (:contour, :contour3d)
opt[:x], opt[:y], handle_surface(opt[:z])
opt[:x], opt[:y], Array(opt[:z])'
elseif st in (:heatmap, :surface, :wireframe)
surface_to_vecs(opt[:x], opt[:y], opt[:z])
elseif RecipesPipeline.is3d(st)
@@ -1041,9 +1040,6 @@ function pgfx_sanitize_string(s::AbstractString)
s = replace(s, r"\\?\&" => "\\&")
s = replace(s, r"\\?\{" => "\\{")
s = replace(s, r"\\?\}" => "\\}")
s = map(split(s, "")) do s
isascii(s) ? s : latexify(s)
end |> join
end
@require LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" begin
using .LaTeXStrings
+54 -60
View File
@@ -120,17 +120,16 @@ end
# this method gets the start/end in percentage of the canvas for this axis direction
function plotly_domain(sp::Subplot)
function plotly_domain(sp::Subplot, letter)
figw, figh = sp.plt[:size]
pcts = bbox_to_pcts(sp.plotarea, figw*px, figh*px)
pcts = plotly_apply_aspect_ratio(sp, sp.plotarea, pcts)
x_domain = [pcts[1], pcts[1] + pcts[3]]
y_domain = [pcts[2], pcts[2] + pcts[4]]
return x_domain, y_domain
i1,i2 = (letter == :x ? (1,3) : (2,4))
[pcts[i1], pcts[i1]+pcts[i2]]
end
function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
letter = axis[:letter]
framestyle = sp[:framestyle]
ax = KW(
@@ -147,11 +146,16 @@ function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
:mirror => framestyle == :box,
:showticklabels => axis[:showaxis],
)
if anchor !== nothing
ax[:anchor] = anchor
end
if domain !== nothing
ax[:domain] = domain
if letter in (:x,:y)
ax[:domain] = plotly_domain(sp, letter)
if RecipesPipeline.is3d(sp)
# don't link 3d axes for synchronized interactivity
x_idx = y_idx = sp[:subplot_index]
else
x_idx, y_idx = plotly_link_indicies(plt, sp)
end
ax[:anchor] = "$(letter==:x ? "y$(y_idx)" : "x$(x_idx)")"
end
ax[:tickangle] = -axis[:rotation]
@@ -246,38 +250,31 @@ function plotly_layout(plt::Plot)
# set to supported framestyle
sp[:framestyle] = _plotly_framestyle(sp[:framestyle])
if ispolar(sp)
# if any(RecipesPipeline.is3d, seriesargs)
if RecipesPipeline.is3d(sp)
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
plotattributes_out[:scene] = KW(
Symbol("xaxis$(spidx)") => plotly_axis(plt, sp[:xaxis], sp),
Symbol("yaxis$(spidx)") => plotly_axis(plt, sp[:yaxis], sp),
Symbol("zaxis$(spidx)") => plotly_axis(plt, sp[:zaxis], sp),
#2.6 multiplier set camera eye such that whole plot can be seen
:camera => KW(
:eye => KW(
:x => cosd(azim)*sind(theta)*2.6,
:y => sind(azim)*sind(theta)*2.6,
:z => cosd(theta)*2.6,
),
),
)
elseif ispolar(sp)
plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis])
plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis])
else
x_domain, y_domain = plotly_domain(sp)
if RecipesPipeline.is3d(sp)
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
plotattributes_out[Symbol(:scene, spidx)] = KW(
:domain => KW(:x => x_domain, :y => y_domain),
Symbol("xaxis$(spidx)") => plotly_axis(sp[:xaxis], sp),
Symbol("yaxis$(spidx)") => plotly_axis(sp[:yaxis], sp),
Symbol("zaxis$(spidx)") => plotly_axis(sp[:zaxis], sp),
#2.6 multiplier set camera eye such that whole plot can be seen
:camera => KW(
:eye => KW(
:x => cosd(azim)*sind(theta)*2.6,
:y => sind(azim)*sind(theta)*2.6,
:z => cosd(theta)*2.6,
),
),
)
else
plotattributes_out[Symbol("xaxis$(x_idx)")] =
plotly_axis(sp[:xaxis], sp, string("y", y_idx) , x_domain)
# don't allow yaxis to be reupdated/reanchored in a linked subplot
if spidx == y_idx
plotattributes_out[Symbol("yaxis$(y_idx)")] =
plotly_axis(sp[:yaxis], sp, string("x", x_idx), y_domain)
end
end
plotattributes_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp)
# don't allow yaxis to be reupdated/reanchored in a linked subplot
spidx == y_idx ? plotattributes_out[Symbol("yaxis$(y_idx)")] = plotly_axis(plt, sp[:yaxis], sp) : nothing
end
# legend
@@ -459,7 +456,7 @@ function plotly_data(series::Series, letter::Symbol, data)
end
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe, :mesh3d)
handle_surface(data)
plotly_surface_data(series, data)
else
plotly_data(data)
end
@@ -469,6 +466,10 @@ plotly_data(v::AbstractArray) = v
plotly_data(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
plotly_surface_data(series::Series, a::AbstractVector) = a
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf)
function plotly_native_data(axis::Axis, data::AbstractArray)
if !isempty(axis[:discrete_values])
construct_categorical_data(data, axis)
@@ -509,17 +510,9 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out = KW()
# these are the axes that the series should be mapped to
if RecipesPipeline.is3d(sp)
spidx = length(plt.subplots) > 1 ? sp[:subplot_index] : ""
plotattributes_out[:xaxis] = "x$spidx"
plotattributes_out[:yaxis] = "y$spidx"
plotattributes_out[:zaxis] = "z$spidx"
plotattributes_out[:scene] = "scene$spidx"
else
x_idx, y_idx = length(plt.subplots) > 1 ? plotly_link_indicies(plt, sp) : ("", "")
plotattributes_out[:xaxis] = "x$(x_idx)"
plotattributes_out[:yaxis] = "y$(y_idx)"
end
x_idx, y_idx = plotly_link_indicies(plt, sp)
plotattributes_out[:xaxis] = "x$(x_idx)"
plotattributes_out[:yaxis] = "y$(y_idx)"
plotattributes_out[:showlegend] = should_add_to_legend(series)
if st == :straightline
@@ -584,7 +577,7 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
plotattributes_out[:showscale] = hascolorbar(sp)
end
@@ -592,7 +585,7 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:type] = "mesh3d"
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
if series[:connections] !== nothing
if series[:connections] != nothing
if typeof(series[:connections]) <: Tuple{Array,Array,Array}
i,j,k = series[:connections]
if !(length(i) == length(j) == length(k))
@@ -609,9 +602,9 @@ function plotly_series(plt::Plot, series::Series)
plotattributes_out[:color] = rgba_string(plot_color(series[:fillcolor], series[:fillalpha]))
plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
plotattributes_out[:showscale] = hascolorbar(sp)
plotattributes_out[:showscale] = hascolorbar(sp)
else
@warn("Plotly: seriestype $st isn't supported.")
return KW()
@@ -704,7 +697,7 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
segments = iter_segments(series, st)
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
needs_scatter_fix = !isscatter && hasmarker && !any(isnan,y) && length(segments) > 1
needs_scatter_fix = !isscatter && hasmarker && !any(isnan,y)
for (i,rng) in enumerate(segments)
plotattributes_out = deepcopy(plotattributes_base)
@@ -795,7 +788,8 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
else
# if fillrange is a tuple with upper and lower limit, plotattributes_out_fillrange
# is the series that will do the filling
plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] = concatenate_fillrange(x[rng], series[:fillrange])
fillrng = Tuple(series[:fillrange][i][rng] for i in 1:2)
plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] = concatenate_fillrange(x[rng], fillrng)
plotattributes_out_fillrange[:line][:width] = 0
delete!(plotattributes_out, :fill)
delete!(plotattributes_out, :fillcolor)
@@ -831,8 +825,8 @@ function plotly_colorbar_hack(series::Series, plotattributes_base::KW, sym::Symb
end
# zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
plotattributes_out[:marker] = KW(
:size => 1e-10,
:opacity => 1e-10,
:size => 0,
:opacity => 0,
:color => [0.5],
:cmin => cmin,
:cmax => cmax,
@@ -882,7 +876,7 @@ html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
const ijulia_initialized = Ref(false)
function plotly_html_head(plt::Plot)
local_file = ("file:///" * plotly_local_file_path[])
local_file = ("file:///" * plotly_local_file_path)
plotly =
use_local_dependencies[] ? local_file : "https://cdn.plot.ly/plotly-1.54.2.min.js"
+32 -64
View File
@@ -25,7 +25,6 @@ pycollections = PyPlot.pyimport("matplotlib.collections")
pyart3d = PyPlot.art3D
pyrcparams = PyPlot.PyDict(PyPlot.matplotlib."rcParams")
# "support" matplotlib v1.5
set_facecolor_sym = if PyPlot.version < v"2"
@warn("You are using Matplotlib $(PyPlot.version), which is no longer officialy supported by the Plots community. To ensure smooth Plots.jl integration update your Matplotlib library to a version >= 2.0.0")
@@ -61,9 +60,6 @@ end
# # anything else just gets a bluesred gradient
# py_colormap(c, α=nothing) = py_colormap(default_gradient(), α)
py_handle_surface(v) = v
py_handle_surface(z::Surface) = z.surf
py_color(s) = py_color(parse(Colorant, string(s)))
py_color(c::Colorant) = (red(c), green(c), blue(c), alpha(c))
py_color(cs::AVec) = map(py_color, cs)
@@ -347,7 +343,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
fix_xy_lengths!(plt, series)
# ax = getAxis(plt, series)
x, y, z = (py_handle_surface(series[letter]) for letter in (:x, :y, :z))
x, y, z = series[:x], series[:y], series[:z]
if st == :straightline
x, y = straightline_data(series)
elseif st == :shape
@@ -515,11 +511,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if st in (:contour, :contour3d)
z = transpose_z(series, z.surf)
if typeof(x)<:Plots.Surface
x = Plots.transpose_z(series, x.surf)
end
if typeof(y)<:Plots.Surface
y = Plots.transpose_z(series, y.surf)
end
if st == :contour3d
extrakw[:extend3d] = true
if !ismatrix(x) || !ismatrix(y)
x, y = repeat(x', length(y), 1), repeat(y, 1, length(x))
end
end
if typeof(series[:linecolor]) <: AbstractArray
@@ -554,17 +555,17 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if st in (:surface, :wireframe)
if z isa AbstractMatrix
if typeof(z) <: AbstractMatrix || typeof(z) <: Surface
x, y, z = map(Array, (x,y,z))
if !ismatrix(x) || !ismatrix(y)
x, y = repeat(x', length(y), 1), repeat(y, 1, length(x))
x = repeat(x', length(y), 1)
y = repeat(y, 1, length(series[:x]))
end
z = transpose_z(series, z)
if st == :surface
if series[:fill_z] !== nothing
# the surface colors are different than z-value
extrakw[:facecolors] = py_shading(
series[:fillcolor],
py_handle_surface(series[:fill_z]),
)
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
extrakw[:shade] = false
else
extrakw[:cmap] = py_fillcolormap(series)
@@ -616,15 +617,15 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
ymin, ymax = ignorenan_extrema(series[:y])
dx = (xmax - xmin) / (length(series[:x]) - 1) / 2
dy = (ymax - ymin) / (length(series[:y]) - 1) / 2
z = if eltype(z) <: Colors.AbstractGray
float(z)
elseif eltype(z) <: Colorant
map(c -> Float64[red(c),green(c),blue(c),alpha(c)], z)
img = Array(transpose_z(series, z.surf))
z = if eltype(img) <: Colors.AbstractGray
float(img)
elseif eltype(img) <: Colorant
map(c -> Float64[red(c),green(c),blue(c),alpha(c)], img)
else
z # hopefully it's in a data format that will "just work" with imshow
end
handle = ax."imshow"(
z;
handle = ax."imshow"(z;
zorder = series[:series_plotindex],
cmap = py_colormap(cgrad(plot_color([:black, :white]))),
vmin = 0.0,
@@ -640,7 +641,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
if st == :heatmap
x, y = heatmap_edges(x, sp[:xaxis][:scale], y, sp[:yaxis][:scale], size(z))
x, y, z = heatmap_edges(x, sp[:xaxis][:scale]), heatmap_edges(y, sp[:yaxis][:scale]), transpose_z(series, z.surf)
expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y)
@@ -726,15 +727,7 @@ function py_set_lims(ax, sp::Subplot, axis::Axis)
getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto)
end
function py_surround_latextext(latexstring, env)
if !isempty(latexstring) && latexstring[1] == '$' && latexstring[end] == '$'
unenclosed = latexstring[2:end-1]
else
unenclosed = latexstring
end
PyPlot.LaTeXStrings.latexstring(env, "{", unenclosed, "}")
end
py_surround_latextext(latexstring, env) = PyPlot.LaTeXStrings.latexstring(env, "{",latexstring[2:end-1],"}")
function py_set_ticks(ax, ticks, letter, env)
ticks == :auto && return
@@ -753,13 +746,7 @@ function py_set_ticks(ax, ticks, letter, env)
axis."set_ticks"(ticks)
elseif ttype == :ticks_and_labels
axis."set_ticks"(ticks[1])
if pyrcparams["text.usetex"]
tick_labels = ticks[2]
else
tick_labels = [py_surround_latextext(ticklabel, env) for ticklabel in ticks[2]]
end
tick_labels = [py_surround_latextext(ticklabel, env) for ticklabel in ticks[2]]
axis."set_ticklabels"(tick_labels)
else
error("Invalid input for $(letter)ticks: $ticks")
@@ -1020,39 +1007,20 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
end
# Set ticks
fontProperties = PyPlot.PyCall.PyDict(
Dict(
"family" => axis[:tickfontfamily],
"size" => py_thickness_scale(plt, axis[:tickfontsize]),
"rotation" => axis[:tickfontrotation],
)
)
positions = getproperty(ax, Symbol("get_",letter,"ticks"))()
pyaxis.set_major_locator(pyticker.FixedLocator(positions))
if RecipesPipeline.is3d(sp)
getproperty(ax, Symbol("set_",letter,"ticklabels"))(
positions;
(Symbol(k) => v for (k, v) in fontProperties)...
)
else
getproperty(ax, Symbol("set_",letter,"ticklabels"))(
positions,
fontdict=fontProperties,
)
end
fontProperties = PyPlot.PyCall.PyDict(Dict("family" => axis[:tickfontfamily],
"size" => py_thickness_scale(plt, axis[:tickfontsize]),
"useTex" => false,
"rotation" => axis[:tickfontrotation]))
getproperty(ax, Symbol("set_",letter,"ticklabels"))(getproperty(ax, Symbol("get_",letter,"ticks"))(), fontProperties)
# workaround to set mathtext.fontspec per Text element
env = "\\mathregular" # matches the outer fonts https://matplotlib.org/tutorials/text/mathtext.html
axis[:ticks] == :native ? nothing : py_set_ticks(ax, ticks, letter, env)
# Tick marks
intensity = 0.5 # This value corresponds to scaling of other grid elements
pyaxis."set_tick_params"(
direction = axis[:tick_direction] == :out ? "out" : "in",
width=py_thickness_scale(plt, intensity),
length= 5 * py_thickness_scale(plt, intensity)
)
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in", width=py_thickness_scale(plt, intensity),
length= 5 * py_thickness_scale(plt, intensity))
getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide])
if get(axis.plotattributes, :flip, false)
+1 -1
View File
@@ -45,7 +45,7 @@ function standalone_html_window(plt::AbstractPlot)
old = use_local_dependencies[] # save state to restore afterwards
# if we open a browser ourself, we can host local files, so
# when we have a local plotly downloaded this is the way to go!
use_local_dependencies[] = isfile(plotly_local_file_path[])
use_local_dependencies[] = isfile(plotly_local_file_path)
filename = write_temp_html(plt)
open_browser_window(filename)
# restore for other backends
+30
View File
@@ -1,3 +1,5 @@
const P2 = GeometryTypes.Point2{Float64}
const P3 = GeometryTypes.Point3{Float64}
@@ -75,6 +77,7 @@ function weave(x,y; ordering = Vector[x,y])
ret
end
"create a star by weaving together points from an outer and inner circle. `n` is the number of arms"
function makestar(n; offset = -0.5, radius = 1.0)
z1 = offset * π
@@ -90,6 +93,7 @@ function makeshape(n; offset = -0.5, radius = 1.0)
Shape(partialcircle(z, z + 2π, n+1, radius))
end
function makecross(; offset = -0.5, radius = 1.0)
z2 = offset * π
z1 = z2 - π/8
@@ -99,6 +103,7 @@ function makecross(; offset = -0.5, radius = 1.0)
ordering=Vector[outercircle,innercircle,outercircle]))
end
from_polar(angle, dist) = P2(dist*cos(angle), dist*sin(angle))
function makearrowhead(angle; h = 2.0, w = 0.4)
@@ -107,6 +112,31 @@ function makearrowhead(angle; h = 2.0, w = 0.4)
from_polar(angle + 0.5π, w) - tip, (0,0)])
end
const _shape_keys = Symbol[
:circle,
:rect,
:star5,
:diamond,
:hexagon,
:cross,
:xcross,
:utriangle,
:dtriangle,
:rtriangle,
:ltriangle,
:pentagon,
:heptagon,
:octagon,
:star4,
:star6,
:star7,
:star8,
:vline,
:hline,
:+,
:x,
]
const _shapes = KW(
:circle => makeshape(20),
:rect => makeshape(4, offset=-0.25),
+4 -13
View File
@@ -1040,23 +1040,15 @@ const _examples = PlotExample[
)
end]
),
PlotExample( # 49
"Polar heatmaps",
"",
[quote
z = (1:4) .+ (1:8)'
heatmap(z, projection = :polar)
end]
),
]
# Some constants for PlotDocs and PlotReferenceImages
_animation_examples = [2, 31]
_backend_skips = Dict(
:gr => [25, 30, 47],
:pyplot => [2, 25, 30, 31, 47, 49],
:plotlyjs => [2, 21, 24, 25, 30, 31, 49],
:plotly => [2, 21, 24, 25, 30, 31, 49],
:pyplot => [2, 25, 30, 31, 47],
:plotlyjs => [2, 21, 24, 25, 30, 31],
:plotly => [2, 21, 24, 25, 30, 31],
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30, 31, 34, 37, 38, 39, 47],
:pgfplotsx => [
2, # animation
@@ -1066,8 +1058,7 @@ _backend_skips = Dict(
30, # @df
31, # animation
32, # spy
47, # mesh3
49, # polar heatmap
47, # mesh3
],
)
+1 -1
View File
@@ -4,7 +4,7 @@ const use_local_plotlyjs = Ref(false)
function _init_ijulia_plotting()
# IJulia is more stable with local file
use_local_plotlyjs[] = isfile(plotly_local_file_path[])
use_local_plotlyjs[] = isfile(plotly_local_file_path)
ENV["MPLBACKEND"] = "Agg"
end
+11 -20
View File
@@ -1,7 +1,5 @@
using REPL
using Pkg.Artifacts
const plotly_local_file_path = Ref("")
function _plots_defaults()
if isdefined(Main, :PLOTS_DEFAULTS)
@@ -15,10 +13,9 @@ end
function __init__()
user_defaults = _plots_defaults()
if haskey(user_defaults, :theme)
theme(pop!(user_defaults, :theme); user_defaults...)
else
default(; user_defaults...)
theme(pop!(user_defaults, :theme))
end
default(; user_defaults...)
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
@@ -44,8 +41,8 @@ function __init__()
include(fn)
end
@require PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5" begin
fn = joinpath(@__DIR__, "backends", "plotlybase.jl")
@require ORCA = "47be7bcc-f1a6-5447-8b36-7eeeff7534fd" begin
fn = joinpath(@__DIR__, "backends", "orca.jl")
include(fn)
end
@@ -77,22 +74,16 @@ function __init__()
end
end
if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == true
artifact_toml = joinpath(@__DIR__, "Artifacts.toml")
plotly_sha = artifact_hash("plotly", artifact_toml)
if plotly_sha === nothing || !artifact_exists(plotly_sha)
plotly_sha = create_artifact() do artifact_dir
download("https://cdn.plot.ly/plotly-1.54.2.min.js", joinpath(artifact_dir, "plotly-1.54.2.min.js"))
end
if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL")
use_local_plotlyjs[] = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local_plotlyjs[]
if use_local_plotlyjs[] && !isfile(plotly_local_file_path)
@warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true")
end
plotly_local_file_path[] = joinpath(artifact_path(plotly_sha), "plotly-1.54.2.min.js")
use_local_plotlyjs[] = true
else
use_local_dependencies[] = use_local_plotlyjs[]
end
use_local_dependencies[] = use_local_plotlyjs[]
@require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin
_show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt)
+29 -1
View File
@@ -4,6 +4,34 @@
to_pixels(m::AbsoluteLength) = m.value / 0.254
const _cbar_width = 5mm
#Base.broadcast(::typeof(Base.:.*), m::Measure, n::Number) = m * n
#Base.broadcast(::typeof(Base.:.*), m::Number, n::Measure) = m * n
Base.:-(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
Base.:-(a::AbstractArray, m::Measure) = map(ai -> ai - m, a)
Base.zero(::Type{typeof(mm)}) = 0mm
Base.one(::Type{typeof(mm)}) = 1mm
Base.typemin(::typeof(mm)) = -Inf*mm
Base.typemax(::typeof(mm)) = Inf*mm
Base.convert(::Type{F}, l::AbsoluteLength) where {F<:AbstractFloat} = convert(F, l.value)
# TODO: these are unintuitive and may cause tricky bugs
# Base.:+(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 + m2.value))
# Base.:+(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (1 + m1.value))
# Base.:-(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 - m2.value))
# Base.:-(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (m1.value - 1))
Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
Base.:/(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value / m1.value)
Base.zero(::Type{typeof(pct)}) = 0pct
Base.one(::Type{typeof(pct)}) = 1pct
Base.typemin(::typeof(pct)) = 0pct
Base.typemax(::typeof(pct)) = 1pct
const defaultbox = BoundingBox(0mm, 0mm, 0mm, 0mm)
left(bbox::BoundingBox) = bbox.x0[1]
@@ -230,7 +258,7 @@ end
grid(args...; kw...)
Create a grid layout for subplots. `args` specify the dimensions, e.g.
`grid(3,2, widths = (0.6,0.4))` creates a grid with three rows and two
`grid(3,2, widths = (0.6,04))` creates a grid with three rows and two
columns of different width.
"""
grid(args...; kw...) = GridLayout(args...; kw...)
+1 -1
View File
@@ -49,7 +49,7 @@ RecipesPipeline.splittable_attribute(plt::Plot, key, val::SeriesAnnotations, len
RecipesPipeline.splittable_attribute(plt, key, val.strs, len)
function RecipesPipeline.split_attribute(plt::Plot, key, val::SeriesAnnotations, indices)
split_strs = RecipesPipeline.split_attribute(plt, key, val.strs, indices)
split_strs = RecipesPipeline.split_attribute(key, val.strs, indices)
return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor)
end
+10 -38
View File
@@ -133,7 +133,7 @@ end
@recipe function f(::Type{Val{:hspan}}, x, y, z)
n = div(length(y), 2)
newx = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n)
newx = repeat([1, 2, 2, 1, NaN], outer = n)
newy = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...)
linewidth --> 0
x := newx
@@ -262,39 +262,24 @@ end
end
end
newx, newy = zeros(3n), zeros(3n)
newz = z!== nothing ? zeros(3n) : nothing
for i = 1:n
rng = (3i - 2):(3i)
newx[rng] = [x[i], x[i], NaN]
if z !== nothing
newy[rng] = [y[i], y[i], NaN]
newz[rng] = [_cycle(fr, i), z[i], NaN]
else
newy[rng] = [_cycle(fr, i), y[i], NaN]
end
newy[rng] = [_cycle(fr, i), y[i], NaN]
end
x := newx
y := newy
if z !== nothing
z := newz
end
fillrange := nothing
seriestype := :path
if plotattributes[:linecolor] == :auto && plotattributes[:marker_z] !== nothing && plotattributes[:line_z] === nothing
line_z := plotattributes[:marker_z]
end
# create a primary series for the markers
# create a secondary series for the markers
if plotattributes[:markershape] != :none
primary := false
@series begin
seriestype := :scatter
x := x
y := y
if z !== nothing
z := z
end
primary := true
label := ""
primary := false
()
end
markershape := :none
@@ -874,7 +859,9 @@ end
x := Plots._bin_centers(edge_x)
y := Plots._bin_centers(edge_y)
z := Surface(permutedims(float_weights))
z := Surface(float_weights)
match_dimensions := true
seriestype := :heatmap
()
end
@@ -931,7 +918,7 @@ end
@recipe function f(::Type{Val{:mesh3d}}, x, y, z)
# As long as no i,j,k are supplied this should work with PyPlot and GR
seriestype := :surface
if plotattributes[:connections] !== nothing
if plotattributes[:connections] != nothing
throw(ArgumentError("Giving triangles using the connections argument is only supported on Plotly backend."))
end
()
@@ -1102,12 +1089,6 @@ function error_coords(errorbar, errordata, otherdata...)
return (ed, od...)
end
# clamp non-NaN values in an array to Base.eps(Float64) for log-scale plots
function clamp_to_eps!(ary)
replace!(x -> x <= 0.0 ? Base.eps(Float64) : x, ary)
nothing
end
# we will create a series of path segments, where each point represents one
# side of an errorbar
@@ -1121,9 +1102,6 @@ end
plotattributes[:x], plotattributes[:y], plotattributes[:z] =
error_coords(xerr, x, y, z)
end
if :xscale keys(plotattributes) && plotattributes[:xscale] == :log10
clamp_to_eps!(plotattributes[:x])
end
()
end
@deps xerror path
@@ -1138,9 +1116,6 @@ end
plotattributes[:y], plotattributes[:x], plotattributes[:z] =
error_coords(yerr, y, x, z)
end
if :yscale keys(plotattributes) && plotattributes[:yscale] == :log10
clamp_to_eps!(plotattributes[:y])
end
()
end
@deps yerror path
@@ -1153,9 +1128,6 @@ end
plotattributes[:z], plotattributes[:x], plotattributes[:y] =
error_coords(zerr, z, x, y)
end
if :zscale keys(plotattributes) && plotattributes[:zscale] == :log10
clamp_to_eps!(plotattributes[:z])
end
()
end
@deps zerror path
@@ -1494,7 +1466,7 @@ end
end
Plots.findnz(A::AbstractSparseMatrix) = SparseArrays.findnz(A)
Plots.findnz(A::AbstractSparseMatrix) = findnz(A)
# fallback function for finding non-zero elements of non-sparse matrices
function Plots.findnz(A::AbstractMatrix)
+2 -2
View File
@@ -432,10 +432,10 @@ zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmi
"Set xticks for an existing plot"
xticks!(v::TicksArgs; kw...) = plot!(; xticks = v, kw...)
xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
"Set yticks for an existing plot"
yticks!(v::TicksArgs; kw...) = plot!(; yticks = v, kw...)
yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
xticks!(
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
+21 -2
View File
@@ -207,6 +207,9 @@ end
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
Base.first(c::Colorant) = c
Base.first(x::Symbol) = x
sortedkeys(plotattributes::Dict) = sort(collect(keys(plotattributes)))
@@ -292,6 +295,13 @@ limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
limsType(lims) = :invalid
# axis_Symbol(letter, postfix) = Symbol(letter * postfix)
# axis_symbols(letter, postfix...) = map(s -> axis_Symbol(letter, s), postfix)
Base.convert(::Type{Vector{T}}, rng::AbstractRange{T}) where {T<:Real} = T[x for x in rng]
Base.convert(::Type{Vector{T}}, rng::AbstractRange{S}) where {T<:Real,S<:Real} = T[x for x in rng]
Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
# recursively merge kw-dicts, e.g. for merging extra_kwargs / extra_plot_kwargs in plotly)
recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...)
@@ -334,8 +344,17 @@ function indices_and_unique_values(z::AbstractArray)
newz, vals
end
handle_surface(z) = z
handle_surface(z::Surface) = permutedims(z.surf)
# this is a helper function to determine whether we need to transpose a surface matrix.
# it depends on whether the backend matches rows to x (transpose_on_match == true) or vice versa
# for example: PyPlot sends rows to y, so transpose_on_match should be true
function transpose_z(plotattributes, z, transpose_on_match::Bool = true)
if plotattributes[:match_dimensions] == transpose_on_match
# z'
permutedims(z, [2,1])
else
z
end
end
function ok(x::Number, y::Number, z::Number = 0)
isfinite(x) && isfinite(y) && isfinite(z)
-1
View File
@@ -11,7 +11,6 @@ import GeometryTypes, GeometryBasics
using Dates
using RecipesBase
include("test_defaults.jl")
include("test_axes.jl")
include("test_axis_letter.jl")
include("test_recipes.jl")
-11
View File
@@ -1,11 +0,0 @@
using Plots, Test
const PLOTS_DEFAULTS = Dict(:theme => :wong2)
Plots.__init__()
@testset "Loading theme" begin
@test plot(1:5)[1][1][:seriescolor] == RGBA(colorant"black")
end
empty!(PLOTS_DEFAULTS)
Plots.__init__()