Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 003cafa98a | |||
| e9f81e23c8 | |||
| ebf6e6bafe | |||
| b19515d9af | |||
| d1c779e49a | |||
| 1ba77d73d7 | |||
| 654efc8acb | |||
| 4fdbadef16 | |||
| 4725014372 | |||
| 90c8fa2b42 | |||
| 21bbf7f1d4 | |||
| 80123e1839 | |||
| 0cae99875c | |||
| f1d1cb7f25 | |||
| 2b42a67b28 | |||
| 7fe6a69a21 | |||
| 60dcfa9a90 | |||
| 3d2f7571a0 | |||
| 86c26085b3 | |||
| 2d5ad2828b | |||
| bae04d05a3 | |||
| bd287f4656 | |||
| 638fe6d245 | |||
| 3f05dc3570 | |||
| 44150ccbe4 | |||
| c15483d593 | |||
| 363f401474 | |||
| a532c97ce2 | |||
| df07dc9377 | |||
| 9cf9edffe0 | |||
| 2ef13c19ea | |||
| 103f0b28ac | |||
| f157c8dc3f | |||
| ade0a2dfdc | |||
| 71189e113e | |||
| 9fe1f55410 | |||
| 827dba1991 | |||
| 6ac7b41eb0 | |||
| 4c7156ca5e | |||
| 9dfc33dc12 | |||
| 317069e2a8 | |||
| cb54dc071f | |||
| b413f0d44e | |||
| 1784d6179a | |||
| 954f002dfe | |||
| 083fe89905 | |||
| 5906d1c8a5 | |||
| bd46b51b94 | |||
| 63e73bc9f0 | |||
| 915eafcea0 | |||
| 63d9363505 | |||
| 721b4b1312 | |||
| f96e239bc0 | |||
| a13e137770 | |||
| 6a1af1c888 | |||
| 729219f5a0 | |||
| bdcc8cdb8d | |||
| 23b852da8f | |||
| 8255096bce | |||
| abde25efe0 | |||
| efb5816bc1 | |||
| 994b543add |
@@ -21,8 +21,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: # NOTE: the versions below should match those in your botconfig
|
||||
- '1.3'
|
||||
- '1.4'
|
||||
- '1.5'
|
||||
os: # NOTE: should match the os setting of your botconfig
|
||||
- ubuntu-latest
|
||||
|
||||
@@ -21,7 +21,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- '1.3'
|
||||
- '1'
|
||||
- 'nightly'
|
||||
os:
|
||||
|
||||
+4
-3
@@ -1,7 +1,7 @@
|
||||
name = "Plots"
|
||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
author = ["Tom Breloff (@tbreloff)"]
|
||||
version = "1.6.8"
|
||||
version = "1.6.12"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
@@ -26,6 +26,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
|
||||
RecipesPipeline = "01d81517-befc-4cb6-b9ec-a95719d0359c"
|
||||
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
|
||||
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
|
||||
Scratch = "6c6a2e73-6563-6170-7368-637461726353"
|
||||
Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
|
||||
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
|
||||
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
||||
@@ -40,6 +41,7 @@ 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"
|
||||
@@ -50,9 +52,8 @@ RecipesPipeline = "0.1.13"
|
||||
Reexport = "0.2"
|
||||
Requires = "1"
|
||||
Showoff = "0.3.1"
|
||||
StableRNGs = "0.1.1"
|
||||
StatsBase = "0.32, 0.33"
|
||||
julia = "1.3"
|
||||
julia = "1.5"
|
||||
|
||||
[extras]
|
||||
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
|
||||
|
||||
@@ -226,7 +226,6 @@ 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,7 +315,6 @@ 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}})
|
||||
|
||||
+588
-607
File diff suppressed because it is too large
Load Diff
@@ -227,7 +227,6 @@ 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,7 +285,6 @@ 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,7 +285,6 @@ 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,7 +226,6 @@ 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,7 +317,6 @@ 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,7 +286,6 @@ 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}})
|
||||
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
|
||||
#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
|
||||
+9
-14
@@ -10,7 +10,7 @@ using Reexport
|
||||
|
||||
import GeometryTypes, GeometryBasics
|
||||
using Dates, Printf, Statistics, Base64, LinearAlgebra, Random
|
||||
import SparseArrays: AbstractSparseMatrix, findnz
|
||||
using SparseArrays
|
||||
|
||||
using FFMPEG
|
||||
|
||||
@@ -25,17 +25,6 @@ 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,
|
||||
@@ -165,6 +154,12 @@ 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
|
||||
|
||||
@@ -229,8 +224,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...) 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::TicksArgs; kw...) = plot!(plt; xticks = ticks, kw...)
|
||||
global yticks!(plt::PlotOrSubplot, ticks::TicksArgs; kw...) = plot!(plt; yticks = ticks, kw...)
|
||||
global xticks!(plt::PlotOrSubplot,
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...)
|
||||
global yticks!(plt::PlotOrSubplot,
|
||||
|
||||
+8
-3
@@ -280,8 +280,6 @@ 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
|
||||
@@ -629,7 +627,6 @@ 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)
|
||||
@@ -1535,8 +1532,16 @@ 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
|
||||
|
||||
|
||||
@@ -316,7 +316,6 @@ 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,
|
||||
@@ -472,7 +471,6 @@ const _pgfplots_attr = merge_with_base_supported([
|
||||
:polar,
|
||||
# :normalize, :weights, :contours,
|
||||
:aspect_ratio,
|
||||
# :match_dimensions,
|
||||
:tick_direction,
|
||||
:framestyle,
|
||||
:camera,
|
||||
@@ -541,7 +539,6 @@ const _pyplot_attr = merge_with_base_supported([
|
||||
:polar,
|
||||
:normalize, :weights,
|
||||
:contours, :aspect_ratio,
|
||||
:match_dimensions,
|
||||
:clims,
|
||||
:inset_subplots,
|
||||
:dpi,
|
||||
@@ -627,7 +624,6 @@ const _hdf5_attr = merge_with_base_supported([
|
||||
:polar,
|
||||
:normalize, :weights,
|
||||
:contours, :aspect_ratio,
|
||||
:match_dimensions,
|
||||
:clims,
|
||||
:inset_subplots,
|
||||
:dpi,
|
||||
@@ -700,7 +696,6 @@ const _inspectdr_attr = merge_with_base_supported([
|
||||
:polar,
|
||||
# :normalize, :weights,
|
||||
# :contours, :aspect_ratio,
|
||||
:match_dimensions,
|
||||
# :clims,
|
||||
# :inset_subplots,
|
||||
:dpi,
|
||||
@@ -761,7 +756,6 @@ const _pgfplotsx_attr = merge_with_base_supported([
|
||||
:ticks,
|
||||
:scale,
|
||||
:flip,
|
||||
:match_dimensions,
|
||||
:titlefontfamily,
|
||||
:titlefontsize,
|
||||
:titlefonthalign,
|
||||
|
||||
+5
-7
@@ -1488,14 +1488,12 @@ function gr_add_series(sp, series)
|
||||
|
||||
GR.savestate()
|
||||
|
||||
x, y, z = series[:x], series[:y], series[:z]
|
||||
x, y, z = (handle_surface(series[letter]) for letter in (:x, :y, :z))
|
||||
xscale, yscale = sp[:xaxis][:scale], sp[:yaxis][:scale]
|
||||
frng = series[:fillrange]
|
||||
|
||||
# recompute data
|
||||
if typeof(z) <: Surface
|
||||
z = transpose_z(series, z.surf, false)
|
||||
elseif ispolar(sp)
|
||||
if ispolar(sp) && z === nothing
|
||||
rmin, rmax = axis_limits(sp, :y)
|
||||
if frng !== nothing
|
||||
_, frng = convert_to_polar(x, frng, (rmin, rmax))
|
||||
@@ -1537,7 +1535,8 @@ function gr_add_series(sp, series)
|
||||
dmin, dmax = GR.gr3.volume(y.v, 0)
|
||||
elseif st in (:heatmap, :image)
|
||||
if !ispolar(series)
|
||||
x, y = heatmap_edges(x, xscale, y, yscale, size(z))
|
||||
# `z` is already transposed, so we need to reverse before passing its size.
|
||||
x, y = heatmap_edges(x, xscale, y, yscale, reverse(size(z)))
|
||||
end
|
||||
if st === :heatmap
|
||||
gr_draw_heatmap(series, x, y, z, clims)
|
||||
@@ -1734,7 +1733,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(sp)
|
||||
xmin, xmax, ymin, ymax = gr_xy_axislims(series[:subplot])
|
||||
GR.setwindow(-ymax, ymax, -ymax, ymax)
|
||||
if ymin > 0
|
||||
@warn "'ymin[1] > 0' (rmin) is not yet supported."
|
||||
@@ -1751,7 +1750,6 @@ 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)
|
||||
|
||||
@@ -646,7 +646,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], Array(opt[:z])'
|
||||
opt[:x], opt[:y], handle_surface(opt[:z])
|
||||
elseif st in (:heatmap, :surface, :wireframe)
|
||||
surface_to_vecs(opt[:x], opt[:y], opt[:z])
|
||||
elseif RecipesPipeline.is3d(st)
|
||||
|
||||
+58
-51
@@ -120,16 +120,17 @@ end
|
||||
|
||||
|
||||
# this method gets the start/end in percentage of the canvas for this axis direction
|
||||
function plotly_domain(sp::Subplot, letter)
|
||||
function plotly_domain(sp::Subplot)
|
||||
figw, figh = sp.plt[:size]
|
||||
pcts = bbox_to_pcts(sp.plotarea, figw*px, figh*px)
|
||||
pcts = plotly_apply_aspect_ratio(sp, sp.plotarea, pcts)
|
||||
i1,i2 = (letter == :x ? (1,3) : (2,4))
|
||||
[pcts[i1], pcts[i1]+pcts[i2]]
|
||||
x_domain = [pcts[1], pcts[1] + pcts[3]]
|
||||
y_domain = [pcts[2], pcts[2] + pcts[4]]
|
||||
return x_domain, y_domain
|
||||
end
|
||||
|
||||
|
||||
function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
|
||||
function plotly_axis(axis, sp, anchor = nothing, domain = nothing)
|
||||
letter = axis[:letter]
|
||||
framestyle = sp[:framestyle]
|
||||
ax = KW(
|
||||
@@ -146,16 +147,11 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
|
||||
:mirror => framestyle == :box,
|
||||
:showticklabels => axis[:showaxis],
|
||||
)
|
||||
|
||||
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)")"
|
||||
if anchor !== nothing
|
||||
ax[:anchor] = anchor
|
||||
end
|
||||
if domain !== nothing
|
||||
ax[:domain] = domain
|
||||
end
|
||||
|
||||
ax[:tickangle] = -axis[:rotation]
|
||||
@@ -250,31 +246,38 @@ function plotly_layout(plt::Plot)
|
||||
# set to supported framestyle
|
||||
sp[:framestyle] = _plotly_framestyle(sp[:framestyle])
|
||||
|
||||
# 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)
|
||||
if ispolar(sp)
|
||||
plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp, sp[:xaxis])
|
||||
plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp, sp[:yaxis])
|
||||
else
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
# legend
|
||||
@@ -456,7 +459,7 @@ function plotly_data(series::Series, letter::Symbol, data)
|
||||
end
|
||||
|
||||
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe, :mesh3d)
|
||||
plotly_surface_data(series, data)
|
||||
handle_surface(data)
|
||||
else
|
||||
plotly_data(data)
|
||||
end
|
||||
@@ -466,10 +469,6 @@ 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)
|
||||
@@ -510,9 +509,17 @@ function plotly_series(plt::Plot, series::Series)
|
||||
plotattributes_out = KW()
|
||||
|
||||
# these are the axes that the series should be mapped to
|
||||
x_idx, y_idx = plotly_link_indicies(plt, sp)
|
||||
plotattributes_out[:xaxis] = "x$(x_idx)"
|
||||
plotattributes_out[:yaxis] = "y$(y_idx)"
|
||||
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
|
||||
plotattributes_out[:showlegend] = should_add_to_legend(series)
|
||||
|
||||
if st == :straightline
|
||||
@@ -577,16 +584,16 @@ 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] = plotly_surface_data(series, series[:fill_z])
|
||||
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
|
||||
end
|
||||
plotattributes_out[:showscale] = hascolorbar(sp)
|
||||
end
|
||||
elseif st == :mesh3d
|
||||
plotattributes_out[:type] = "mesh3d"
|
||||
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
|
||||
|
||||
if series[:connections] != nothing
|
||||
if typeof(series[:connections]) <: Tuple{Array,Array,Array}
|
||||
|
||||
if series[:connections] !== nothing
|
||||
if typeof(series[:connections]) <: Tuple{Array,Array,Array}
|
||||
i,j,k = series[:connections]
|
||||
if !(length(i) == length(j) == length(k))
|
||||
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
|
||||
@@ -602,7 +609,7 @@ 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] = plotly_surface_data(series, series[:fill_z])
|
||||
plotattributes_out[:surfacecolor] = handle_surface(series[:fill_z])
|
||||
end
|
||||
plotattributes_out[:showscale] = hascolorbar(sp)
|
||||
else
|
||||
@@ -697,7 +704,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)
|
||||
needs_scatter_fix = !isscatter && hasmarker && !any(isnan,y) && length(segments) > 1
|
||||
|
||||
for (i,rng) in enumerate(segments)
|
||||
plotattributes_out = deepcopy(plotattributes_base)
|
||||
@@ -875,7 +882,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"
|
||||
|
||||
|
||||
+44
-29
@@ -25,6 +25,7 @@ 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")
|
||||
@@ -60,6 +61,9 @@ 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)
|
||||
@@ -343,7 +347,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
fix_xy_lengths!(plt, series)
|
||||
|
||||
# ax = getAxis(plt, series)
|
||||
x, y, z = series[:x], series[:y], series[:z]
|
||||
x, y, z = (py_handle_surface(series[letter]) for letter in (:x, :y, :z))
|
||||
if st == :straightline
|
||||
x, y = straightline_data(series)
|
||||
elseif st == :shape
|
||||
@@ -511,16 +515,11 @@ 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
|
||||
@@ -555,17 +554,17 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st in (:surface, :wireframe)
|
||||
if typeof(z) <: AbstractMatrix || typeof(z) <: Surface
|
||||
x, y, z = map(Array, (x,y,z))
|
||||
if z isa AbstractMatrix
|
||||
if !ismatrix(x) || !ismatrix(y)
|
||||
x = repeat(x', length(y), 1)
|
||||
y = repeat(y, 1, length(series[:x]))
|
||||
x, y = repeat(x', length(y), 1), repeat(y, 1, length(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], transpose_z(series, series[:fill_z].surf))
|
||||
extrakw[:facecolors] = py_shading(
|
||||
series[:fillcolor],
|
||||
py_handle_surface(series[:fill_z]),
|
||||
)
|
||||
extrakw[:shade] = false
|
||||
else
|
||||
extrakw[:cmap] = py_fillcolormap(series)
|
||||
@@ -617,15 +616,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
|
||||
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)
|
||||
z = if eltype(z) <: Colors.AbstractGray
|
||||
float(z)
|
||||
elseif eltype(z) <: Colorant
|
||||
map(c -> Float64[red(c),green(c),blue(c),alpha(c)], z)
|
||||
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,
|
||||
@@ -641,7 +640,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st == :heatmap
|
||||
x, y, z = heatmap_edges(x, sp[:xaxis][:scale]), heatmap_edges(y, sp[:yaxis][:scale]), transpose_z(series, z.surf)
|
||||
x, y = heatmap_edges(x, sp[:xaxis][:scale], y, sp[:yaxis][:scale], size(z))
|
||||
|
||||
expand_extrema!(sp[:xaxis], x)
|
||||
expand_extrema!(sp[:yaxis], y)
|
||||
@@ -728,7 +727,7 @@ function py_set_lims(ax, sp::Subplot, axis::Axis)
|
||||
end
|
||||
|
||||
function py_surround_latextext(latexstring, env)
|
||||
if latexstring[1] == '$' && latexstring[end] == '$'
|
||||
if !isempty(latexstring) && latexstring[1] == '$' && latexstring[end] == '$'
|
||||
unenclosed = latexstring[2:end-1]
|
||||
else
|
||||
unenclosed = latexstring
|
||||
@@ -1021,16 +1020,32 @@ 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]),
|
||||
# "useTex" => false,
|
||||
"rotation" => axis[:tickfontrotation]))
|
||||
getproperty(ax, Symbol("set_",letter,"ticklabels"))(getproperty(ax, Symbol("get_",letter,"ticks"))(), fontProperties)
|
||||
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
|
||||
|
||||
# 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)
|
||||
|
||||
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"(
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+13
-4
@@ -1040,15 +1040,23 @@ 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],
|
||||
:plotlyjs => [2, 21, 24, 25, 30, 31],
|
||||
:plotly => [2, 21, 24, 25, 30, 31],
|
||||
:pyplot => [2, 25, 30, 31, 47, 49],
|
||||
:plotlyjs => [2, 21, 24, 25, 30, 31, 49],
|
||||
:plotly => [2, 21, 24, 25, 30, 31, 49],
|
||||
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30, 31, 34, 37, 38, 39, 47],
|
||||
:pgfplotsx => [
|
||||
2, # animation
|
||||
@@ -1058,7 +1066,8 @@ _backend_skips = Dict(
|
||||
30, # @df
|
||||
31, # animation
|
||||
32, # spy
|
||||
47, # mesh3
|
||||
47, # mesh3
|
||||
49, # polar heatmap
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+14
-9
@@ -1,4 +1,7 @@
|
||||
using REPL
|
||||
using Scratch
|
||||
|
||||
const plotly_local_file_path = Ref{Union{Nothing, String}}(nothing)
|
||||
|
||||
|
||||
function _plots_defaults()
|
||||
@@ -13,9 +16,10 @@ end
|
||||
function __init__()
|
||||
user_defaults = _plots_defaults()
|
||||
if haskey(user_defaults, :theme)
|
||||
theme(pop!(user_defaults, :theme))
|
||||
theme(pop!(user_defaults, :theme); user_defaults...)
|
||||
else
|
||||
default(; user_defaults...)
|
||||
end
|
||||
default(; user_defaults...)
|
||||
|
||||
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
|
||||
|
||||
@@ -74,16 +78,17 @@ function __init__()
|
||||
end
|
||||
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")
|
||||
if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true"
|
||||
global plotly_local_file_path[] = joinpath(@get_scratch!("plotly"), "plotly-1.54.2.min.js")
|
||||
if !isfile(plotly_local_file_path[])
|
||||
download("https://cdn.plot.ly/plotly-1.54.2.min.js", plotly_local_file_path[])
|
||||
end
|
||||
else
|
||||
use_local_dependencies[] = use_local_plotlyjs[]
|
||||
|
||||
use_local_plotlyjs[] = true
|
||||
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)
|
||||
|
||||
+1
-29
@@ -4,34 +4,6 @@
|
||||
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]
|
||||
@@ -258,7 +230,7 @@ end
|
||||
grid(args...; kw...)
|
||||
|
||||
Create a grid layout for subplots. `args` specify the dimensions, e.g.
|
||||
`grid(3,2, widths = (0.6,04))` creates a grid with three rows and two
|
||||
`grid(3,2, widths = (0.6,0.4))` creates a grid with three rows and two
|
||||
columns of different width.
|
||||
"""
|
||||
grid(args...; kw...) = GridLayout(args...; kw...)
|
||||
|
||||
+1
-1
@@ -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(key, val.strs, indices)
|
||||
split_strs = RecipesPipeline.split_attribute(plt, key, val.strs, indices)
|
||||
return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor)
|
||||
end
|
||||
|
||||
|
||||
+4
-6
@@ -280,7 +280,7 @@ end
|
||||
end
|
||||
fillrange := nothing
|
||||
seriestype := :path
|
||||
if plotattributes[:linecolor] == :auto && plotattributes[:marker_z] !== nothing && plotattributes[:line_z] == nothing
|
||||
if plotattributes[:linecolor] == :auto && plotattributes[:marker_z] !== nothing && plotattributes[:line_z] === nothing
|
||||
line_z := plotattributes[:marker_z]
|
||||
end
|
||||
|
||||
@@ -874,9 +874,7 @@ end
|
||||
|
||||
x := Plots._bin_centers(edge_x)
|
||||
y := Plots._bin_centers(edge_y)
|
||||
z := Surface(float_weights)
|
||||
|
||||
match_dimensions := true
|
||||
z := Surface(permutedims(float_weights))
|
||||
seriestype := :heatmap
|
||||
()
|
||||
end
|
||||
@@ -933,7 +931,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
|
||||
()
|
||||
@@ -1496,7 +1494,7 @@ end
|
||||
end
|
||||
|
||||
|
||||
Plots.findnz(A::AbstractSparseMatrix) = findnz(A)
|
||||
Plots.findnz(A::AbstractSparseMatrix) = SparseArrays.findnz(A)
|
||||
|
||||
# fallback function for finding non-zero elements of non-sparse matrices
|
||||
function Plots.findnz(A::AbstractMatrix)
|
||||
|
||||
+2
-2
@@ -432,10 +432,10 @@ zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmi
|
||||
|
||||
|
||||
"Set xticks for an existing plot"
|
||||
xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
|
||||
xticks!(v::TicksArgs; kw...) = plot!(; xticks = v, kw...)
|
||||
|
||||
"Set yticks for an existing plot"
|
||||
yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
|
||||
yticks!(v::TicksArgs; kw...) = plot!(; yticks = v, kw...)
|
||||
|
||||
xticks!(
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
|
||||
|
||||
+2
-21
@@ -207,9 +207,6 @@ 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)))
|
||||
|
||||
@@ -295,13 +292,6 @@ 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...)
|
||||
@@ -344,17 +334,8 @@ function indices_and_unique_values(z::AbstractArray)
|
||||
newz, vals
|
||||
end
|
||||
|
||||
# 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
|
||||
handle_surface(z) = z
|
||||
handle_surface(z::Surface) = permutedims(z.surf)
|
||||
|
||||
function ok(x::Number, y::Number, z::Number = 0)
|
||||
isfinite(x) && isfinite(y) && isfinite(z)
|
||||
|
||||
@@ -11,6 +11,20 @@ import GeometryTypes, GeometryBasics
|
||||
using Dates
|
||||
using RecipesBase
|
||||
|
||||
@testset "Plotly standalone" begin
|
||||
@test Plots.plotly_local_file_path[] === nothing
|
||||
temp = Plots.use_local_dependencies[]
|
||||
withenv("PLOTS_HOST_DEPENDENCY_LOCAL" => true) do
|
||||
Plots.__init__()
|
||||
@test Plots.plotly_local_file_path[] isa String
|
||||
@test isfile(Plots.plotly_local_file_path[])
|
||||
@test Plots.use_local_dependencies[] = true
|
||||
end
|
||||
Plots.plotly_local_file_path[] = nothing
|
||||
Plots.use_local_dependencies[] = temp
|
||||
end # testset
|
||||
|
||||
include("test_defaults.jl")
|
||||
include("test_axes.jl")
|
||||
include("test_axis_letter.jl")
|
||||
include("test_recipes.jl")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
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__()
|
||||
Reference in New Issue
Block a user