Compare commits

..

71 Commits

Author SHA1 Message Date
Daniel Schwabeneder 4a57f462bc Merge pull request #2172 from daschw/release
prepare release
2019-09-06 09:39:18 +02:00
Daniel Schwabeneder 11ae5ea014 prepare release 2019-09-06 09:38:23 +02:00
Daniel Schwabeneder 4cb3e6a23c Merge pull request #2170 from daschw/vline
swap x/y formatters for vline
2019-09-04 21:11:25 +02:00
Daniel Schwabeneder dd645bcd9f swap x/y formatters for vline 2019-09-02 00:04:11 +02:00
Daniel Schwabeneder bccf4ef563 Merge pull request #2167 from daschw/pyplot
always return positive linthresh for pyplot with log scales
2019-08-31 10:17:44 +02:00
Yuval 85e2534e93 Merge pull request #2165 from yha/yha-any
Correctly typed vector in convertToAnyVector
2019-08-30 11:38:25 +03:00
Daniel Schwabeneder 2c57e0c958 always return positive linthresh for pyplot with log scales 2019-08-29 14:13:57 +02:00
Daniel Schwabeneder cb161a25da Merge pull request #2166 from daschw/remove-show
remove `@show`s
2019-08-29 09:36:28 +02:00
Daniel Schwabeneder a4380586e9 remove @shows 2019-08-29 09:35:02 +02:00
Daniel Schwabeneder f2a583a599 Merge pull request #2164 from daschw/pyplot
avoid annotation clipping for pyplot
2019-08-29 09:27:57 +02:00
yha 3ea4c8d9ca Correctly typed vector for all number/missing or all string/missing input 2019-08-29 02:36:23 +03:00
Daniel Schwabeneder 30f321d88b avoid annotation clipping for pyplot 2019-08-28 23:36:46 +02:00
Daniel Schwabeneder 1db3b69489 Merge pull request #2162 from daschw/any
allow plotting of Any vectors and 3D plots
2019-08-28 23:24:24 +02:00
Daniel Schwabeneder 3a775315b9 Merge pull request #2163 from daschw/coords
small coords bug-fix
2019-08-28 21:34:22 +02:00
Daniel Schwabeneder 1ed9bcae5c small coords bug-fix 2019-08-28 18:43:01 +02:00
Daniel Schwabeneder 03d57e690c allow 3D plotting 2019-08-27 19:08:30 +02:00
Daniel Schwabeneder 4247584df2 delete left-over text 2019-08-27 16:43:41 +02:00
Daniel Schwabeneder 844c3f7002 allow plotting of Any vectors 2019-08-27 14:15:01 +02:00
Daniel Schwabeneder ff774dc409 Merge pull request #2159 from daschw/legendtitlefont
Specify legend title font in GR and PyPlot
2019-08-27 09:11:07 +02:00
Daniel Schwabeneder 9fd7a84b48 legendtitlefont implementation for pyplot 2019-08-26 11:59:47 +02:00
Daniel Schwabeneder e555f679c1 implementation for GR 2019-08-26 10:55:46 +02:00
Daniel Schwabeneder 89613bfee5 add legendtitlefont function 2019-08-26 10:45:13 +02:00
Daniel Schwabeneder 3fdf87a955 add legendtitlefont attributes 2019-08-26 10:37:07 +02:00
Daniel Schwabeneder 0f07975857 Merge pull request #2153 from pkofod/patch-1
Delete pushtomaster.sh
2019-08-26 09:37:54 +02:00
Patrick Kofod Mogensen 48a245559c Delete pushtomaster.sh
`dev` is dead
2019-08-20 15:17:35 +02:00
Christopher Rackauckas 648f26f075 Merge pull request #2148 from JuliaPlots/nothing
use === nothing
2019-08-20 08:36:04 -04:00
Yuval 808e20588e one more != --> !== 2019-08-18 23:31:34 +03:00
Chris Rackauckas 82dd5bf3eb != nothing -> !== nothing 2019-08-17 14:45:54 -04:00
Chris Rackauckas 0950c738e3 fix !== 2019-08-17 14:20:23 -04:00
Chris Rackauckas f12f6db310 use === nothing
Should decrease compile times
2019-08-17 14:17:27 -04:00
Yuval ae4031b993 Merge pull request #2133 from yha/dict-recipe
Recipe for plotting dicts
2019-08-14 16:36:07 +03:00
Daniel Schwabeneder 2495d2a1e9 Merge pull request #2142 from daschw/register
prepare release
2019-08-14 13:32:16 +03:00
Daniel Schwabeneder 0a97b08c72 prepare release 2019-08-14 12:31:56 +02:00
Daniel Schwabeneder e0a89c55ac Merge pull request #2140 from yha/gr-heatmap-flip
Fix GR axis flip for heatmap and image plots
2019-08-14 13:22:43 +03:00
Daniel Schwabeneder 75ac34b719 Merge pull request #2141 from benchislett/handle-empty-anim
Add handling for empty animation build error (fix #2138)
2019-08-14 10:38:51 +03:00
benchislett 2072c54c53 Add handling for animation build with 0 frames 2019-08-14 00:03:19 +09:00
yha 6e1ed63005 Fix GR axis flip for heatmap & image by removing "manual" axis flip 2019-08-13 17:46:22 +03:00
Yuval 17e59daeb4 Merge pull request #2139 from yha/ribbons
Fix ribbons specified as two-tuples.
2019-08-13 17:06:06 +03:00
yha 69e83ef89f Typo fix 2019-08-13 17:05:36 +03:00
yha b2707f5c8a Fix ribbons specified as two-tuples. 2019-08-13 15:27:01 +03:00
yha 0fd24e5210 Generalize dict recipe for any element type. Do not default to :bar seriestype. 2019-08-12 14:12:00 +03:00
Yuval 3dcc7e5556 Merge pull request #2135 from yha/char-recipe
Replace low-level Char handling with a type recipe.
2019-08-11 18:37:31 +03:00
unknown 57ebeae1ad Replace low-level Char handling with a type recipe. 2019-08-09 01:12:39 +03:00
yha 9e35cc3fe1 Recipe for plotting dicts as bars. 2019-08-08 19:05:53 +03:00
Daniel Schwabeneder 3e1258aa0c Merge pull request #2132 from daschw/plotly-animation
Fix Plotly plots with one-element series (fix #2014)
2019-08-08 17:12:16 +02:00
Daniel Schwabeneder 96e1b1d105 Merge pull request #2131 from daschw/plotlyjs
PlotlyJS backend rewrite (fix #1721 #1756 #1934 #2003)
2019-08-08 17:08:02 +02:00
Daniel Schwabeneder fe80e486aa don't return undef dict 2019-08-08 12:58:29 +02:00
Daniel Schwabeneder ad051f21c1 small cosmetics 2019-08-07 21:45:55 +02:00
Daniel Schwabeneder ac24a4ae19 cleanup 2019-08-07 16:50:09 +02:00
Daniel Schwabeneder 7ae43ee9f6 use plotly implementation for html/js/ijulia 2019-08-07 16:40:52 +02:00
Daniel Schwabeneder 0e79070ad8 create syncplot at show/display 2019-08-07 16:39:39 +02:00
Daniel Schwabeneder f11b976574 Merge pull request #2128 from daschw/release
prepare release
2019-08-07 09:29:23 +02:00
Daniel Schwabeneder 59da5d5deb prepare release 2019-08-07 09:27:05 +02:00
Daniel Schwabeneder 0deb7038e6 Merge pull request #2124 from daschw/chars
handle chars
2019-08-07 09:19:53 +02:00
Daniel Schwabeneder 2ef692c690 Merge pull request #2125 from daschw/plotly-html
Fix saving to html and IJulia show for plotly (fix #1985)
2019-08-07 09:11:36 +02:00
Daniel Schwabeneder 9228c0b9ec improve plotly html formatting 2019-08-06 16:08:49 +02:00
Daniel Schwabeneder 89d02b1d67 allow plotly plotting in ijulia 2019-08-06 15:02:04 +02:00
Daniel Schwabeneder a63a9248d6 handle chars 2019-08-06 14:05:35 +02:00
Jack Devine 79777adc07 Merge pull request #2122 from JackDevine/expand_path
Expand paths beginning with ~ on unix systems.
2019-08-06 21:30:49 +12:00
JackDevine 5619feb6c0 Expand paths beginning with ~ on unix systems. 2019-08-06 20:40:09 +12:00
Daniel Schwabeneder f15a721db6 Merge pull request #2119 from daschw/palette
don't split color_palette into groups (fix #2104)
2019-08-02 15:50:57 +02:00
Daniel Schwabeneder d6b3b68cd9 don't split color_palette into groups 2019-08-02 14:54:32 +02:00
Yuval 78785fa8fe Merge pull request #2110 from yha/convertToAny
convertToAnyVector cleanup. Adds missing support in heatmap/volume.
2019-07-31 00:33:39 +03:00
yha 74c69f575f Fix general vec method 2019-07-25 18:51:04 +03:00
yha 12e34bb24f Fix comment, move all3D method 2019-07-25 18:29:49 +03:00
yha 4ac5484b4f convertToAnyVector cleanup. Adds missing support in heatmap/volume. 2019-07-25 18:08:37 +03:00
Daniel Schwabeneder 8306619faf Merge pull request #2109 from yha/datetime-fix
Restore Date, DateTime and Time recipes
2019-07-25 15:49:14 +02:00
yha 5673477428 Restore Date, DateTime and Time recipes 2019-07-25 16:05:08 +03:00
Daniel Schwabeneder 84c5b67574 Merge pull request #2035 from wfrgra/date_period_recipes
add recipes for time periods
2019-07-18 11:37:15 +02:00
Will Grant 068523fac1 neaten change by implementing with a for loop 2019-06-17 17:44:24 +10:00
Will Grant 6d6d4f14b5 add recipes for time periods 2019-05-24 11:27:09 +10:00
28 changed files with 334 additions and 296 deletions
+24
View File
@@ -11,6 +11,30 @@
---
## (current master)
## 0.26.3
- fix `vline` with dates
- fix PyPlot logscale bug
- avoid annotation clipping for PyPlot
- allow plotting of Any vectors and 3D plotting again in convertToAnyVector
- specify legend title font in GR and PyPlot
- delete `pushtomaster.sh`
- use `=== nothing`
## 0.26.2
- improve empty animation build error
- fix GR axis flip for heatmaps and images
- fix ribbons specified as tuples
- add Char recipe
- fix Plotly plots with single-element series
- rewrite PlotlyJS backend
## 0.26.1
- handle `Char`s as input data
- fix html saving for Plotly
- expand ~ in paths on UNIX systems
- convertToAnyVector clean-up
- fix color_palette grouping issue
## 0.26.0
- use FFMPEG.jl
- add missing method for convertToAnyVector
+1 -1
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.26.0"
version = "0.26.3"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
-4
View File
@@ -1,4 +0,0 @@
git checkout master
git merge --ff-only dev
git push origin master
git checkout dev
+1 -1
View File
@@ -1,6 +1,6 @@
module Plots
_current_plots_version = v"0.25.0"
_current_plots_version = v"0.26.1"
using Reexport
+10 -5
View File
@@ -60,17 +60,22 @@ end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim, fn, false; kw...)
function buildanimation(animdir::AbstractString, fn::AbstractString,
function buildanimation(anim::Animation, fn::AbstractString,
is_animated_gif::Bool=true;
fps::Integer = 20, loop::Integer = 0,
variable_palette::Bool=false,
show_msg::Bool=true)
fn = abspath(fn)
if length(anim.frames) == 0
throw(ArgumentError("Cannot build empty animations"))
end
fn = abspath(expanduser(fn))
animdir = anim.dir
if is_animated_gif
if variable_palette
+8 -1
View File
@@ -50,7 +50,7 @@ const _arg_desc = KW(
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
:colorbar_entry => "Bool. Include this series in the color bar? Set to `false` to exclude.",
# plot args
:plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)",
:background_color => "Color Type. Base color for all backgrounds.",
@@ -95,9 +95,16 @@ const _arg_desc = KW(
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
:legendtitlefontsize => "Integer. Font pointsize the legend title.",
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
:legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center",
:legendtitlefontrotation => "Real. Font rotation of the legend title",
:legendtitlefontcolor => "Color Type. Font color of the legend title",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.",
:legendtitlefont => "Font. Font of the legend title.",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
:projection => "Symbol or String. '3d' or 'polar'",
:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.",
+52 -34
View File
@@ -336,6 +336,12 @@ const _subplot_defaults = KW(
:legendfontvalign => :vcenter,
:legendfontrotation => 0.0,
:legendfontcolor => :match,
:legendtitlefontfamily => :match,
:legendtitlefontsize => 11,
:legendtitlefonthalign => :hcenter,
:legendtitlefontvalign => :vcenter,
:legendtitlefontrotation => 0.0,
:legendtitlefontcolor => :match,
:annotations => [], # annotation tuples... list of (x,y,annotation)
:projection => :none, # can also be :polar or :3d
:aspect_ratio => :none, # choose from :none or :equal
@@ -450,6 +456,7 @@ const _initial_axis_defaults = deepcopy(_axis_defaults)
# to be able to reset font sizes to initial values
const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize],
:legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize])
@@ -685,15 +692,15 @@ function processLineArg(plotattributes::KW, arg)
plotattributes[:linestyle] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[:linewidth] = arg.width)
arg.color == nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:linealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:linestyle] = arg.style)
arg.width === nothing || (plotattributes[:linewidth] = arg.width)
arg.color === nothing || (plotattributes[:linecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:linealpha] = arg.alpha)
arg.style === nothing || (plotattributes[:linestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows)
plotattributes[:arrow] = arg
@@ -724,15 +731,15 @@ function processMarkerArg(plotattributes::KW, arg)
plotattributes[:markerstrokestyle] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[:markerstrokewidth] = arg.width)
arg.color == nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
arg.style == nothing || (plotattributes[:markerstrokestyle] = arg.style)
arg.width === nothing || (plotattributes[:markerstrokewidth] = arg.width)
arg.color === nothing || (plotattributes[:markerstrokecolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:markerstrokealpha] = arg.alpha)
arg.style === nothing || (plotattributes[:markerstrokestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:markersize] = arg.size)
arg.color == nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:markeralpha] = arg.alpha)
arg.size === nothing || (plotattributes[:markersize] = arg.size)
arg.color === nothing || (plotattributes[:markercolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:markeralpha] = arg.alpha)
# linealpha
elseif allAlphas(arg)
@@ -757,9 +764,9 @@ end
function processFillArg(plotattributes::KW, arg)
# fr = get(plotattributes, :fillrange, 0)
if typeof(arg) <: Brush
arg.size == nothing || (plotattributes[:fillrange] = arg.size)
arg.color == nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[:fillalpha] = arg.alpha)
arg.size === nothing || (plotattributes[:fillrange] = arg.size)
arg.color === nothing || (plotattributes[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
elseif typeof(arg) <: Bool
plotattributes[:fillrange] = arg ? 0 : nothing
@@ -793,10 +800,10 @@ function processGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :gridstyle)] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
arg.width === nothing || (plotattributes[Symbol(letter, :gridlinewidth)] = arg.width)
arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style === nothing || (plotattributes[Symbol(letter, :gridstyle)] = arg.style)
# linealpha
elseif allAlphas(arg)
@@ -822,10 +829,10 @@ function processMinorGridArg!(plotattributes::KW, arg, letter)
plotattributes[Symbol(letter, :minorgrid)] = true
elseif typeof(arg) <: Stroke
arg.width == nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
arg.color == nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha == nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
arg.style == nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
arg.width === nothing || (plotattributes[Symbol(letter, :minorgridlinewidth)] = arg.width)
arg.color === nothing || (plotattributes[Symbol(letter, :foreground_color_minor_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha === nothing || (plotattributes[Symbol(letter, :minorgridalpha)] = arg.alpha)
arg.style === nothing || (plotattributes[Symbol(letter, :minorgridstyle)] = arg.style)
plotattributes[Symbol(letter, :minorgrid)] = true
# linealpha
@@ -930,6 +937,15 @@ function preprocessArgs!(plotattributes::KW)
end
end
# vline accesses the y argument but actually maps it to the x axis.
# Hence, we have to swap formatters
if get(plotattributes, :seriestype, :path) == :vline
xformatter = get(plotattributes, :xformatter, :auto)
yformatter = get(plotattributes, :yformatter, :auto)
plotattributes[:xformatter] = yformatter
plotattributes[:yformatter] = xformatter
end
# handle grid args common to all axes
args = pop!(plotattributes, :grid, ())
for arg in wraptuple(args)
@@ -961,7 +977,7 @@ function preprocessArgs!(plotattributes::KW)
end
end
# fonts
for fontname in (:titlefont, :legendfont)
for fontname in (:titlefont, :legendfont, :legendtitlefont)
args = pop!(plotattributes, fontname, ())
for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg)
@@ -1121,7 +1137,7 @@ end
function _filter_input_data!(plotattributes::KW)
idxfilter = pop!(plotattributes, :idxfilter, nothing)
if idxfilter != nothing
if idxfilter !== nothing
filter_data!(plotattributes, idxfilter)
end
end
@@ -1237,7 +1253,7 @@ end
# v = plotattributes[k]
# plotattributes[k] = if v == :match
# match_color
# elseif v == nothing
# elseif v === nothing
# plot_color(RGBA(0,0,0,0))
# else
# v
@@ -1246,7 +1262,7 @@ end
function color_or_nothing!(plotattributes::KW, k::Symbol)
v = plotattributes[k]
plotattributes[k] = if v == nothing || v == false
plotattributes[k] = if v === nothing || v == false
RGBA{Float64}(0,0,0,0)
elseif v != :match
plot_color(v)
@@ -1271,8 +1287,10 @@ const _match_map = KW(
:bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot,
:legendfontfamily => :fontfamily_subplot,
:legendtitlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot,
:legendfontcolor => :foreground_color_subplot,
:legendtitlefontcolor => :foreground_color_subplot,
:tickfontcolor => :foreground_color_text,
:guidefontcolor => :foreground_color_guide,
)
@@ -1563,11 +1581,11 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
# update alphas
for asym in (:linealpha, :markeralpha, :fillalpha)
if plotattributes[asym] == nothing
if plotattributes[asym] === nothing
plotattributes[asym] = plotattributes[:seriesalpha]
end
end
if plotattributes[:markerstrokealpha] == nothing
if plotattributes[:markerstrokealpha] === nothing
plotattributes[:markerstrokealpha] = plotattributes[:markeralpha]
end
@@ -1602,13 +1620,13 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot)
end
# if marker_z, fill_z or line_z are set, ensure we have a gradient
if plotattributes[:marker_z] != nothing
if plotattributes[:marker_z] !== nothing
ensure_gradient!(plotattributes, :markercolor, :markeralpha)
end
if plotattributes[:line_z] != nothing
if plotattributes[:line_z] !== nothing
ensure_gradient!(plotattributes, :linecolor, :linealpha)
end
if plotattributes[:fill_z] != nothing
if plotattributes[:fill_z] !== nothing
ensure_gradient!(plotattributes, :fillcolor, :fillalpha)
end
+7 -7
View File
@@ -67,7 +67,7 @@ function process_axis_arg!(plotattributes::KW, arg, letter = "")
elseif T <: AVec
plotattributes[Symbol(letter,:ticks)] = arg
elseif arg == nothing
elseif arg === nothing
plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs
@@ -166,7 +166,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
# or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
if ticks == nothing && scale == :identity
if ticks === nothing && scale == :identity
if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes
@@ -184,7 +184,7 @@ function optimal_ticks_and_labels(sp::Subplot, axis::Axis, ticks = nothing)
end
# get a list of well-laid-out ticks
if ticks == nothing
if ticks === nothing
scaled_ticks = optimize_ticks(
sf(amin),
sf(amax);
@@ -382,7 +382,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
end
expand_extrema!(axis, data)
elseif data != nothing
elseif data !== nothing
# TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value)
@@ -399,10 +399,10 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
# expand for fillrange
fr = plotattributes[:fillrange]
if fr == nothing && plotattributes[:seriestype] == :bar
if fr === nothing && plotattributes[:seriestype] == :bar
fr = 0.0
end
if fr != nothing && !all3D(plotattributes)
if fr !== nothing && !all3D(plotattributes)
axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple
for fri in fr
@@ -419,7 +419,7 @@ function expand_extrema!(sp::Subplot, plotattributes::KW)
data = plotattributes[dsym]
bw = plotattributes[:bar_width]
if bw == nothing
if bw === nothing
bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end
axis = sp.attr[Symbol(dsym, :axis)]
+1 -1
View File
@@ -77,7 +77,7 @@ text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(l
# account for the size/length/rotation of tick labels
function tick_padding(sp::Subplot, axis::Axis)
ticks = get_ticks(sp, axis)
if ticks == nothing
if ticks === nothing
0mm
else
vals, labs = ticks
+18 -23
View File
@@ -147,7 +147,7 @@ gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.inqmathtex(x, y, s[2:end-1])
elseif findfirst(isequal('\\'), s) != nothing || occursin("10^{", s)
elseif findfirst(isequal('\\'), s) !== nothing || occursin("10^{", s)
GR.inqtextext(x, y, s)
else
GR.inqtext(x, y, s)
@@ -159,7 +159,7 @@ gr_text(x, y, s::Symbol) = gr_text(x, y, string(s))
function gr_text(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.mathtex(x, y, s[2:end-1])
elseif findfirst(isequal('\\'), s) != nothing || occursin("10^{", s)
elseif findfirst(isequal('\\'), s) !== nothing || occursin("10^{", s)
GR.textext(x, y, s)
else
GR.text(x, y, s)
@@ -237,7 +237,7 @@ gr_z_axislims(sp::Subplot) = axis_limits(sp, :z)
gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)...
function gr_lims(sp::Subplot, axis::Axis, adjust::Bool, expand = nothing)
if expand != nothing
if expand !== nothing
expand_extrema!(axis, expand)
end
lims = axis_limits(sp, axis[:letter])
@@ -629,11 +629,11 @@ function gr_get_color(series::Series)
series[:fillcolor]
elseif st in (:contour, :wireframe)
series[:linecolor]
elseif series[:marker_z] != nothing
elseif series[:marker_z] !== nothing
series[:markercolor]
elseif series[:line_z] != nothing
elseif series[:line_z] !== nothing
series[:linecolor]
elseif series[:fill_z] != nothing
elseif series[:fill_z] !== nothing
series[:fillcolor]
end
end
@@ -879,12 +879,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.savestate()
GR.selntran(0)
GR.setscale(0)
gr_set_font(legendfont(sp))
if sp[:legendtitle] != nothing
if sp[:legendtitle] !== nothing
gr_set_font(legendtitlefont(sp))
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
legendw = tbx[3] - tbx[1]
legendn += 1
end
gr_set_font(legendfont(sp))
for series in series_list(sp)
should_add_to_legend(series) || continue
legendn += 1
@@ -1247,7 +1248,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if typeof(z) <: Surface
z = vec(transpose_z(series, z.surf, false))
elseif ispolar(sp)
if frng != nothing
if frng !== nothing
_, frng = convert_to_polar(x, frng, (rmin, rmax))
end
x, y = convert_to_polar(x, y, (rmin, rmax))
@@ -1258,11 +1259,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if st in (:path, :scatter, :straightline)
if x != nothing && length(x) > 1
if x !== nothing && length(x) > 1
lz = series[:line_z]
segments = iter_segments(series)
# do area fill
if frng != nothing
if frng !== nothing
GR.setfillintstyle(GR.INTSTYLE_SOLID)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i, rng) in enumerate(segments)
@@ -1301,7 +1302,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
plot_color(series[:linecolor]) in (black,[black])
end
h = gr_contour_levels(series, clims)
if series[:fillrange] != nothing
if series[:fillrange] !== nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines")
end
@@ -1337,9 +1338,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if !ispolar(sp)
xmin, xmax, ymin, ymax = xy_lims
m, n = length(x), length(y)
xinds = sort(1:m, rev = xaxis[:flip])
yinds = sort(1:n, rev = yaxis[:flip])
z = reshape(reshape(z, m, n)[xinds, yinds], m*n)
GR.setspace(zmin, zmax, 0, 90)
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad()
colors = [plot_color(grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)], series[:fillalpha]) for zi=z]
@@ -1454,9 +1452,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :image
z = transpose_z(series, series[:z].surf, true)'
w, h = size(z)
xinds = sort(1:w, rev = xaxis[:flip])
yinds = sort(1:h, rev = yaxis[:flip])
z = z[xinds, yinds]
xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
if eltype(z) <: Colors.AbstractGray
grey = round.(UInt8, clamp.(float(z) * 255, 0, 255))
@@ -1502,12 +1497,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_set_line(1, :solid, sp[:foreground_color_legend])
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
i = 0
if sp[:legendtitle] != nothing
if sp[:legendtitle] !== nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(sp[:legendfontcolor])
gr_set_transparency(sp[:legendfontcolor])
gr_set_font(legendtitlefont(sp))
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy
gr_set_font(legendfont(sp))
end
for series in series_list(sp)
should_add_to_legend(series) || continue
@@ -1515,7 +1510,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
lc = get_linecolor(series, clims)
gr_set_line(get_linewidth(series), get_linestyle(series), lc) #, series[:linealpha])
if (st == :shape || series[:fillrange] != nothing) && series[:ribbon] == nothing
if (st == :shape || series[:fillrange] !== nothing) && series[:ribbon] === nothing
fc = get_fillcolor(series, clims)
gr_set_fill(fc) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01
@@ -1532,7 +1527,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if st in (:path, :straightline)
gr_set_transparency(lc, get_linealpha(series))
if series[:fillrange] == nothing || series[:ribbon] != nothing
if series[:fillrange] === nothing || series[:ribbon] !== nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
else
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos+0.4dy, ypos+0.4dy])
+2 -2
View File
@@ -121,9 +121,9 @@ function _create_backend_figure(plt::Plot{InspectDRBackend})
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot != nothing
if plt[:overwrite_figure] && mplot !== nothing
mplot.subplots = [] #Reset
if gplot != nothing #Ensure still references current plot
if gplot !== nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
+4 -4
View File
@@ -96,7 +96,7 @@ pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(plotattributes, i)
if fa != nothing
if fa !== nothing
a = fa
end
"fill = $cstr, fill opacity=$a"
@@ -216,12 +216,12 @@ function pgf_series(sp::Subplot, series::Series)
# add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if plotattributes[:fillrange] != nothing
if plotattributes[:fillrange] !== nothing
push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
else
kw[:legendentry] = plotattributes[:label]
if st == :shape # || plotattributes[:fillrange] != nothing
if st == :shape # || plotattributes[:fillrange] !== nothing
push!(style, "area legend")
end
end
@@ -238,7 +238,7 @@ function pgf_series(sp::Subplot, series::Series)
kw[:style] = join(style, ',')
# add fillrange
if series[:fillrange] != nothing && st != :shape
if series[:fillrange] !== nothing && st != :shape
push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
end
+32 -25
View File
@@ -347,7 +347,7 @@ function plotly_layout(plt::Plot)
end
function plotly_layout_json(plt::Plot)
JSON.json(plotly_layout(plt))
JSON.json(plotly_layout(plt), 4)
end
@@ -403,7 +403,7 @@ end
function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)]
data = if axis[:ticks] == :native && data != nothing
data = if axis[:ticks] == :native && data !== nothing
plotly_native_data(axis, data)
else
data
@@ -415,7 +415,7 @@ function plotly_data(series::Series, letter::Symbol, data)
plotly_data(data)
end
end
plotly_data(v) = v != nothing ? collect(v) : v
plotly_data(v) = v !== nothing ? collect(v) : v
plotly_data(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
@@ -529,7 +529,7 @@ function plotly_series(plt::Plot, series::Series)
else
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] != nothing
if series[:fill_z] !== nothing
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
plotattributes_out[:showscale] = hascolorbar(sp)
@@ -611,11 +611,11 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
plotattributes_outs[i] = plotattributes_out
end
if series[:fill_z] != nothing
if series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:line_z] != nothing
elseif series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:marker_z] != nothing
elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
plotattributes_outs
@@ -631,11 +631,9 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series)
plotattributes_outs = Vector{KW}(undef, (hasfillrange ? 2 : 1 ) * length(segments))
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
for (i,rng) in enumerate(segments)
!isscatter && length(rng) < 2 && continue
plotattributes_out = deepcopy(plotattributes_base)
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotattributes_out[:legendgroup] = series[:label]
@@ -735,11 +733,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
end
end
if series[:line_z] != nothing
if series[:line_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:fill_z] != nothing
elseif series[:fill_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:marker_z] != nothing
elseif series[:marker_z] !== nothing
push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end
@@ -784,7 +782,7 @@ function plotly_hover!(plotattributes_out::KW, hover)
# hover text
if hover in (:none, false)
plotattributes_out[:hoverinfo] = "none"
elseif hover != nothing
elseif hover !== nothing
plotattributes_out[:hoverinfo] = "text"
plotattributes_out[:text] = hover
end
@@ -800,13 +798,16 @@ function plotly_series(plt::Plot)
end
# get json string for a list of dictionaries, each representing the series params
plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt))
plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt), 4)
# ----------------------------------------------------------------
html_head(plt::Plot{PlotlyBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
const ijulia_initialized = Ref(false)
function html_head(plt::Plot{PlotlyBackend})
function plotly_html_head(plt::Plot)
local_file = ("file://" * plotly_local_file_path)
plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path
if isijulia() && !ijulia_initialized[]
@@ -822,13 +823,11 @@ function html_head(plt::Plot{PlotlyBackend})
""")
ijulia_initialized[] = true
end
# IJulia just needs one initialization
isijulia() && return ""
return "<script src=$(repr(plotly))></script>"
end
function html_body(plt::Plot{PlotlyBackend}, style = nothing)
if style == nothing
function plotly_html_body(plt, style = nothing)
if style === nothing
w, h = plt[:size]
style = "width:$(w)px;height:$(h)px;"
end
@@ -843,17 +842,14 @@ function html_body(plt::Plot{PlotlyBackend}, style = nothing)
html
end
function js_body(plt::Plot{PlotlyBackend}, uuid)
function js_body(plt::Plot, uuid)
js = """
PLOT = document.getElementById('$(uuid)');
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
"""
end
# ----------------------------------------------------------------
function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
function plotly_show_js(io::IO, plot::Plot)
data = []
for series in plot.series_list
append!(data, plotly_series(plot, series))
@@ -862,6 +858,17 @@ function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{Plotly
JSON.print(io, Dict(:data => data, :layout => layout))
end
# ----------------------------------------------------------------
function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
plotly_show_js(io, plot)
end
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
write(io, standalone_html(plt))
end
function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt)
+29 -63
View File
@@ -1,78 +1,44 @@
# https://github.com/sglyon/PlotlyJS.jl
# --------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options)
else
PlotlyJS.plot()
function plotlyjs_syncplot(plt::Plot{PlotlyJSBackend})
plt[:overwrite_figure] && closeall()
plt.o = PlotlyJS.plot()
traces = PlotlyJS.GenericTrace[]
for series_dict in plotly_series(plt)
plotly_type = pop!(series_dict, :type)
push!(traces, PlotlyJS.GenericTrace(plotly_type; series_dict...))
end
PlotlyJS.addtraces!(plt.o, traces...)
layout = plotly_layout(plt)
w, h = plt[:size]
PlotlyJS.relayout!(plt.o, layout, width = w, height = h)
return plt.o
end
# ------------------------------------------------------------------------------
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
syncplot = plt.o
pdicts = plotly_series(plt, series)
for pdict in pdicts
typ = pop!(pdict, :type)
gt = PlotlyJS.GenericTrace(typ; pdict...)
PlotlyJS.addtraces!(syncplot, gt)
end
const _plotlyjs_mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"image/svg+xml" => "svg",
"image/eps" => "eps",
)
for (mime, fmt) in _plotlyjs_mimeformats
@eval _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plotlyjs_syncplot(plt), format = $fmt)
end
function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
xsym, ysym = (ispolar(series) ? (:t,:r) : (:x,:y))
kw = KW(xsym => (series.plotattributes[:x],), ysym => (series.plotattributes[:y],))
z = series[:z]
if z != nothing
kw[:z] = (isa(z,Surface) ? transpose_z(series, series[:z].surf, false) : z,)
end
PlotlyJS.restyle!(
plt.o,
findfirst(isequal(series), plt.series_list),
kw
)
end
# Use the Plotly implementation for json and html:
_show(io::IO, mime::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend}) = plotly_show_js(io, plt)
html_head(plt::Plot{PlotlyJSBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyJSBackend}) = plotly_html_body(plt)
# ----------------------------------------------------------------
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = write(io, standalone_html(plt))
function _update_plot_object(plt::Plot{PlotlyJSBackend})
pdict = plotly_layout(plt)
syncplot = plt.o
w,h = plt[:size]
PlotlyJS.relayout!(syncplot, pdict, width = w, height = h)
end
# ----------------------------------------------------------------
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o)
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="svg")
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="png")
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf")
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps")
function _show(io::IO, m::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend})
show(io, m, plt.o)
end
function write_temp_html(plt::Plot{PlotlyJSBackend})
filename = string(tempname(), ".html")
savefig(plt, filename)
filename
end
function _display(plt::Plot{PlotlyJSBackend})
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
display(plt.o)
else
standalone_html_window(plt)
end
end
_display(plt::Plot{PlotlyJSBackend}) = display(plotlyjs_syncplot(plt))
@require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin
function WebIO.render(plt::Plot{PlotlyJSBackend})
+24 -20
View File
@@ -216,7 +216,7 @@ end
# ---------------------------------------------------------------------------
function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
if series[:x] != nothing
if series[:x] !== nothing
x, y = series[:x], series[:y]
nx, ny = length(x), length(y)
if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
@@ -434,7 +434,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if maximum(series[:linewidth]) > 0
segments = iter_segments(series)
# TODO: check LineCollection alternative for speed
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] != nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] !== nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
# # multicolored line segments
# n = length(segments)
# # segments = Array(Any,n)
@@ -478,7 +478,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# end
a = series[:arrow]
if a != nothing && !is3d(st) # TODO: handle 3d later
if a !== nothing && !is3d(st) # TODO: handle 3d later
if typeof(a) != Arrow
@warn("Unexpected type for arrow: $(typeof(a))")
else
@@ -508,7 +508,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
if series[:markershape] != :none && st in (:path, :scatter, :path3d,
:scatter3d, :steppre, :steppost,
:bar)
markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] != nothing
markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] !== nothing
# py_color(plot_color.(get_markercolor.(series, clims, eachindex(x)), get_markeralpha.(series, eachindex(x))))
[py_color(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) for i in eachindex(x)]
else
@@ -672,7 +672,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
# contour fills
if series[:fillrange] != nothing
if series[:fillrange] !== nothing
handle = ax."contourf"(x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
@@ -691,7 +691,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
z = transpose_z(series, z)
if st == :surface
if series[:fill_z] != nothing
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[:shade] = false
@@ -830,7 +830,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# handle area filling
fillrange = series[:fillrange]
if fillrange != nothing && st != :contour
if fillrange !== nothing && st != :contour
for (i, rng) in enumerate(iter_segments(series))
f, dim1, dim2 = if isvertical(series)
:fill_between, x[rng], y[rng]
@@ -871,7 +871,7 @@ end
function py_set_ticks(ax, ticks, letter)
ticks == :auto && return
axis = getproperty(ax, Symbol(letter,"axis"))
if ticks == :none || ticks == nothing || ticks == false
if ticks == :none || ticks === nothing || ticks == false
kw = KW()
for dir in (:top,:bottom,:left,:right)
kw[dir] = kw[Symbol(:label,dir)] = false
@@ -927,7 +927,7 @@ function py_set_scale(ax, sp::Subplot, axis::Axis)
elseif scale == :log10
10
end
kw[Symbol(:linthresh,letter)] = NaNMath.min(1e-16, py_compute_axis_minval(sp, axis))
kw[Symbol(:linthresh,letter)] = NaNMath.max(1e-16, py_compute_axis_minval(sp, axis))
"symlog"
end
func(arg; kw...)
@@ -978,7 +978,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update subplots
for sp in plt.subplots
ax = sp.o
if ax == nothing
if ax === nothing
continue
end
@@ -1018,12 +1018,12 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
kw[:ticks] = locator
kw[:format] = formatter
kw[:boundaries] = vcat(0, kw[:values] + 0.5)
elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z))
elseif any(colorbar_series[attr] !== nothing for attr in (:line_z, :fill_z, :marker_z))
cmin, cmax = get_clims(sp)
norm = pycolors."Normalize"(vmin = cmin, vmax = cmax)
f = if colorbar_series[:line_z] != nothing
f = if colorbar_series[:line_z] !== nothing
py_linecolormap
elseif colorbar_series[:fill_z] != nothing
elseif colorbar_series[:fill_z] !== nothing
py_fillcolormap
else
py_markercolormap
@@ -1186,7 +1186,7 @@ end
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{PyPlotBackend})
ax = sp.o
ax == nothing && return sp.minpad
ax === nothing && return sp.minpad
plotbb = py_bbox(ax)
# TODO: this should initialize to the margin from sp.attr
@@ -1228,7 +1228,7 @@ end
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val)
ax = sp.o
ax."annotate"(val, xy = (x,y), zorder = 999)
ax."annotate"(val, xy = (x,y), zorder = 999, annotation_clip = false)
end
@@ -1242,7 +1242,8 @@ function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
rotation = val.font.rotation,
size = py_thickness_scale(sp.plt, val.font.pointsize),
zorder = 999
zorder = 999,
annotation_clip = false
)
end
@@ -1297,7 +1298,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
for series in series_list(sp)
if should_add_to_legend(series)
# add a line/marker and a label
push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
push!(handles, if series[:seriestype] == :shape || series[:fillrange] !== nothing
pypatches."Patch"(
edgecolor = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
facecolor = py_color(single_color(get_fillcolor(series, clims)), get_fillalpha(series)),
@@ -1335,10 +1336,13 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
frame = leg."get_frame"()
frame."set_linewidth"(py_thickness_scale(plt, 1))
leg."set_zorder"(1000)
sp[:legendtitle] != nothing && leg."set_title"(sp[:legendtitle])
if sp[:legendtitle] !== nothing
leg."set_title"(sp[:legendtitle])
PyPlot.plt."setp"(leg."get_title"(), color = py_color(sp[:legendtitlefontcolor]), family = sp[:legendtitlefontfamily], fontsize = py_thickness_scale(plt, sp[:legendtitlefontsize]))
end
for txt in leg."get_texts"()
PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily], fontsize = py_thickness_scale(plt, sp[:legendfontsize]))
end
end
end
@@ -1352,7 +1356,7 @@ end
function _update_plot_object(plt::Plot{PyPlotBackend})
for sp in plt.subplots
ax = sp.o
ax == nothing && return
ax === nothing && return
figw, figh = sp.plt[:size]
figw, figh = figw*px, figh*px
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
+3 -3
View File
@@ -529,7 +529,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# end
# @show msw msh
if anns != nothing && anns.baseshape != nothing
if anns !== nothing && anns.baseshape !== nothing
# we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each
msw,msh = anns.scalefactor
@@ -568,7 +568,7 @@ mutable struct EachAnn
end
function Base.iterate(ea::EachAnn, i = 1)
if ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
if ea.anns === nothing || isempty(ea.anns.strs) || i > length(ea.y)
return nothing
end
@@ -794,7 +794,7 @@ end
@deprecate curve_points coords
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50))
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, Base.range(range..., length=n))
# build a BezierCurve which leaves point p vertically upwards and arrives point q vertically upwards.
# may create a loop if necessary. Assumes the view is [0,1]
+2 -2
View File
@@ -496,7 +496,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
Plots._debugMode.on = debug
plts = Dict()
for i in 1:length(_examples)
only != nothing && !(i in only) && continue
only !== nothing && !(i in only) && continue
i in skip && continue
try
plt = test_examples(pkgname, i, debug=debug, disp=disp)
@@ -505,7 +505,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
# TODO: put error info into markdown?
@warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
end
if sleep != nothing
if sleep !== nothing
Base.sleep(sleep)
end
end
+4 -1
View File
@@ -20,7 +20,10 @@ frontends like jupyterlab and nteract.
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
out["application/vnd.plotly.v1+json"] = Dict(
:data => plotly_series(plt),
:layout => plotly_layout(plt)
)
out
end
-1
View File
@@ -107,7 +107,6 @@ function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
if mix.len != 0mm
f = (letter == :x ? width : height)
totlen = f(plotarea(sp))
@show totlen
pct += mix.len / totlen
end
if pct != 0
+1 -1
View File
@@ -103,7 +103,7 @@ type is inferred from the file extension. All backends support png and pdf
file types, some also support svg, ps, eps, html and tex.
"""
function savefig(plt::Plot, fn::AbstractString)
fn = abspath(expanduser(fn))
# get the extension
local ext
try
+3 -3
View File
@@ -126,7 +126,7 @@ function _preprocess_userrecipe(kw::KW)
end
# convert a ribbon into a fillrange
if get(kw, :ribbon, nothing) != nothing
if get(kw, :ribbon, nothing) !== nothing
make_fillrange_from_ribbon(kw)
end
return
@@ -136,7 +136,7 @@ function _add_errorbar_kw(kw_list::Vector{KW}, kw::KW)
# handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror)
if get(kw, esym, nothing) != nothing
if get(kw, esym, nothing) !== nothing
# we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw)
errkw[:seriestype] = esym
@@ -227,7 +227,7 @@ function _plot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# handle inset subplots
insets = plt[:inset_subplots]
if insets != nothing
if insets !== nothing
if !(typeof(insets) <: AVec)
insets = [insets]
end
+1 -1
View File
@@ -4,7 +4,7 @@ mutable struct CurrentPlot
end
const CURRENT_PLOT = CurrentPlot(nothing)
isplotnull() = CURRENT_PLOT.nullableplot == nothing
isplotnull() = CURRENT_PLOT.nullableplot === nothing
"""
current()
+22 -16
View File
@@ -239,7 +239,7 @@ end
@recipe function f(::Type{Val{:sticks}}, x, y, z)
n = length(x)
fr = plotattributes[:fillrange]
if fr == nothing
if fr === nothing
sp = plotattributes[:subplot]
yaxis = sp[:yaxis]
fr = if yaxis[:scale] == :identity
@@ -291,13 +291,13 @@ end
# create segmented bezier curves in place of line segments
@recipe function f(::Type{Val{:curves}}, x, y, z; npoints = 30)
args = z != nothing ? (x,y,z) : (x,y)
args = z !== nothing ? (x,y,z) : (x,y)
newx, newy = zeros(0), zeros(0)
fr = plotattributes[:fillrange]
newfr = fr != nothing ? zeros(0) : nothing
newz = z != nothing ? zeros(0) : nothing
newfr = fr !== nothing ? zeros(0) : nothing
newz = z !== nothing ? zeros(0) : nothing
# lz = plotattributes[:line_z]
# newlz = lz != nothing ? zeros(0) : nothing
# newlz = lz !== nothing ? zeros(0) : nothing
# for each line segment (point series with no NaNs), convert it into a bezier curve
# where the points are the control points of the curve
@@ -306,13 +306,13 @@ end
ts = range(0, stop = 1, length = npoints)
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts))
if z != nothing
if z !== nothing
nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
end
if fr != nothing
if fr !== nothing
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
end
# if lz != nothing
# if lz !== nothing
# lzrng = _cycle(lz, rng) # the line_z's for this segment
# push!(newlz, 0.0)
# append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
@@ -321,16 +321,16 @@ end
x := newx
y := newy
if z == nothing
if z === nothing
seriestype := :path
else
seriestype := :path3d
z := newz
end
if fr != nothing
if fr !== nothing
fillrange := newfr
end
# if lz != nothing
# if lz !== nothing
# # line_z := newlz
# linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad())
# end
@@ -357,7 +357,7 @@ end
# compute half-width of bars
bw = plotattributes[:bar_width]
hw = if bw == nothing
hw = if bw === nothing
if nx > 1
0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx)))
else
@@ -369,7 +369,7 @@ end
# make fillto a vector... default fills to 0
fillto = plotattributes[:fillrange]
if fillto == nothing
if fillto === nothing
fillto = 0
end
if (yscale in _logScales) && !all(_is_positive, fillto)
@@ -491,7 +491,7 @@ end
@recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y)
if (plotattributes[:bar_width] == nothing)
if (plotattributes[:bar_width] === nothing)
bar_width := diff(edge)
end
x := _bin_centers(edge)
@@ -533,7 +533,7 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S
last_w = eltype(weights)(NaN)
while it_tuple_e != nothing && it_tuple_w != nothing
while it_tuple_e !== nothing && it_tuple_w !== nothing
b, it_state_e = it_tuple_e
w, it_state_w = it_tuple_w
@@ -667,7 +667,7 @@ end
function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
localvs = _filternans(vs)
edges = _hist_edges(localvs, binning)
h = float( weights == nothing ?
h = float( weights === nothing ?
StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left)
)
@@ -1099,6 +1099,12 @@ timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t)))
@recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter)
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter)
@recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter)
@recipe f(::Type{P}, t::P) where P <: Dates.Period = (t -> Dates.value(t), t -> string(P(t)))
# -------------------------------------------------
# Characters
@recipe f(::Type{<:AbstractChar}, ::AbstractChar) = (string, string)
# -------------------------------------------------
# Complex Numbers
+57 -64
View File
@@ -7,68 +7,64 @@
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
const MaybeNumber = Union{Number, Missing}
const MaybeString = Union{AbstractString, Missing}
const DataPoint = Union{MaybeNumber, MaybeString}
const SeriesData = Union{AVec{<:DataPoint}, Function, Surface, Volume}
all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none))
# unknown
convertToAnyVector(x, plotattributes::KW) = error("No user recipe defined for $(typeof(x))")
# missing
convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing
# numeric/string vector
convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Union{Number,AbstractString,Missing}} = Any[handlemissings(v)], nothing
function convertToAnyVector(v::AMat, plotattributes::KW)
v = handlemissings(v)
if all3D(plotattributes)
Any[Surface(v)]
else
Any[v[:,i] for i in 1:size(v,2)]
end, nothing
end
prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting")
prepareSeriesData(::Nothing) = nothing
prepareSeriesData(s::SeriesData) = handlemissings(s)
handlemissings(v) = v
handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: Number = replace(v, missing => NaN)
handlemissings(v::AbstractArray{Union{T,Missing}}) where T <: AbstractString = replace(v, missing => "")
handlemissings(v::AbstractArray{<:MaybeNumber}) = replace(v, missing => NaN)
handlemissings(v::AbstractArray{<:MaybeString}) = replace(v, missing => "")
handlemissings(s::Surface) = Surface(handlemissings(s.surf))
handlemissings(v::Volume) = Volume(handlemissings(v.v), v.x_extents, v.y_extents, v.z_extents)
# function
convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing
# default: assume x represents a single series
convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)]
# surface
convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n]
# volume
convertToAnyVector(v::Volume, plotattributes::KW) = Any[v], nothing
# # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing
# # dates
convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# vector of data points is a single series
convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)]
# list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, plotattributes::KW)
if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
function convertToAnyVector(v::AVec, plotattributes)
if all(x -> x isa MaybeNumber, v)
convertToAnyVector(Vector{MaybeNumber}(v), plotattributes)
elseif all(x -> x isa MaybeString, v)
convertToAnyVector(Vector{MaybeString}(v), plotattributes)
else
# something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing
vcat((convertToAnyVector(vi, plotattributes) for vi in v)...)
end
end
convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing
function convertToAnyVector(args...)
error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))")
# Matrix is split into columns
function convertToAnyVector(v::AMat{<:DataPoint}, plotattributes)
if all3D(plotattributes)
Any[prepareSeriesData(Surface(v))]
else
Any[prepareSeriesData(v[:, i]) for i in 1:size(v, 2)]
end
end
# --------------------------------------------------------------------
# Fillranges & ribbons
process_fillrange(range::Number, plotattributes) = [range]
process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes)
process_ribbon(ribbon::Number, plotattributes) = [ribbon]
process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes)
# ribbon as a tuple: (lower_ribbons, upper_ribbons)
process_ribbon(ribbon::Tuple{Any,Any}) = collect(zip(convertToAnyVector(ribbon[1], plotattributes),
convertToAnyVector(ribbon[2], plotattributes)))
# --------------------------------------------------------------------
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
@@ -130,24 +126,17 @@ struct SliceIt end
z = z.data
end
xs, _ = convertToAnyVector(x, plotattributes)
ys, _ = convertToAnyVector(y, plotattributes)
zs, _ = convertToAnyVector(z, plotattributes)
xs = convertToAnyVector(x, plotattributes)
ys = convertToAnyVector(y, plotattributes)
zs = convertToAnyVector(z, plotattributes)
fr = pop!(plotattributes, :fillrange, nothing)
fillranges, _ = if typeof(fr) <: Number
([fr],nothing)
else
convertToAnyVector(fr, plotattributes)
end
fillranges = process_fillrange(fr, plotattributes)
mf = length(fillranges)
rib = pop!(plotattributes, :ribbon, nothing)
ribbons, _ = if typeof(rib) <: Number
([fr],nothing)
else
convertToAnyVector(rib, plotattributes)
end
ribbons = process_ribbon(rib, plotattributes)
mr = length(ribbons)
# @show zs
@@ -288,8 +277,10 @@ end
@recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing)
all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none))
# return a surface if this is a 3d plot, otherwise let it be sliced up
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat}
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing}
if all3D(plotattributes)
n,m = size(mat)
wrap_surfaces(plotattributes)
@@ -312,7 +303,7 @@ end
end
# assume this is a Volume, so construct one
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Number
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Union{Number,Missing}
seriestype := :volume
SliceIt, nothing, Volume(vol, args...), nothing
end
@@ -380,7 +371,9 @@ end
end
end
# Dicts: each entry is a data point (x,y)=(key,value)
@recipe f(d::AbstractDict) = collect(keys(d)), collect(values(d))
# function without range... use the current range of the x-axis
@@ -581,7 +574,7 @@ end
# end
splittable_kw(key, val, lengthGroup) = false
splittable_kw(key, val::AbstractArray, lengthGroup) = (key != :group) && size(val,1) == lengthGroup
splittable_kw(key, val::AbstractArray, lengthGroup) = !(key in (:group, :color_palette)) && size(val,1) == lengthGroup
splittable_kw(key, val::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup))
splittable_kw(key, val::SeriesAnnotations, lengthGroup) = splittable_kw(key, val.strs, lengthGroup)
+1 -1
View File
@@ -22,7 +22,7 @@ function _get_defaults(s::Symbol)
:fglegend => thm.text,
:palette => thm.palette,
)
if thm.gradient != nothing
if thm.gradient !== nothing
push!(defaults, :gradient => thm.gradient)
end
return defaults
+18 -10
View File
@@ -26,7 +26,7 @@ function histogramHack(; kw...)
plotattributes[:x] = midpoints
plotattributes[:y] = float(counts)
plotattributes[:seriestype] = :bar
plotattributes[:fillrange] = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
plotattributes[:fillrange] = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
plotattributes
end
@@ -38,7 +38,7 @@ function barHack(; kw...)
plotattributes = KW(kw)
midpoints = plotattributes[:x]
heights = plotattributes[:y]
fillrange = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
fillrange = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
# estimate the edges
dists = diff(midpoints) * 0.5
@@ -81,7 +81,7 @@ function sticksHack(; kw...)
# these are the line vertices
x = Float64[]
y = Float64[]
fillrange = plotattributesLine[:fillrange] == nothing ? 0.0 : plotattributesLine[:fillrange]
fillrange = plotattributesLine[:fillrange] === nothing ? 0.0 : plotattributesLine[:fillrange]
# calculate the vertices
yScatter = plotattributesScatter[:y]
@@ -115,7 +115,6 @@ function regressionXY(x, y)
end
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
@show T, size(z)
n, m = size(z)
# idx = 0
colors = ColorGradient(vec(z))
@@ -194,7 +193,7 @@ end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
if x == nothing
if x === nothing
return UnitRange{Int}[]
elseif has_attribute_segments(series)
if series[:seriestype] in (:scatter, :scatter3d)
@@ -478,7 +477,7 @@ function make_fillrange_from_ribbon(kw::KW)
rib1, rib2 = -first(rib), last(rib)
# kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2)
(get(kw, :fillalpha, nothing) == nothing) && (kw[:fillalpha] = 0.5)
(get(kw, :fillalpha, nothing) === nothing) && (kw[:fillalpha] = 0.5)
end
#turn tuple of fillranges to one path
@@ -529,7 +528,7 @@ function get_clims(sp::Subplot)
for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real})
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
elseif (vals != nothing) && (eltype(vals) <: Union{Missing, Real})
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
end
end
@@ -602,7 +601,7 @@ for comp in (:line, :fill, :marker)
function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
c = series[$Symbol($compcolor)]
z = series[$Symbol($comp_z)]
if z == nothing
if z === nothing
isa(c, ColorGradient) ? c : plot_color(_cycle(c, i))
else
grad = isa(c, ColorGradient) ? c : cgrad()
@@ -613,7 +612,7 @@ for comp in (:line, :fill, :marker)
$get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
function $get_compcolor(series, i::Int = 1)
if series[$Symbol($comp_z)] == nothing
if series[$Symbol($comp_z)] === nothing
$get_compcolor(series, 0, 1, i)
else
$get_compcolor(series, get_clims(series[:subplot]), i)
@@ -650,7 +649,7 @@ function has_attribute_segments(series::Series)
for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and
# SegmentsIterator is used
series[letter] != nothing && NaN in collect(series[letter]) && return false
series[letter] !== nothing && NaN in collect(series[letter]) && return false
end
series[:seriestype] == :shape && return false
# ... else we check relevant attributes if they have multiple inputs
@@ -1060,6 +1059,15 @@ legendfont(sp::Subplot) = font(
sp[:legendfontcolor],
)
legendtitlefont(sp::Subplot) = font(
sp[:legendtitlefontfamily],
sp[:legendtitlefontsize],
sp[:legendtitlefontvalign],
sp[:legendtitlefonthalign],
sp[:legendtitlefontrotation],
sp[:legendtitlefontcolor],
)
tickfont(ax::Axis) = font(
ax[:tickfontfamily],
ax[:tickfontsize],
+2 -2
View File
@@ -64,7 +64,7 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
# now we have the fn (if any)... do the comparison
# @show reffn
if reffn == nothing
if reffn === nothing
reffn = newfn
end
# @show reffn
@@ -98,7 +98,7 @@ function image_comparison_facts(pkg::Symbol;
tol = 1e-2) # acceptable error (percent)
for i in 1:length(Plots._examples)
i in skip && continue
if only == nothing || i in only
if only === nothing || i in only
@test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, tol=tol) |> success == true
end
end
+7
View File
@@ -63,6 +63,13 @@ end
end
end
@testset "EmptyAnim" begin
anim = @animate for i in []
end
@test_throws ArgumentError gif(anim)
end
@testset "Segments" begin
function segments(args...)
segs = UnitRange{Int}[]