Compare commits

..

1 Commits

Author SHA1 Message Date
Josef Heinen 0d17aa0093 gr: removed println statement 2017-06-17 22:11:57 +02:00
37 changed files with 590 additions and 1119 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ os:
- linux
# - osx
julia:
- 0.6
- 0.5
matrix:
allow_failures:
- julia: nightly
+1 -35
View File
@@ -9,42 +9,8 @@
- `backports` branch is for Julia 0.4
---
## (current master)
## 0.12.3
- new grid line style defaults
- `grid` is now an axis attribute and a magic argument: it is now possible to modify the grid line style, alpha and line width
- Enforce plot order in user recipes
- import `plot!` from RecipesBase
- GR no longer automatically handles _ and ^ in texts
- fix GR colorbar for scatter plots
#### 0.12.2
- fix an issue with Juno/PlotlyJS compatibility on new installations
- fix markers not showing up in seriesrecipes using :scatter
- don't use pywrap in the pyplot backend
- improve the bottom margin for the gr backend
#### 0.12.1
- fix deprecation warnings
- switch from FixedSizeArrays to StaticArrays.FixedSizeArrays
- drop FactCheck in tests
- remove julia 0.5 compliant uses of transpose operator
- fix GR heatmap bugs
- fix GR guide padding
- improve legend markers in GR
- add surface alpha for Plotly(JS)
- add fillrange to Plotly(JS)
- allow usage of Matplotlib 1.5 with PyPlot
- fix GLVisualize for julia 0.6
- conform to changes in InspectDR
#### 0.12.0
- 0.6 only
## 0.11 (current master/dev)
#### 0.11.3
-1
View File
@@ -1,7 +1,6 @@
# Plots
[![Build Status](https://travis-ci.org/JuliaPlots/Plots.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/Plots.jl)
[![Build status](https://ci.appveyor.com/api/projects/status/github/tbreloff/plots.jl?branch=master&svg=true)](https://ci.appveyor.com/project/tbreloff/plots-jl)
[![Join the chat at https://gitter.im/tbreloff/Plots.jl](https://badges.gitter.im/tbreloff/Plots.jl.svg)](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<!-- [![Plots](http://pkg.julialang.org/badges/Plots_0.3.svg)](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
<!-- [![Plots](http://pkg.julialang.org/badges/Plots_0.4.svg)](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
+3 -5
View File
@@ -1,15 +1,13 @@
julia 0.6
julia 0.5
RecipesBase 0.2.0
RecipesBase
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
StaticArrays 0.5
FixedSizeArrays
FixedPointNumbers 0.3
Measures
Showoff
StatsBase 0.14.0
JSON
NaNMath
Requires
Contour
+2 -8
View File
@@ -1,13 +1,7 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
matrix:
allow_failures:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" #check and address
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
+30 -66
View File
@@ -1,14 +1,10 @@
__precompile__(true)
__precompile__(false)
module Plots
using Reexport
import StaticArrays
using StaticArrays.FixedSizeArrays
using FixedSizeArrays
@reexport using RecipesBase
import RecipesBase: plot, plot!, animate
using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
@@ -34,6 +30,9 @@ export
with,
twinx,
@userplot,
@shorthands,
pie,
pie!,
plot3d,
@@ -52,8 +51,6 @@ export
yflip!,
xaxis!,
yaxis!,
xgrid!,
ygrid!,
xlims,
ylims,
@@ -110,26 +107,14 @@ export
# ---------------------------------------------------------
import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563
ignorenan_minimum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.minimum(x)
ignorenan_minimum(x) = Base.minimum(x)
ignorenan_maximum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.maximum(x)
ignorenan_maximum(x) = Base.maximum(x)
ignorenan_mean{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.mean(x)
ignorenan_mean(x) = Base.mean(x)
ignorenan_extrema{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.extrema(x)
ignorenan_extrema(x) = Base.extrema(x)
# ---------------------------------------------------------
# to cater for block matrices, Base.transpose is recursive.
# This makes it impossible to create row vectors of String and Symbol with the transpose operator.
# This solves this issue, internally in Plots at least.
# commented out on the insistence of the METADATA maintainers
#Base.transpose(x::Symbol) = x
#Base.transpose(x::String) = x
ignoreNaN_minimum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.minimum(x)
ignoreNaN_minimum(x) = Base.minimum(x)
ignoreNaN_maximum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.maximum(x)
ignoreNaN_maximum(x) = Base.maximum(x)
ignoreNaN_mean{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.mean(x)
ignoreNaN_mean(x) = Base.mean(x)
ignoreNaN_extrema{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.extrema(x)
ignoreNaN_extrema(x) = Base.extrema(x)
# ---------------------------------------------------------
@@ -153,14 +138,25 @@ include("layouts.jl")
include("subplots.jl")
include("recipes.jl")
include("animation.jl")
include("output.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
include("output.jl")
# ---------------------------------------------------------
# define and export shorthand plotting method definitions
macro shorthands(funcname::Symbol)
funcname2 = Symbol(funcname, "!")
esc(quote
export $funcname, $funcname2
$funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname)))
$funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname)))
end)
end
@shorthands scatter
@shorthands bar
@shorthands barh
@@ -188,65 +184,33 @@ include("output.jl")
@shorthands quiver
@shorthands curves
"Plot a pie diagram"
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
"Plot with seriestype :path3d"
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
"Add title to an existing plot"
title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
"Add xlabel to an existing plot"
xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
"Add ylabel to an existing plot"
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
"Set xlims for an existing plot"
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; xlims = lims, kw...)
"Set ylims for an existing plot"
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; ylims = lims, kw...)
"Set zlims for an existing plot"
zlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; zlims = lims, kw...)
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...)
"Set xticks for an existing plot"
xticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; xticks = v, kw...)
"Set yticks for an existing plot"
yticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; yticks = v, kw...)
xticks!{T<:Real,S<:AbstractString}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:AbstractString}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; yticks = (ticks,labels), kw...)
"Add annotations to an existing plot"
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
annotate!{T<:Tuple}(anns::AVec{T}; kw...) = plot!(; annotation = anns, kw...)
"Flip the current plots' x axis"
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
"Flip the current plots' y axis"
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
"Specify x axis attributes for an existing plot"
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
"Specify x axis attributes for an existing plot"
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
let PlotOrSubplot = Union{Plot, Subplot}
title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
@@ -264,8 +228,6 @@ let PlotOrSubplot = Union{Plot, Subplot}
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:AbstractString}(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; yticks = (ticks,labels), kw...)
xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
annotate!{T<:Tuple}(plt::PlotOrSubplot, anns::AVec{T}; kw...) = plot!(plt; annotation = anns, kw...)
xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
@@ -279,8 +241,10 @@ end
const CURRENT_BACKEND = CurrentBackend(:none)
# for compatibility with Requires.jl:
@init begin
function __init__()
setup_ijulia()
setup_atom()
if isdefined(Main, :PLOTS_DEFAULTS)
for (k,v) in Main.PLOTS_DEFAULTS
default(k, v)
+2 -7
View File
@@ -1,4 +1,4 @@
"Represents an animation object"
immutable Animation
dir::String
frames::Vector{String}
@@ -9,11 +9,6 @@ function Animation()
Animation(tmpdir, String[])
end
"""
frame(animation[, plot])
Add a plot (the current plot if not specified) to an existing animation
"""
function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i)
@@ -86,7 +81,7 @@ function buildanimation(animdir::AbstractString, fn::AbstractString;
catch err
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`.
You may also need to install the imagemagick c++ library through your operating system.
You may also need to install the imagemagick c++ library through your operating system.
Will try ffmpeg, but it's lower quality...)""")
# low quality
+3 -6
View File
@@ -76,6 +76,7 @@ const _arg_desc = KW(
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
:foreground_color_subplot => "Color Type or `:match` (matches `:foreground_color`). Base foreground color of the subplot.",
:foreground_color_legend => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.",
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.",
:legend => "Bool (show the legend?) or Symbol (legend position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:inside`, `:legend`, `:topright`, `:topleft`, `:bottomleft`, `:bottomright` (note: only some may be supported in each backend)",
@@ -83,6 +84,7 @@ const _arg_desc = KW(
: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.",
:grid => "Bool. Show the grid lines?",
: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 `apect_ratio` x-units.",
@@ -93,7 +95,6 @@ const _arg_desc = KW(
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
:colorbar_title => "String. Title of colorbar.",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
# axis args
:guide => "String. Axis guide (label).",
@@ -110,9 +111,5 @@ const _arg_desc = KW(
:foreground_color_text => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of tick labels.",
:foreground_color_guide => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis guides (axis labels).",
:mirror => "Bool. Switch the side of the tick labels (right or top).",
:grid => "Bool, Symbol, String or `nothing`. Show the grid lines? `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:none`, `:off`",
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
:gridalpha => "Number in [0,1]. The alpha/opacity override for the grid lines.",
:gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)",
:gridlinewidth => "Number. Width of the grid lines (in pixels)",
)
+12 -115
View File
@@ -163,32 +163,6 @@ const _scaleAliases = Dict{Symbol,Symbol}(
:log => :log10,
)
const _allGridSyms = [:x, :y, :z,
:xy, :xz, :yx, :yz, :zx, :zy,
:xyz, :xzy, :yxz, :yzx, :zxy, :zyx,
:all, :both, :on,
:none, :off,]
const _allGridArgs = [_allGridSyms; string.(_allGridSyms); nothing]
hasgrid(arg::Void, letter) = false
hasgrid(arg::Bool, letter) = arg
function hasgrid(arg::Symbol, letter)
if arg in _allGridSyms
arg in (:all, :both, :on) || contains(string(arg), string(letter))
else
warn("Unknown grid argument $arg; $(Symbol(letter, :grid)) was set to `true` instead.")
true
end
end
hasgrid(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter)
const _allFramestyles = [:box, :semi, :axes, :grid, :none]
const _framestyleAliases = Dict{Symbol, Symbol}(
:frame => :box,
:border => :box,
:on => :box,
:transparent => :semi,
:semitransparent => :semi,
)
# -----------------------------------------------------------------------------
const _series_defaults = KW(
@@ -198,7 +172,7 @@ const _series_defaults = KW(
:seriestype => :path,
:linestyle => :solid,
:linewidth => :auto,
:linecolor => :auto,
:linecolor => :match,
:linealpha => nothing,
:fillrange => nothing, # ribbons, areas, etc
:fillcolor => :match,
@@ -273,6 +247,7 @@ const _subplot_defaults = KW(
:background_color_inside => :match, # background inside grid
:foreground_color_subplot => :match, # default for other fg colors... match takes plot default
:foreground_color_legend => :match, # foreground of legend
:foreground_color_grid => :match, # grid color
:foreground_color_title => :match, # title color
:color_palette => :auto,
:legend => :best,
@@ -280,6 +255,7 @@ const _subplot_defaults = KW(
:colorbar => :legend,
:clims => :auto,
:legendfont => font(8),
:grid => true,
:annotations => [], # annotation tuples... list of (x,y,annotation)
:projection => :none, # can also be :polar or :3d
:aspect_ratio => :none, # choose from :none or :equal
@@ -290,7 +266,6 @@ const _subplot_defaults = KW(
:bottom_margin => :match,
:subplot_index => -1,
:colorbar_title => "",
:framestyle => :axes,
)
const _axis_defaults = KW(
@@ -310,11 +285,6 @@ const _axis_defaults = KW(
:discrete_values => [],
:formatter => :auto,
:mirror => false,
:grid => true,
:foreground_color_grid => :match, # grid color
:gridalpha => 0.1,
:gridstyle => :solid,
:gridlinewidth => 0.5,
)
const _suppress_warnings = Set{Symbol}([
@@ -366,12 +336,6 @@ const _all_defaults = KW[
_axis_defaults_byletter
]
# to be able to reset font sizes to initial values
const _initial_fontsizes = Dict(:titlefont => _subplot_defaults[:titlefont].pointsize,
:legendfont => _subplot_defaults[:legendfont].pointsize,
:tickfont => _axis_defaults[:tickfont].pointsize,
:guidefont => _axis_defaults[:guidefont].pointsize)
const _all_args = sort(collect(union(map(keys, _all_defaults)...)))
RecipesBase.is_key_supported(k::Symbol) = is_attr_supported(k)
@@ -432,7 +396,7 @@ add_aliases(:foreground_color_title, :fg_title, :fgtitle, :fgcolor_title, :fg_co
add_aliases(:foreground_color_axis, :fg_axis, :fgaxis, :fgcolor_axis, :fg_color_axis, :foreground_axis,
:foreground_colour_axis, :fgcolour_axis, :fg_colour_axis, :axiscolor)
add_aliases(:foreground_color_border, :fg_border, :fgborder, :fgcolor_border, :fg_color_border, :foreground_border,
:foreground_colour_border, :fgcolour_border, :fg_colour_border, :bordercolor)
:foreground_colour_border, :fgcolour_border, :fg_colour_border, :bordercolor, :border)
add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text,
:foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor)
add_aliases(:foreground_color_guide, :fg_guide, :fgguide, :fgcolor_guide, :fg_color_guide, :foreground_guide,
@@ -444,7 +408,6 @@ add_aliases(:linealpha, :la, :lalpha, :lα, :lineopacity, :lopacity)
add_aliases(:markeralpha, :ma, :malpha, :mα, :markeropacity, :mopacity)
add_aliases(:markerstrokealpha, :msa, :msalpha, :msα, :markerstrokeopacity, :msopacity)
add_aliases(:fillalpha, :fa, :falpha, :fα, :fillopacity, :fopacity)
add_aliases(:gridalpha, :ga, :galpha, :gα, :gridopacity, :gopacity)
# series attributes
add_aliases(:seriestype, :st, :t, :typ, :linetype, :lt)
@@ -500,9 +463,6 @@ add_aliases(:series_annotations, :series_ann, :seriesann, :series_anns, :seriesa
add_aliases(:html_output_format, :format, :fmt, :html_format)
add_aliases(:orientation, :direction, :dir)
add_aliases(:inset_subplots, :inset, :floating)
add_aliases(:gridlinewidth, :gridwidth, :grid_linewidth, :grid_width, :gridlw, :grid_lw)
add_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls, :gridls)
add_aliases(:framestyle, :frame_style, :frame, :axesstyle, :axes_style, :boxstyle, :box_style, :box, :borderstyle, :border_style, :border)
# add all pluralized forms to the _keyAliases dict
@@ -522,6 +482,7 @@ end
`default(; kw...)` will set the current default value for each key/value pair
`default(d, key)` returns the key from d if it exists, otherwise `default(key)`
"""
function default(k::Symbol)
k = get(_keyAliases, k, k)
for defaults in _all_defaults
@@ -561,6 +522,7 @@ function default(d::KW, k::Symbol)
end
# -----------------------------------------------------------------------------
# if arg is a valid color value, then set d[csym] and return true
@@ -678,36 +640,6 @@ function processFillArg(d::KW, arg)
return
end
function processGridArg!(d::KW, arg, letter)
if arg in _allGridArgs || isa(arg, Bool)
d[Symbol(letter, :grid)] = hasgrid(arg, letter)
elseif allStyles(arg)
d[Symbol(letter, :gridstyle)] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (d[Symbol(letter, :gridlinewidth)] = arg.width)
arg.color == nothing || (d[Symbol(letter, :foreground_color_grid)] = arg.color in (:auto, :match) ? :match : plot_color(arg.color))
arg.alpha == nothing || (d[Symbol(letter, :gridalpha)] = arg.alpha)
arg.style == nothing || (d[Symbol(letter, :gridstyle)] = arg.style)
# linealpha
elseif allAlphas(arg)
d[Symbol(letter, :gridalpha)] = arg
# linewidth
elseif allReals(arg)
d[Symbol(letter, :gridlinewidth)] = arg
# color
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_grid))
warn("Skipped grid arg $arg.")
end
end
_replace_markershape(shape::Symbol) = get(_markerAliases, shape, shape)
_replace_markershape(shapes::AVec) = map(_replace_markershape, shapes)
_replace_markershape(shape) = shape
@@ -729,7 +661,6 @@ function preprocessArgs!(d::KW)
if haskey(d, :axis) && d[:axis] in (:none, nothing, false)
d[:ticks] = nothing
d[:foreground_color_border] = RGBA(0,0,0,0)
d[:foreground_color_axis] = RGBA(0,0,0,0)
d[:grid] = false
delete!(d, :axis)
end
@@ -752,22 +683,6 @@ function preprocessArgs!(d::KW)
end
end
# handle grid args common to all axes
args = pop!(d, :grid, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
processGridArg!(d, arg, letter)
end
end
# handle individual axes grid args
for letter in (:x, :y, :z)
gridsym = Symbol(letter, :grid)
args = pop!(d, gridsym, ())
for arg in wraptuple(args)
processGridArg!(d, arg, letter)
end
end
# handle line args
for arg in wraptuple(pop!(d, :line, ()))
processLineArg(d, arg)
@@ -786,9 +701,6 @@ function preprocessArgs!(d::KW)
delete!(d, :marker)
if haskey(d, :markershape)
d[:markershape] = _replace_markershape(d[:markershape])
if d[:markershape] == :none && d[:seriestype] in (:scatter, :scatterbins, :scatterhist, :scatter3d) #the default should be :auto, not :none, so that :none can be set explicitly and would be respected
d[:markershape] = :circle
end
elseif anymarker
d[:markershape_to_add] = :circle # add it after _apply_recipe
end
@@ -832,11 +744,6 @@ function preprocessArgs!(d::KW)
d[:colorbar] = convertLegendValue(d[:colorbar])
end
# framestyle
if haskey(d, :framestyle) && haskey(_framestyleAliases, d[:framestyle])
d[:framestyle] = _framestyleAliases[d[:framestyle]]
end
# warnings for moved recipes
st = get(d, :seriestype, :path)
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatPlots)
@@ -856,29 +763,21 @@ end
# this is when given a vector-type of values to group by
function extractGroupArgs(v::AVec, args...; legendEntry = string)
function extractGroupArgs(v::AVec, args...)
groupLabels = sort(collect(unique(v)))
n = length(groupLabels)
if n > 100
warn("You created n=$n groups... Is that intended?")
end
groupIds = Vector{Int}[filter(i -> v[i] == glab, 1:length(v)) for glab in groupLabels]
GroupBy(map(legendEntry, groupLabels), groupIds)
GroupBy(map(string, groupLabels), groupIds)
end
legendEntryFromTuple(ns::Tuple) = string(("$n " for n in ns)...)
# this is when given a tuple of vectors of values to group by
function extractGroupArgs(vs::Tuple, args...)
(vs == ()) && return GroupBy([""], [1:size(args[1],1)])
v = collect(zip(vs...))
extractGroupArgs(v, args...; legendEntry = legendEntryFromTuple)
end
# expecting a mapping of "group label" to "group indices"
function extractGroupArgs{T, V<:AVec{Int}}(idxmap::Dict{T,V}, args...)
groupLabels = sortedkeys(idxmap)
groupIds = Vector{Int}[collect(idxmap[k]) for k in groupLabels]
groupIds = VecI[collect(idxmap[k]) for k in groupLabels]
GroupBy(groupLabels, groupIds)
end
@@ -1036,6 +935,7 @@ const _match_map = KW(
:background_color_legend => :background_color_subplot,
:background_color_inside => :background_color_subplot,
:foreground_color_legend => :foreground_color_subplot,
:foreground_color_grid => :foreground_color_subplot,
:foreground_color_title => :foreground_color_subplot,
:left_margin => :margin,
:top_margin => :margin,
@@ -1049,7 +949,6 @@ const _match_map2 = KW(
:foreground_color_subplot => :foreground_color,
:foreground_color_axis => :foreground_color_subplot,
:foreground_color_border => :foreground_color_subplot,
:foreground_color_grid => :foreground_color_subplot,
:foreground_color_guide => :foreground_color_subplot,
:foreground_color_text => :foreground_color_subplot,
)
@@ -1184,6 +1083,7 @@ function _update_subplot_colors(sp::Subplot)
# foreground colors
color_or_nothing!(sp.attr, :foreground_color_subplot)
color_or_nothing!(sp.attr, :foreground_color_legend)
color_or_nothing!(sp.attr, :foreground_color_grid)
color_or_nothing!(sp.attr, :foreground_color_title)
return
end
@@ -1235,7 +1135,6 @@ function _update_axis_colors(axis::Axis)
color_or_nothing!(axis.d, :foreground_color_border)
color_or_nothing!(axis.d, :foreground_color_guide)
color_or_nothing!(axis.d, :foreground_color_text)
color_or_nothing!(axis.d, :foreground_color_grid)
return
end
@@ -1341,14 +1240,12 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
# update other colors
for s in (:line, :marker, :fill)
csym, asym = Symbol(s,:color), Symbol(s,:alpha)
d[csym] = if d[csym] == :auto
d[csym] = if d[csym] == :match
plot_color(if has_black_border_for_default(d[:seriestype]) && s == :line
sp[:foreground_color_subplot]
else
d[:seriescolor]
end, d[asym])
elseif d[csym] == :match
plot_color(d[:seriescolor], d[asym])
else
getSeriesRGBColor(d[csym], d[asym], sp, plotIndex)
end
+39 -63
View File
@@ -118,7 +118,7 @@ Base.show(io::IO, axis::Axis) = dumpdict(axis.d, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.d, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
ignoreNaN_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
const _scale_funcs = Dict{Symbol,Function}(
@@ -181,27 +181,15 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
end
# get a list of well-laid-out ticks
if ticks == nothing
scaled_ticks = optimize_ticks(
scaled_ticks = if ticks == nothing
optimize_ticks(
sf(amin),
sf(amax);
k_min = 4, # minimum number of ticks
k_min = 5, # minimum number of ticks
k_max = 8, # maximum number of ticks
)[1]
elseif typeof(ticks) <: Int
scaled_ticks, viewmin, viewmax = optimize_ticks(
sf(amin),
sf(amax);
k_min = ticks, # minimum number of ticks
k_max = ticks, # maximum number of ticks
k_ideal = ticks,
# `strict_span = false` rewards cases where the span of the
# chosen ticks is not too much bigger than amin - amax:
strict_span = false,
)
axis[:lims] = map(invscalefunc(scale), (viewmin, viewmax))
else
scaled_ticks = map(sf, (filter(t -> amin <= t <= amax, ticks)))
map(sf, filter(t -> amin <= t <= amax, ticks))
end
unscaled_ticks = map(invscalefunc(scale), scaled_ticks)
@@ -228,7 +216,7 @@ end
# return (continuous_values, discrete_values) for the ticks on this axis
function get_ticks(axis::Axis)
ticks = _transform_ticks(axis[:ticks])
ticks = axis[:ticks]
ticks in (nothing, false) && return nothing
dvals = axis[:discrete_values]
@@ -238,7 +226,7 @@ function get_ticks(axis::Axis)
elseif ticks == :auto
# compute optimal ticks and labels
optimal_ticks_and_labels(axis)
elseif typeof(ticks) <: Union{AVec, Int}
elseif typeof(ticks) <: AVec
# override ticks, but get the labels
optimal_ticks_and_labels(axis, ticks)
elseif typeof(ticks) <: NTuple{2, Any}
@@ -258,10 +246,6 @@ function get_ticks(axis::Axis)
end
end
_transform_ticks(ticks) = ticks
_transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.value.(ticks)
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2])
# -------------------------------------------------------------------------
@@ -365,11 +349,11 @@ function expand_extrema!(sp::Subplot, d::KW)
bw = d[:bar_width]
if bw == nothing
bw = d[:bar_width] = ignorenan_mean(diff(data))
bw = d[:bar_width] = ignoreNaN_mean(diff(data))
end
axis = sp.attr[Symbol(dsym, :axis)]
expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
expand_extrema!(axis, ignoreNaN_maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, ignoreNaN_minimum(data) - 0.5minimum(bw))
end
end
@@ -506,46 +490,38 @@ function axis_drawing_info(sp::Subplot)
ymin, ymax = axis_limits(yaxis)
xticks = get_ticks(xaxis)
yticks = get_ticks(yaxis)
xaxis_segs = Segments(2)
yaxis_segs = Segments(2)
xgrid_segs = Segments(2)
ygrid_segs = Segments(2)
xborder_segs = Segments(2)
yborder_segs = Segments(2)
spine_segs = Segments(2)
grid_segs = Segments(2)
if !(sp[:framestyle] == :none)
# xaxis
sp[:framestyle] == :grid || push!(xaxis_segs, (xmin,ymin), (xmax,ymin)) # bottom spine / xaxis
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin,ymax), (xmax,ymax)) # top spine
if !(xaxis[:ticks] in (nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
t1 = invf(f(ymin) + 0.015*(f(ymax)-f(ymin)))
t2 = invf(f(ymax) - 0.015*(f(ymax)-f(ymin)))
if !(xaxis[:ticks] in (nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
t1 = invf(f(ymin) + 0.015*(f(ymax)-f(ymin)))
t2 = invf(f(ymax) - 0.015*(f(ymax)-f(ymin)))
for xtick in xticks[1]
push!(xaxis_segs, (xtick, ymin), (xtick, t1)) # bottom tick
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:grid] && push!(xgrid_segs, (xtick, t1), (xtick, t2)) # vertical grid
end
end
# yaxis
sp[:framestyle] == :grid || push!(yaxis_segs, (xmin,ymin), (xmin,ymax)) # left spine / yaxis
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (xmax,ymin), (xmax,ymax)) # right spine
if !(yaxis[:ticks] in (nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
t1 = invf(f(xmin) + 0.015*(f(xmax)-f(xmin)))
t2 = invf(f(xmax) - 0.015*(f(xmax)-f(xmin)))
for ytick in yticks[1]
push!(yaxis_segs, (xmin, ytick), (t1, ytick)) # left tick
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (t1, ytick), (t2, ytick)) # horizontal grid
end
push!(spine_segs, (xmin,ymin), (xmax,ymin)) # bottom spine
# push!(spine_segs, (xmin,ymax), (xmax,ymax)) # top spine
for xtick in xticks[1]
push!(spine_segs, (xtick, ymin), (xtick, t1)) # bottom tick
push!(grid_segs, (xtick, t1), (xtick, t2)) # vertical grid
# push!(spine_segs, (xtick, ymax), (xtick, t2)) # top tick
end
end
xticks, yticks, xaxis_segs, yaxis_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs
if !(yaxis[:ticks] in (nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
t1 = invf(f(xmin) + 0.015*(f(xmax)-f(xmin)))
t2 = invf(f(xmax) - 0.015*(f(xmax)-f(xmin)))
push!(spine_segs, (xmin,ymin), (xmin,ymax)) # left spine
# push!(spine_segs, (xmax,ymin), (xmax,ymax)) # right spine
for ytick in yticks[1]
push!(spine_segs, (xmin, ytick), (t1, ytick)) # left tick
push!(grid_segs, (t1, ytick), (t2, ytick)) # horizontal grid
# push!(spine_segs, (xmax, ytick), (t2, ytick)) # right tick
end
end
xticks, yticks, spine_segs, grid_segs
end
-3
View File
@@ -6,10 +6,7 @@ const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
const _backends = Symbol[]
const _initialized_backends = Set{Symbol}()
"Returns a list of supported backends"
backends() = _backends
"Returns the name of the current backend"
backend_name() = CURRENT_BACKEND.sym
_backend_instance(sym::Symbol) = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
+54 -70
View File
@@ -24,8 +24,7 @@ const _glvisualize_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :colorbar,
:grid, :legend, :colorbar,
:marker_z,
:line_z,
:levels,
@@ -39,8 +38,7 @@ const _glvisualize_attr = merge_with_base_supported([
:clims,
:inset_subplots,
:dpi,
:hover,
:framestyle,
:hover
])
const _glvisualize_seriestype = [
:path, :shape,
@@ -60,7 +58,7 @@ const _glvisualize_scale = [:identity, :ln, :log2, :log10]
function _initialize_backend(::GLVisualizeBackend; kw...)
@eval begin
import GLVisualize, GeometryTypes, Reactive, GLAbstraction, GLWindow, Contour
import GeometryTypes: Point2f0, Point3f0, Vec2f0, Vec3f0, GLNormalMesh, SimpleRectangle, Point, Vec
import GeometryTypes: Point2f0, Point3f0, Vec2f0, Vec3f0, GLNormalMesh, SimpleRectangle
import FileIO, Images
export GLVisualize
import Reactive: Signal
@@ -68,8 +66,9 @@ function _initialize_backend(::GLVisualizeBackend; kw...)
import GLVisualize: visualize
import Plots.GL
import UnicodeFun
Plots.slice_arg{C<:Colorant}(img::Matrix{C}, idx::Int) = img
Plots.slice_arg(img::Images.AbstractImage, idx::Int) = img
is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true
is_marker_supported{Img<:Images.AbstractImage}(::GLVisualizeBackend, shape::Union{Vector{Img}, Img}) = true
is_marker_supported{C<:Colorant}(::GLVisualizeBackend, shape::Union{Vector{Matrix{C}}, Matrix{C}}) = true
is_marker_supported(::GLVisualizeBackend, shape::Shape) = true
const GL = Plots
@@ -174,12 +173,12 @@ function gl_marker(shape)
shape
end
function gl_marker(shape::Shape)
points = Point2f0[GeometryTypes.Vec{2, Float32}(p) for p in zip(shape.x, shape.y)]
points = Point2f0[Vec{2,Float32}(p) for p in zip(shape.x, shape.y)]
bb = GeometryTypes.AABB(points)
mini, maxi = minimum(bb), maximum(bb)
w3 = maxi-mini
origin, width = Point2f0(mini[1], mini[2]), Point2f0(w3[1], w3[2])
map!(p -> ((p - origin) ./ width) - 0.5f0, points, points) # normalize and center
map!(p -> ((p - origin) ./ width) - 0.5f0, points) # normalize and center
GeometryTypes.GLNormalMesh(points)
end
# create a marker/shape type
@@ -213,13 +212,13 @@ function extract_limits(sp, d, kw_args)
nothing
end
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, vec::T) = vec
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, s::Number) = T(s)
to_vec{T <: FixedVector}(::Type{T}, vec::T) = vec
to_vec{T <: FixedVector}(::Type{T}, s::Number) = T(s)
to_vec{T <: StaticArrays.StaticVector{2}}(::Type{T}, vec::StaticArrays.StaticVector{3}) = T(vec[1], vec[2])
to_vec{T <: StaticArrays.StaticVector{3}}(::Type{T}, vec::StaticArrays.StaticVector{2}) = T(vec[1], vec[2], 0)
to_vec{T <: FixedVector{2}}(::Type{T}, vec::FixedVector{3}) = T(vec[1], vec[2])
to_vec{T <: FixedVector{3}}(::Type{T}, vec::FixedVector{2}) = T(vec[1], vec[2], 0)
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, vecs::AbstractVector) = map(x-> to_vec(T, x), vecs)
to_vec{T <: FixedVector}(::Type{T}, vecs::AbstractVector) = map(x-> to_vec(T, x), vecs)
function extract_marker(d, kw_args)
dim = Plots.is3d(d) ? 3 : 2
@@ -275,7 +274,7 @@ function extract_surface(d)
map(_extract_surface, (d[:x], d[:y], d[:z]))
end
function topoints{P}(::Type{P}, array)
[P(x) for x in zip(array...)]
P[x for x in zip(array...)]
end
function extract_points(d)
dim = is3d(d) ? 3 : 2
@@ -305,7 +304,7 @@ function extract_any_color(d, kw_args)
kw_args[:color_norm] = Vec2f0(clims)
end
elseif clims == :auto
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y]))
kw_args[:color_norm] = Vec2f0(ignoreNaN_extrema(d[:y]))
end
end
else
@@ -316,7 +315,7 @@ function extract_any_color(d, kw_args)
kw_args[:color_norm] = Vec2f0(clims)
end
elseif clims == :auto
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y]))
kw_args[:color_norm] = Vec2f0(ignoreNaN_extrema(d[:y]))
else
error("Unsupported limits: $clims")
end
@@ -483,7 +482,7 @@ function hover(to_hover, to_display, window)
end
function extract_extrema(d, kw_args)
xmin, xmax = ignorenan_extrema(d[:x]); ymin, ymax = ignorenan_extrema(d[:y])
xmin, xmax = ignoreNaN_extrema(d[:x]); ymin, ymax = ignoreNaN_extrema(d[:y])
kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(xmin, ymin, xmax-xmin, ymax-ymin)
nothing
end
@@ -510,7 +509,7 @@ function extract_colornorm(d, kw_args)
else
d[:y]
end
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(z))
kw_args[:color_norm] = Vec2f0(ignoreNaN_extrema(z))
kw_args[:intensity] = map(Float32, collect(z))
end
end
@@ -577,10 +576,8 @@ end
function align_offset(startpos, lastpos, atlas, rscale, font, align)
xscale, yscale = GLVisualize.glyph_scale!('X', rscale)
xmove = (lastpos-startpos)[1] + xscale
if isa(align, GeometryTypes.Vec)
return -Vec2f0(xmove, yscale) .* align
elseif align == :top
xmove = (lastpos-startpos)[1]+xscale
if align == :top
return -Vec2f0(xmove/2f0, yscale)
elseif align == :right
return -Vec2f0(xmove, yscale/2f0)
@@ -589,6 +586,11 @@ function align_offset(startpos, lastpos, atlas, rscale, font, align)
end
end
function align_offset(startpos, lastpos, atlas, rscale, font, align::Vec)
xscale, yscale = GLVisualize.glyph_scale!('X', rscale)
xmove = (lastpos-startpos)[1] + xscale
return -Vec2f0(xmove, yscale) .* align
end
function alignment2num(x::Symbol)
(x in (:hcenter, :vcenter)) && return 0.5
@@ -636,7 +638,7 @@ function draw_ticks(
position = GLVisualize.calc_position(str, startpos, sz, font, atlas)
offset = GLVisualize.calc_offset(str, sz, font, atlas)
alignoff = align_offset(startpos, last(position), atlas, sz, font, align)
map!(position, position) do pos
map!(position) do pos
pos .+ alignoff
end
append!(positions, position)
@@ -658,7 +660,7 @@ function glvisualize_text(position, text, kw_args)
offset = GLVisualize.calc_offset(text.str, rscale, font, atlas)
alignoff = align_offset(startpos, last(position), atlas, rscale, font, text_align)
map!(position, position) do pos
map!(position) do pos
pos .+ alignoff
end
kw_args[:position] = position
@@ -678,29 +680,17 @@ function text_model(font, pivot)
end
end
function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, area)
xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs = Plots.axis_drawing_info(sp)
xticks, yticks, spine_segs, grid_segs = Plots.axis_drawing_info(sp)
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
xgc = Colors.color(Plots.gl_color(xaxis[:foreground_color_grid]))
ygc = Colors.color(Plots.gl_color(yaxis[:foreground_color_grid]))
c = Colors.color(Plots.gl_color(sp[:foreground_color_grid]))
axis_vis = []
if xaxis[:grid]
grid = draw_grid_lines(sp, xgrid_segs, xaxis[:gridlinewidth], xaxis[:gridstyle], model, RGBA(xgc, xaxis[:gridalpha]))
if sp[:grid]
grid = draw_grid_lines(sp, grid_segs, 1f0, :dot, model, RGBA(c, 0.3f0))
push!(axis_vis, grid)
end
if yaxis[:grid]
grid = draw_grid_lines(sp, ygrid_segs, yaxis[:gridlinewidth], yaxis[:gridstyle], model, RGBA(ygc, yaxis[:gridalpha]))
push!(axis_vis, grid)
end
xac = Colors.color(Plots.gl_color(xaxis[:foreground_color_axis]))
yac = Colors.color(Plots.gl_color(yaxis[:foreground_color_axis]))
if alpha(xaxis[:foreground_color_axis]) > 0
spine = draw_grid_lines(sp, xspine_segs, 1f0, :solid, model, RGBA(xac, 1.0f0))
push!(axis_vis, spine)
end
if alpha(yaxis[:foreground_color_axis]) > 0
spine = draw_grid_lines(sp, yspine_segs, 1f0, :solid, model, RGBA(yac, 1.0f0))
if alpha(xaxis[:foreground_color_border]) > 0
spine = draw_grid_lines(sp, spine_segs, 1f0, :solid, model, RGBA(c, 1.0f0))
push!(axis_vis, spine)
end
fcolor = Plots.gl_color(xaxis[:foreground_color_axis])
@@ -708,7 +698,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
xlim = Plots.axis_limits(xaxis)
ylim = Plots.axis_limits(yaxis)
if !(xaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none)
if !(xaxis[:ticks] in (nothing, false, :none))
ticklabels = map(model) do m
mirror = xaxis[:mirror]
t, positions, offsets = draw_ticks(xaxis, xticks, true, ylim, m)
@@ -728,15 +718,6 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
end
xbc = Colors.color(Plots.gl_color(xaxis[:foreground_color_border]))
ybc = Colors.color(Plots.gl_color(yaxis[:foreground_color_border]))
intensity = sp[:framestyle] == :semi ? 0.5f0 : 1.0f0
if sp[:framestyle] in (:box, :semi)
xborder = draw_grid_lines(sp, xborder_segs, intensity, :solid, model, RGBA(xbc, intensity))
yborder = draw_grid_lines(sp, yborder_segs, intensity, :solid, model, RGBA(ybc, intensity))
push!(axis_vis, xborder, yborder)
end
area_w = GeometryTypes.widths(area)
if sp[:title] != ""
tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title])
@@ -800,9 +781,9 @@ function gl_bar(d, kw_args)
# compute half-width of bars
bw = nothing
hw = if bw == nothing
ignorenan_mean(diff(x))
ignoreNaN_mean(diff(x))
else
Float64[_cycle(bw,i)*0.5 for i=1:length(x)]
Float64[cycle(bw,i)*0.5 for i=1:length(x)]
end
# make fillto a vector... default fills to 0
@@ -811,12 +792,12 @@ function gl_bar(d, kw_args)
fillto = 0
end
# create the bar shapes by adding x/y segments
positions, scales = Array{Point2f0}(ny), Array{Vec2f0}(ny)
positions, scales = Array(Point2f0, ny), Array(Vec2f0, ny)
m = Reactive.value(kw_args[:model])
sx, sy = m[1,1], m[2,2]
for i=1:ny
center = x[i]
hwi = abs(_cycle(hw,i)); yi = y[i]; fi = _cycle(fillto,i)
hwi = abs(cycle(hw,i)); yi = y[i]; fi = cycle(fillto,i)
if Plots.isvertical(d)
sz = (hwi*sx, yi*sy)
else
@@ -852,7 +833,7 @@ function gl_boxplot(d, kw_args)
sx, sy = m[1,1], m[2,2]
for (i,glabel) in enumerate(glabels)
# filter y
values = y[filter(i -> _cycle(x,i) == glabel, 1:length(y))]
values = y[filter(i -> cycle(x,i) == glabel, 1:length(y))]
# compute quantiles
q1,q2,q3,q4,q5 = quantile(values, linspace(0,1,5))
# notch
@@ -865,7 +846,7 @@ function gl_boxplot(d, kw_args)
# make the shape
center = Plots.discrete_value!(d[:subplot][:xaxis], glabel)[1]
hw = d[:bar_width] == nothing ? Plots._box_halfwidth*2 : _cycle(d[:bar_width], i)
hw = d[:bar_width] == nothing ? Plots._box_halfwidth*2 : cycle(d[:bar_width], i)
l, m, r = center - hw/2, center, center + hw/2
# internal nodes for notches
@@ -883,7 +864,7 @@ function gl_boxplot(d, kw_args)
end
# change q1 and q5 to show outliers
# using maximum and minimum values inside the limits
q1, q5 = ignorenan_extrema(inside)
q1, q5 = ignoreNaN_extrema(inside)
end
# Box
if notch
@@ -962,9 +943,9 @@ function scale_for_annotations!(series::Series, scaletype::Symbol = :pixels)
# we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each
msw, msh = anns.scalefactor
offsets = Array{Vec2f0}(length(anns.strs))
offsets = Array(Vec2f0, length(anns.strs))
series[:markersize] = map(1:length(anns.strs)) do i
str = _cycle(anns.strs, i)
str = cycle(anns.strs, i)
# get the width and height of the string (in mm)
sw, sh = text_size(str, anns.font.pointsize)
@@ -1077,7 +1058,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
kw = copy(kw_args)
fr = d[:fillrange]
ps = if all(x-> x >= 0, diff(d[:x])) # if is monotonic
vcat(points, Point2f0[(points[i][1], _cycle(fr, i)) for i=length(points):-1:1])
vcat(points, Point2f0[(points[i][1], cycle(fr, i)) for i=length(points):-1:1])
else
points
end
@@ -1141,7 +1122,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
anns = series[:series_annotations]
for (x, y, str, font) in EachAnn(anns, d[:x], d[:y])
txt_args = Dict{Symbol, Any}(:model => eye(GLAbstraction.Mat4f0))
x, y = Reactive.value(model_m) * GeometryTypes.Vec{4, Float32}(x, y, 0, 1)
x, y = Reactive.value(model_m) * Vec{4, Float32}(x, y, 0, 1)
extract_font(font, txt_args)
t = glvisualize_text(Point2f0(x, y), PlotText(str, font), txt_args)
GLVisualize._view(t, sp_screen, camera = :perspective)
@@ -1167,7 +1148,10 @@ function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend})
GLWindow.render_frame(GLWindow.rootscreen(plt.o))
GLWindow.swapbuffers(plt.o)
buff = GLWindow.screenbuffer(plt.o)
png = map(RGB{U8}, buff)
png = Images.Image(map(RGB{U8}, buff),
colorspace = "sRGB",
spatialorder = ["y", "x"]
)
FileIO.save(FileIO.Stream(FileIO.DataFormat{:PNG}, io), png)
end
@@ -1247,7 +1231,7 @@ function gl_scatter(points, kw_args)
if haskey(kw_args, :stroke_width)
s = Reactive.value(kw_args[:scale])
sw = kw_args[:stroke_width]
if sw*5 > _cycle(Reactive.value(s), 1)[1] # restrict marker stroke to 1/10th of scale (and handle arrays of scales)
if sw*5 > cycle(Reactive.value(s), 1)[1] # restrict marker stroke to 1/10th of scale (and handle arrays of scales)
kw_args[:stroke_width] = s[1] / 5f0
end
end
@@ -1325,8 +1309,8 @@ function gl_contour(x, y, z, kw_args)
if kw_args[:fillrange] != nothing
delete!(kw_args, :intensity)
I = GLVisualize.Intensity{Float32}
main = [I(z[j,i]) for i=1:size(z, 2), j=1:size(z, 1)]
I = GLVisualize.Intensity{1, Float32}
main = I[z[j,i] for i=1:size(z, 2), j=1:size(z, 1)]
return visualize(main, Style(:default), kw_args)
else
@@ -1334,7 +1318,7 @@ function gl_contour(x, y, z, kw_args)
T = eltype(z)
levels = Contour.contours(map(T, x), map(T, y), z, h)
result = Point2f0[]
zmin, zmax = get(kw_args, :limits, Vec2f0(ignorenan_extrema(z)))
zmin, zmax = get(kw_args, :limits, Vec2f0(ignoreNaN_extrema(z)))
cmap = get(kw_args, :color_map, get(kw_args, :color, RGBA{Float32}(0,0,0,1)))
colors = RGBA{Float32}[]
for c in levels.contours
@@ -1355,10 +1339,10 @@ end
function gl_heatmap(x,y,z, kw_args)
get!(kw_args, :color_norm, Vec2f0(ignorenan_extrema(z)))
get!(kw_args, :color_norm, Vec2f0(ignoreNaN_extrema(z)))
get!(kw_args, :color_map, Plots.make_gradient(cgrad()))
delete!(kw_args, :intensity)
I = GLVisualize.Intensity{Float32}
I = GLVisualize.Intensity{1, Float32}
heatmap = I[z[j,i] for i=1:size(z, 2), j=1:size(z, 1)]
tex = GLAbstraction.Texture(heatmap, minfilter=:nearest)
kw_args[:stroke_width] = 0f0
+62 -175
View File
@@ -20,8 +20,7 @@ const _gr_attr = merge_with_base_supported([
:title, :window_title,
:guide, :lims, :ticks, :scale, :flip,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar,
:grid, :legend, :legendtitle, :colorbar,
:marker_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -32,7 +31,6 @@ const _gr_attr = merge_with_base_supported([
:inset_subplots,
:bar_width,
:arrow,
:framestyle,
])
const _gr_seriestype = [
:path, :scatter,
@@ -126,10 +124,10 @@ function gr_getcolorind(c)
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
end
gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(_cycle(c,1)))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(_cycle(c,1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1)))
gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(cycle(c,1)))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(cycle(c,1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(cycle(c,1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(cycle(c,1)))
# --------------------------------------------------------------------------------------
@@ -181,7 +179,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.inqtextext(x, y, s[2:end-1])
elseif search(s, '\\') != 0
elseif search(s, '\\') != 0 || search(s, '_') != 0 || search(s, '^') != 0
GR.inqtextext(x, y, s)
else
GR.inqtext(x, y, s)
@@ -193,7 +191,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 search(s, '\\') != 0
elseif search(s, '\\') != 0 || search(s, '_') != 0 || search(s, '^') != 0
GR.textext(x, y, s)
else
GR.text(x, y, s)
@@ -266,7 +264,7 @@ end
normalize_zvals(zv::Void) = zv
function normalize_zvals(zv::AVec)
vmin, vmax = ignorenan_extrema(zv)
vmin, vmax = ignoreNaN_extrema(zv)
if vmin == vmax
zeros(length(zv))
else
@@ -274,10 +272,6 @@ function normalize_zvals(zv::AVec)
end
end
gr_alpha(α::Void) = 1
gr_alpha(α::Real) = α
# ---------------------------------------------------------
# draw ONE Shape
@@ -307,30 +301,27 @@ function gr_draw_markers(series::Series, x, y, msize, mz)
shapes = series[:markershape]
if shapes != :none
for i=1:length(x)
msi = _cycle(msize, i)
shape = _cycle(shapes, i)
msi = cycle(msize, i)
shape = cycle(shapes, i)
cfunc = isa(shape, Shape) ? gr_set_fillcolor : gr_set_markercolor
cfuncind = isa(shape, Shape) ? GR.setfillcolorind : GR.setmarkercolorind
# draw a filled in shape, slightly bigger, to estimate a stroke
if series[:markerstrokewidth] > 0
cfunc(_cycle(series[:markerstrokecolor], i)) #, series[:markerstrokealpha])
cfunc(cycle(series[:markerstrokecolor], i)) #, series[:markerstrokealpha])
gr_draw_marker(x[i], y[i], msi + series[:markerstrokewidth], shape)
end
# draw the shape
if mz == nothing
cfunc(_cycle(series[:markercolor], i)) #, series[:markeralpha])
cfunc(cycle(series[:markercolor], i)) #, series[:markeralpha])
else
# pick a color from the pre-loaded gradient
ci = round(Int, 1000 + _cycle(mz, i) * 255)
ci = round(Int, 1000 + cycle(mz, i) * 255)
cfuncind(ci)
GR.settransparency(_gr_gradient_alpha[ci-999])
end
# don't draw filled area if marker shape is 1D
if !(shape in (:hline, :vline, :+, :x))
gr_draw_marker(x[i], y[i], msi, shape)
end
gr_draw_marker(x[i], y[i], msi, shape)
end
end
end
@@ -341,7 +332,6 @@ function gr_draw_markers(series::Series, x, y)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
gr_draw_markers(series, x, y, series[:markersize], mz)
if mz != nothing
GR.setscale(0)
gr_colorbar(series[:subplot])
end
end
@@ -363,7 +353,7 @@ function gr_set_fill(c) #, a)
end
# this stores the conversion from a font pointsize to "percentage of window height" (which is what GR uses)
const _gr_point_mult = 0.0018 * ones(1)
const _gr_point_mult = zeros(1)
# set the font attributes... assumes _gr_point_mult has been populated already
function gr_set_font(f::Font; halign = f.halign, valign = f.valign,
@@ -394,7 +384,7 @@ end
const viewport_plotarea = zeros(4)
# the size of the current plot in pixels
const gr_plot_size = [600.0, 400.0]
const gr_plot_size = zeros(2)
function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, viewport_canvas)
viewport = zeros(4)
@@ -543,95 +533,17 @@ function gr_display(plt::Plot)
end
function gr_set_xticks_font(sp)
flip = sp[:yaxis][:flip]
mirror = sp[:xaxis][:mirror]
gr_set_font(sp[:xaxis][:tickfont],
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
valign = (mirror ? :bottom : :top),
color = sp[:xaxis][:foreground_color_axis],
rotation = sp[:xaxis][:rotation])
return flip, mirror
end
function gr_set_yticks_font(sp)
flip = sp[:xaxis][:flip]
mirror = sp[:yaxis][:mirror]
gr_set_font(sp[:yaxis][:tickfont],
halign = (mirror ? :left : :right),
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
color = sp[:yaxis][:foreground_color_axis],
rotation = sp[:yaxis][:rotation])
return flip, mirror
end
function gr_get_ticks_size(ticks, i)
GR.savestate()
GR.selntran(0)
l = 0.0
for (cv, dv) in zip(ticks...)
tb = gr_inqtext(0, 0, string(dv))[i]
tb_min, tb_max = extrema(tb)
l = max(l, tb_max - tb_min)
end
GR.restorestate()
return l
end
function _update_min_padding!(sp::Subplot{GRBackend})
if !haskey(ENV, "GKSwstype") && isijulia()
ENV["GKSwstype"] = "svg"
end
# Add margin given by the user
leftpad = 2mm + sp[:left_margin]
toppad = 2mm + sp[:top_margin]
rightpad = 4mm + sp[:right_margin]
bottompad = 2mm + sp[:bottom_margin]
# Add margin for title
if sp[:title] != ""
toppad += 5mm
end
# Add margin for x and y ticks
xticks, yticks = axis_drawing_info(sp)[1:2]
if !(xticks in (nothing, false))
flip, mirror = gr_set_xticks_font(sp)
l = gr_get_ticks_size(xticks, 2)
if mirror
toppad += 1mm + gr_plot_size[2] * l * px
else
bottompad += 1mm + gr_plot_size[2] * l * px
end
end
if !(yticks in (nothing, false))
flip, mirror = gr_set_yticks_font(sp)
l = gr_get_ticks_size(yticks, 1)
if mirror
rightpad += 1mm + gr_plot_size[1] * l * px
else
leftpad += 1mm + gr_plot_size[1] * l * px
end
end
# Add margin for x label
if sp[:xaxis][:guide] != ""
bottompad += 4mm
end
# Add margin for y label
if sp[:yaxis][:guide] != ""
leftpad += 4mm
end
sp.minpad = (leftpad, toppad, rightpad, bottompad)
sp.minpad = (10mm,2mm,2mm,8mm)
end
function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
_update_min_padding!(sp)
# the viewports for this subplot
viewport_subplot = gr_viewport_from_bbox(sp, bbox(sp), w, h, viewport_canvas)
viewport_plotarea[:] = gr_viewport_from_bbox(sp, plotarea(sp), w, h, viewport_canvas)
# get data limits
data_lims = gr_xy_axislims(sp)
xy_lims = data_lims
ratio = sp[:aspect_ratio]
if ratio != :none
@@ -661,7 +573,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# TODO: can these be generic flags?
outside_ticks = false
cmap = false
draw_axes = sp[:framestyle] != :none
draw_axes = true
# axes_2d = true
for series in series_list(sp)
st = series[:seriestype]
@@ -673,8 +585,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if st == :heatmap
outside_ticks = true
x, y = heatmap_edges(series[:x], sp[:xaxis][:scale]), heatmap_edges(series[:y], sp[:yaxis][:scale])
xy_lims = x[1], x[end], y[1], y[end]
x, y = heatmap_edges(series[:x]), heatmap_edges(series[:y])
expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y)
data_lims = gr_xy_axislims(sp)
@@ -746,15 +657,16 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
ticksize = 0.01 * (viewport_plotarea[2] - viewport_plotarea[1])
# GR.setlinetype(GR.LINETYPE_DOTTED)
xaxis[:grid] && GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0)
yaxis[:grid] && GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0)
zaxis[:grid] && GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2)
if sp[:grid]
GR.grid3d(xtick, 0, ztick, xmin, ymax, zmin, 2, 0, 2)
GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0)
end
GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize)
GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize)
elseif ispolar(sp)
r = gr_set_viewport_polar()
rmin, rmax = GR.adjustrange(ignorenan_minimum(r), ignorenan_maximum(r))
rmin, rmax = GR.adjustrange(ignoreNaN_minimum(r), ignoreNaN_maximum(r))
# rmin, rmax = axis_limits(sp[:yaxis])
gr_polaraxes(rmin, rmax)
@@ -763,66 +675,58 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setwindow(xmin, xmax, ymin, ymax)
end
xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs = axis_drawing_info(sp)
xticks, yticks, spine_segs, grid_segs = axis_drawing_info(sp)
# @show xticks yticks #spine_segs grid_segs
# draw the grid lines
if xaxis[:grid]
if sp[:grid]
# gr_set_linecolor(sp[:foreground_color_grid])
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
GR.settransparency(xaxis[:gridalpha])
gr_polyline(coords(xgrid_segs)...)
end
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
GR.settransparency(yaxis[:gridalpha])
gr_polyline(coords(ygrid_segs)...)
gr_set_line(1, :dot, sp[:foreground_color_grid])
GR.settransparency(0.5)
gr_polyline(coords(grid_segs)...)
end
GR.settransparency(1.0)
# axis lines
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
# spine (border) and tick marks
gr_set_line(1, :solid, sp[:xaxis][:foreground_color_axis])
GR.setclip(0)
gr_polyline(coords(xspine_segs)...)
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
GR.setclip(0)
gr_polyline(coords(yspine_segs)...)
gr_polyline(coords(spine_segs)...)
GR.setclip(1)
# tick marks
if !(xticks in (:none, nothing, false))
if !(xticks in (nothing, false))
# x labels
flip, mirror = gr_set_xticks_font(sp)
flip = sp[:yaxis][:flip]
mirror = sp[:xaxis][:mirror]
gr_set_font(sp[:xaxis][:tickfont],
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
valign = (mirror ? :bottom : :top),
color = sp[:xaxis][:foreground_color_axis],
rotation = sp[:xaxis][:rotation])
for (cv, dv) in zip(xticks...)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc(cv, xor(flip, mirror) ? ymax : ymin)
xi, yi = GR.wctondc(cv, (flip $ mirror) ? ymax : ymin)
# @show cv dv ymin xi yi flip mirror (flip $ mirror)
gr_text(xi, yi + (mirror ? 1 : -1) * 5e-3, string(dv))
end
end
if !(yticks in (:none, nothing, false))
if !(yticks in (nothing, false))
# y labels
flip, mirror = gr_set_yticks_font(sp)
flip = sp[:xaxis][:flip]
mirror = sp[:yaxis][:mirror]
gr_set_font(sp[:yaxis][:tickfont],
halign = (mirror ? :left : :right),
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
color = sp[:yaxis][:foreground_color_axis],
rotation = sp[:yaxis][:rotation])
for (cv, dv) in zip(yticks...)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc(xor(flip, mirror) ? xmax : xmin, cv)
xi, yi = GR.wctondc((flip $ mirror) ? xmax : xmin, cv)
# @show cv dv xmin xi yi
gr_text(xi + (mirror ? 1 : -1) * 1e-2, yi, string(dv))
end
end
# border
intensity = sp[:framestyle] == :semi ? 0.5 : 1.0
if sp[:framestyle] in (:box, :semi)
gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
GR.settransparency(intensity)
gr_polyline(coords(xborder_segs)...)
gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
GR.settransparency(intensity)
gr_polyline(coords(yborder_segs)...)
end
end
# end
@@ -904,9 +808,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i,rng) in enumerate(iter_segments(series[:x], series[:y]))
if length(rng) > 1
gr_set_fillcolor(_cycle(series[:fillcolor], i))
fx = _cycle(x, vcat(rng, reverse(rng)))
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
gr_set_fillcolor(cycle(series[:fillcolor], i))
fx = cycle(x, vcat(rng, reverse(rng)))
fy = vcat(cycle(fr_from,rng), cycle(fr_to,reverse(rng)))
# @show i rng fx fy
GR.fillarea(fx, fy)
end
@@ -922,10 +826,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if series[:markershape] != :none
if series[:marker_z] != nothing
zmin, zmax = extrema(series[:marker_z])
GR.setspace(zmin, zmax, 0, 90)
end
gr_draw_markers(series, x, y)
end
@@ -951,7 +851,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# create the colorbar of contour levels
if sp[:colorbar] != :none
gr_set_viewport_cmap(sp)
l = round.(Int32, 1000 + (h - ignorenan_minimum(h)) / (ignorenan_maximum(h) - ignorenan_minimum(h)) * 255)
l = round(Int32, 1000 + (h - ignoreNaN_minimum(h)) / (ignoreNaN_maximum(h) - ignoreNaN_minimum(h)) * 255)
GR.setwindow(xmin, xmax, zmin, zmax)
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
ztick = 0.5 * GR.tick(zmin, zmax)
@@ -973,7 +873,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
cmap && gr_colorbar(sp)
elseif st == :heatmap
xmin, xmax, ymin, ymax = xy_lims
zmin, zmax = gr_lims(zaxis, true)
clims = sp[:clims]
if is_2tuple(clims)
@@ -987,8 +886,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
round(Int, blue(c) * 255) << 16 +
round(Int, green(c) * 255) << 8 +
round(Int, red(c) * 255) ), colors)
w, h = length(x), length(y)
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
GR.drawimage(xmin, xmax, ymax, ymin, length(x), length(y), rgba)
cmap && gr_colorbar(sp)
elseif st in (:path3d, :scatter3d)
@@ -1064,11 +962,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
x, y = series[:x][rng], series[:y][rng]
# draw the interior
gr_set_fill(_cycle(series[:fillcolor], i))
gr_set_fill(cycle(series[:fillcolor], i))
GR.fillarea(x, y)
# draw the shapes
gr_set_line(series[:linewidth], :solid, _cycle(series[:linecolor], i))
gr_set_line(series[:linewidth], :solid, cycle(series[:linecolor], i))
GR.polyline(x, y)
end
end
@@ -1140,7 +1038,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if sp[:legendtitle] != nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(sp[:foreground_color_legend])
GR.settransparency(1)
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy
end
@@ -1148,26 +1045,16 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
should_add_to_legend(series) || continue
st = series[:seriestype]
gr_set_line(series[:linewidth], series[:linestyle], series[:linecolor]) #, series[:linealpha])
if (st == :shape || series[:fillrange] != nothing) && series[:ribbon] == nothing
if st == :path && series[:fillrange] == nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
elseif st == :shape || series[:fillrange] != nothing
gr_set_fill(series[:fillcolor]) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01
b, t = ypos-0.4dy, ypos+0.4dy
x = [l, r, r, l, l]
y = [b, b, t, t, b]
GR.settransparency(gr_alpha(series[:fillalpha]))
gr_polyline(x, y, GR.fillarea)
GR.settransparency(gr_alpha(series[:linealpha]))
st == :shape && gr_polyline(x, y)
end
if st == :path
GR.settransparency(gr_alpha(series[:linealpha]))
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])
end
gr_polyline(x, y)
end
if series[:markershape] != :none
+29 -32
View File
@@ -18,8 +18,7 @@ Add in functionality to Plots.jl:
const _inspectdr_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
# :foreground_color_grid,
:foreground_color_legend, :foreground_color_title,
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
:label,
:linecolor, :linestyle, :linewidth, :linealpha,
@@ -266,8 +265,8 @@ For st in :shape:
nmax = i
if length(rng) > 1
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(_cycle(series[:fillcolor], i))
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
line = InspectDR.line(
style=:solid, width=linewidth, color=linecolor
)
@@ -281,8 +280,8 @@ For st in :shape:
i = (nmax >= 2? div(nmax, 2): nmax) #Must pick one set of colors for legend
if i > 1 #Add dummy waveform for legend entry:
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(_cycle(series[:fillcolor], i))
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
wfrm = InspectDR.add(plot, Float64[], Float64[], id=series[:label])
wfrm.line = InspectDR.line(
style=:none, width=linewidth, #linewidth affects glyph
@@ -335,18 +334,15 @@ end
# ---------------------------------------------------------------------------
function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
const gridon = InspectDR.GridRect(vmajor=true, hmajor=true)
const gridoff = InspectDR.GridRect()
const plot = sp.o
const strip = plot.strips[1] #Only 1 strip supported with Plots.jl
#No independent control of grid???
strip.grid = sp[:grid]? gridon: gridoff
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
xgrid_show = xaxis[:grid]
ygrid_show = yaxis[:grid]
strip.grid = InspectDR.GridRect(
vmajor=xgrid_show, # vminor=xgrid_show,
hmajor=ygrid_show, # hminor=ygrid_show,
)
plot.xscale = _inspectdr_getscale(xaxis[:scale], false)
strip.yscale = _inspectdr_getscale(yaxis[:scale], true)
xmin, xmax = axis_limits(xaxis)
@@ -366,29 +362,30 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]]
l = plot.layout
l[:frame_canvas].fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
l[:frame_data].fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l[:frame_data].line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l[:font_title] = InspectDR.Font(sp[:titlefont].family,
l.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l.fnttitle = InspectDR.Font(sp[:titlefont].family,
_inspectdr_mapptsize(sp[:titlefont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_title])
)
#Cannot independently control fonts of axes with InspectDR:
l[:font_axislabel] = InspectDR.Font(xaxis[:guidefont].family,
l.fntaxlabel = InspectDR.Font(xaxis[:guidefont].family,
_inspectdr_mapptsize(xaxis[:guidefont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_guide])
)
l[:font_ticklabel] = InspectDR.Font(xaxis[:tickfont].family,
l.fntticklabel = InspectDR.Font(xaxis[:tickfont].family,
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
)
l[:enable_legend] = (sp[:legend] != :none)
#l[:halloc_legend] = 150 #TODO: compute???
l[:font_legend] = InspectDR.Font(sp[:legendfont].family,
leg = l.legend
leg.enabled = (sp[:legend] != :none)
#leg.width = 150 #TODO: compute???
leg.font = InspectDR.Font(sp[:legendfont].family,
_inspectdr_mapptsize(sp[:legendfont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_legend])
)
l[:frame_legend].fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
leg.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
end
# called just before updating layout bounding boxes... in case you need to prep
@@ -402,7 +399,7 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
#Don't use window_title... probably not what you want.
#mplot.title = plt[:window_title]
end
mplot.layout[:frame].fillcolor = _inspectdr_mapcolor(plt[:background_color_outside])
mplot.frame.fillcolor = _inspectdr_mapcolor(plt[:background_color_outside])
resize!(mplot.subplots, length(plt.subplots))
nsubplots = length(plt.subplots)
@@ -424,15 +421,15 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
#Do not yet support absolute plot positionning.
#Just try to make things look more-or less ok:
if nsubplots <= 1
mplot.layout[:ncolumns] = 1
mplot.ncolumns = 1
elseif nsubplots <= 4
mplot.layout[:ncolumns] = 2
mplot.ncolumns = 2
elseif nsubplots <= 6
mplot.layout[:ncolumns] = 3
mplot.ncolumns = 3
elseif nsubplots <= 12
mplot.layout[:ncolumns] = 4
mplot.ncolumns = 4
else
mplot.layout[:ncolumns] = 5
mplot.ncolumns = 5
end
for series in plt.series_list
@@ -449,7 +446,7 @@ function _update_min_padding!(sp::Subplot{InspectDRBackend})
plot = sp.o
if !isa(plot, InspectDR.Plot2D); return sp.minpad; end
#Computing plotbounds with 0-BoundingBox returns required padding:
bb = InspectDR.plotbounds(plot.layout.values, InspectDR.BoundingBox(0,0,0,0))
bb = InspectDR.plotbounds(plot.layout, InspectDR.BoundingBox(0,0,0,0))
#NOTE: plotbounds always pads for titles, legends, etc. even if not in use.
#TODO: possibly zero-out items not in use??
@@ -471,7 +468,7 @@ function _update_plot_object(plt::Plot{InspectDRBackend})
for (i, sp) in enumerate(plt.subplots)
graphbb = _inspectdr_to_pixels(plotarea(sp))
plot = mplot.subplots[i]
plot.plotbb = InspectDR.plotbounds(plot.layout.values, graphbb)
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
end
gplot = _inspectdr_getgui(plt.o)
+4 -8
View File
@@ -98,7 +98,7 @@ const _pgf_series_extrastyle = KW(
:xsticks => "xcomb",
)
# PGFPlots uses the anchors to define orientations for example to align left
# PGFPlots uses the anchors to define orientations for example to align left
# one needs to use the right edge as anchor
const _pgf_annotation_halign = KW(
:center => "",
@@ -121,7 +121,7 @@ function pgf_color(grad::ColorGradient)
end
# Generates a colormap for pgfplots based on a ColorGradient
function pgf_colormap(grad::ColorGradient)
function pgf_colormap(grad::ColorGradient)
join(map(grad.colors) do c
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c))
end,", ")
@@ -266,11 +266,6 @@ function pgf_axis(sp::Subplot, letter)
push!(style, "$(letter)majorticks=false")
end
# grid on or off
if axis[:grid]
push!(style, "$(letter)majorgrids = true")
end
# limits
# TODO: support zlims
if letter != :z
@@ -329,6 +324,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
kw[:title] = "$(sp[:title])"
end
sp[:grid] && push!(style, "grid = major")
if sp[:aspect_ratio] in (1, :equal)
kw[:axisEqual] = "true"
end
@@ -364,7 +360,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
kw[:colorbar] = "true"
end
# goto is needed to break out of col and series for
@goto colorbar_end
@goto colorbar_end
end
end
end
+12 -47
View File
@@ -5,7 +5,7 @@ const _plotly_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_legend, :foreground_color_guide,
:foreground_color_grid, :foreground_color_axis,
# :foreground_color_grid, :foreground_color_axis,
:foreground_color_text, :foreground_color_border,
:foreground_color_title,
:label,
@@ -19,8 +19,7 @@ const _plotly_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridlinewidth,
:legend, :colorbar, :colorbar_title,
:grid, :legend, :colorbar, :colorbar_title,
:marker_z, :fill_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -214,9 +213,7 @@ function plotly_axis(axis::Axis, sp::Subplot)
letter = axis[:letter]
ax = KW(
:title => axis[:guide],
:showgrid => axis[:grid],
:gridcolor => rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])),
:gridwidth => axis[:gridlinewidth],
:showgrid => sp[:grid],
:zeroline => false,
:ticks => "inside",
)
@@ -232,8 +229,8 @@ function plotly_axis(axis::Axis, sp::Subplot)
ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide])
ax[:type] = plotly_scale(axis[:scale])
ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text])
ax[:tickcolor] = rgba_string(axis[:foreground_color_axis])
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
ax[:tickcolor] = rgba_string(axis[:foreground_color_border])
ax[:linecolor] = rgba_string(axis[:foreground_color_border])
# lims
lims = axis[:lims]
@@ -438,8 +435,6 @@ function plotly_series(plt::Plot, series::Series)
isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none
hasline = st in (:path, :path3d)
hasfillrange = st in (:path, :scatter, :scattergl) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
# for surface types, set the data
if st in (:heatmap, :contour, :surface, :wireframe)
@@ -463,14 +458,11 @@ function plotly_series(plt::Plot, series::Series)
else
hasline ? "lines" : "none"
end
if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple)
if series[:fillrange] == true || series[:fillrange] == 0
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = rgba_string(series[:fillcolor])
elseif isa(series[:fillrange], AbstractVector)
d_out[:fill] = "tonexty"
d_out[:fillcolor] = rgba_string(series[:fillcolor])
elseif !(series[:fillrange] in (false, nothing))
warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])")
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(series[:fillrange])")
end
d_out[:x], d_out[:y] = x, y
@@ -487,7 +479,6 @@ function plotly_series(plt::Plot, series::Series)
d_out[:type] = "heatmap"
# d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:showscale] = sp[:legend] != :none
elseif st == :contour
d_out[:type] = "contour"
@@ -496,7 +487,6 @@ function plotly_series(plt::Plot, series::Series)
d_out[:ncontours] = series[:levels]
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
d_out[:showscale] = sp[:legend] != :none
elseif st in (:surface, :wireframe)
d_out[:type] = "surface"
@@ -509,14 +499,11 @@ function plotly_series(plt::Plot, series::Series)
:highlightwidth => series[:linewidth],
)
d_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
d_out[:showscale] = false
else
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:opacity] = series[:fillalpha]
if series[:fill_z] != nothing
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
d_out[:showscale] = sp[:legend] != :none
end
elseif st == :pie
@@ -559,7 +546,7 @@ function plotly_series(plt::Plot, series::Series)
else
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
grad = as_gradient(series[:markercolor], series[:markeralpha])
zmin, zmax = ignorenan_extrema(series[:marker_z])
zmin, zmax = ignoreNaN_extrema(series[:marker_z])
zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
[rgba_string(grad[(zi - zmin) / zrange]) for zi in series[:marker_z]]
end
@@ -585,29 +572,7 @@ function plotly_series(plt::Plot, series::Series)
plotly_polar!(d_out, series)
plotly_hover!(d_out, series[:hover])
if hasfillrange
# if hasfillrange is true, return two dictionaries (one for original
# series, one for series being filled to) instead of one
d_out_fillrange = deepcopy(d_out)
d_out_fillrange[:showlegend] = false
if isa(series[:fillrange], AbstractVector)
d_out_fillrange[:y] = series[:fillrange]
delete!(d_out_fillrange, :fill)
delete!(d_out_fillrange, :fillcolor)
else
# if fillrange is a tuple with upper and lower limit, d_out_fillrange
# is the series that will do the filling
d_out_fillrange[:x], d_out_fillrange[:y] =
concatenate_fillrange(series[:x], series[:fillrange])
d_out_fillrange[:line][:width] = 0
delete!(d_out, :fill)
delete!(d_out, :fillcolor)
end
return [d_out_fillrange, d_out]
else
return [d_out]
end
[d_out]
end
function plotly_series_shapes(plt::Plot, series::Series)
@@ -635,18 +600,18 @@ function plotly_series_shapes(plt::Plot, series::Series)
:x => vcat(x[rng], x[rng[1]]),
:y => vcat(y[rng], y[rng[1]]),
:fill => "tozeroy",
:fillcolor => rgba_string(_cycle(series[:fillcolor], i)),
:fillcolor => rgba_string(cycle(series[:fillcolor], i)),
))
if series[:markerstrokewidth] > 0
d_out[:line] = KW(
:color => rgba_string(_cycle(series[:linecolor], i)),
:color => rgba_string(cycle(series[:linecolor], i)),
:width => series[:linewidth],
:dash => string(series[:linestyle]),
)
end
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotly_polar!(d_out, series)
plotly_hover!(d_out, _cycle(series[:hover], i))
plotly_hover!(d_out, cycle(series[:hover], i))
push!(d_outs, d_out)
end
d_outs
+52 -86
View File
@@ -17,8 +17,7 @@ const _pyplot_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :gridalpha, :gridstyle, :gridlinewidth,
:legend, :legendtitle, :colorbar,
:grid, :legend, :legendtitle, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
@@ -32,7 +31,6 @@ const _pyplot_attr = merge_with_base_supported([
:inset_subplots,
:dpi,
:colorbar_title,
:framestyle,
])
const _pyplot_seriestype = [
:path, :steppre, :steppost, :shape,
@@ -72,26 +70,18 @@ function _initialize_backend(::PyPlotBackend)
append!(Base.Multimedia.displays, otherdisplays)
export PyPlot
const pycolors = PyPlot.pyimport("matplotlib.colors")
const pypath = PyPlot.pyimport("matplotlib.path")
const mplot3d = PyPlot.pyimport("mpl_toolkits.mplot3d")
const pypatches = PyPlot.pyimport("matplotlib.patches")
const pyfont = PyPlot.pyimport("matplotlib.font_manager")
const pyticker = PyPlot.pyimport("matplotlib.ticker")
const pycmap = PyPlot.pyimport("matplotlib.cm")
const pynp = PyPlot.pyimport("numpy")
pynp["seterr"](invalid="ignore")
const pytransforms = PyPlot.pyimport("matplotlib.transforms")
const pycollections = PyPlot.pyimport("matplotlib.collections")
const pyart3d = PyPlot.pyimport("mpl_toolkits.mplot3d.art3d")
# "support" matplotlib v1.5
const 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")
:set_axis_bgcolor
else
:set_facecolor
end
const pycolors = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colors"))
const pypath = PyPlot.pywrap(PyPlot.pyimport("matplotlib.path"))
const mplot3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d"))
const pypatches = PyPlot.pywrap(PyPlot.pyimport("matplotlib.patches"))
const pyfont = PyPlot.pywrap(PyPlot.pyimport("matplotlib.font_manager"))
const pyticker = PyPlot.pywrap(PyPlot.pyimport("matplotlib.ticker"))
const pycmap = PyPlot.pywrap(PyPlot.pyimport("matplotlib.cm"))
const pynp = PyPlot.pywrap(PyPlot.pyimport("numpy"))
pynp.seterr(invalid="ignore")
const pytransforms = PyPlot.pywrap(PyPlot.pyimport("matplotlib.transforms"))
const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections"))
const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d"))
# we don't want every command to update the figure
PyPlot.ioff()
@@ -111,7 +101,7 @@ end
# function py_colormap(c::ColorGradient, α=nothing)
# pyvals = [(v, py_color(getColorZ(c, v), α)) for v in c.values]
# pycolors["LinearSegmentedColormap"][:from_list]("tmp", pyvals)
# pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", pyvals)
# end
# # convert vectors and ColorVectors to standard ColorGradients
@@ -128,7 +118,7 @@ py_color(grad::ColorGradient) = py_color(grad.colors)
function py_colormap(grad::ColorGradient)
pyvals = [(z, py_color(grad[z])) for z in grad.values]
cm = pycolors["LinearSegmentedColormap"][:from_list]("tmp", pyvals)
cm = pycolors.LinearSegmentedColormap[:from_list]("tmp", pyvals)
cm[:set_bad](color=(0,0,0,0.0), alpha=0.0)
cm
end
@@ -137,7 +127,7 @@ py_colormap(c) = py_colormap(cgrad())
function py_shading(c, z)
cmap = py_colormap(c)
ls = pycolors["LightSource"](270,45)
ls = pycolors.pymember("LightSource")(270,45)
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
end
@@ -161,7 +151,7 @@ function py_marker(marker::Shape)
mat[i,2] = y[i]
end
mat[n+1,:] = mat[1,:]
pypath["Path"](mat)
pypath.pymember("Path")(mat)
end
const _path_MOVETO = UInt8(1)
@@ -187,7 +177,7 @@ const _path_CLOSEPOLY = UInt8(79)
# lastnan = nan
# end
# codes[n+1] = _path_CLOSEPOLY
# pypath["Path"](mat, codes)
# pypath.pymember("Path")(mat, codes)
# end
# get the marker shape
@@ -237,14 +227,14 @@ end
# # untested... return a FontProperties object from a Plots.Font
# function py_font(font::Font)
# pyfont["FontProperties"](
# pyfont.pymember("FontProperties")(
# family = font.family,
# size = font.size
# )
# end
function get_locator_and_formatter(vals::AVec)
pyticker["FixedLocator"](1:length(vals)), pyticker["FixedFormatter"](vals)
pyticker.pymember("FixedLocator")(1:length(vals)), pyticker.pymember("FixedFormatter")(vals)
end
function add_pyfixedformatter(cbar, vals::AVec)
@@ -266,9 +256,9 @@ function labelfunc(scale::Symbol, backend::PyPlotBackend)
end
function py_mask_nans(z)
# pynp["ma"][:masked_invalid](z)))
PyCall.pycall(pynp["ma"][:masked_invalid], Any, z)
# pynp["ma"][:masked_where](pynp["isnan"](z),z)
# PyPlot.pywrap(pynp.ma[:masked_invalid](PyPlot.pywrap(z)))
PyCall.pycall(pynp.ma[:masked_invalid], Any, z)
# pynp.ma[:masked_where](pynp.isnan(z),z)
end
# ---------------------------------------------------------------------------
@@ -499,30 +489,30 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw = KW()
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
kw[:norm] = pycolors["Normalize"](; extrakw...)
kw[:norm] = pycolors.Normalize(; extrakw...)
end
lz = collect(series[:line_z])
handle = if is3d(st)
for rng in iter_segments(x, y, z)
length(rng) < 2 && continue
push!(segments, [(_cycle(x,i),_cycle(y,i),_cycle(z,i)) for i in rng])
push!(segments, [(cycle(x,i),cycle(y,i),cycle(z,i)) for i in rng])
end
# for i=1:n
# segments[i] = [(_cycle(x,i), _cycle(y,i), _cycle(z,i)), (_cycle(x,i+1), _cycle(y,i+1), _cycle(z,i+1))]
# segments[i] = [(cycle(x,i), cycle(y,i), cycle(z,i)), (cycle(x,i+1), cycle(y,i+1), cycle(z,i+1))]
# end
lc = pyart3d["Line3DCollection"](segments; kw...)
lc = pyart3d.Line3DCollection(segments; kw...)
lc[:set_array](lz)
ax[:add_collection3d](lc, zs=z) #, zdir='y')
lc
else
for rng in iter_segments(x, y)
length(rng) < 2 && continue
push!(segments, [(_cycle(x,i),_cycle(y,i)) for i in rng])
push!(segments, [(cycle(x,i),cycle(y,i)) for i in rng])
end
# for i=1:n
# segments[i] = [(_cycle(x,i), _cycle(y,i)), (_cycle(x,i+1), _cycle(y,i+1))]
# segments[i] = [(cycle(x,i), cycle(y,i)), (cycle(x,i+1), cycle(y,i+1))]
# end
lc = pycollections["LineCollection"](segments; kw...)
lc = pycollections.LineCollection(segments; kw...)
lc[:set_array](lz)
ax[:add_collection](lc)
lc
@@ -591,16 +581,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
lw = py_dpi_scale(plt, series[:markerstrokewidth])
for i=1:length(y)
extrakw[:c] = if series[:marker_z] == nothing
py_color_fix(py_color(_cycle(series[:markercolor],i)), x)
py_color_fix(py_color(cycle(series[:markercolor],i)), x)
else
extrakw[:c]
end
push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i);
push!(handle, ax[:scatter](cycle(x,i), cycle(y,i);
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(_cycle(shapes,i)),
s = py_dpi_scale(plt, _cycle(series[:markersize],i) .^ 2),
marker = py_marker(cycle(shapes,i)),
s = py_dpi_scale(plt, cycle(series[:markersize],i) .^ 2),
edgecolors = msc,
linewidths = lw,
extrakw...
@@ -715,11 +705,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# contours on the axis planes
if series[:contours]
for (zdir,mat) in (("x",x), ("y",y), ("z",z))
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat)
offset = (zdir == "y" ? ignoreNaN_maximum : ignoreNaN_minimum)(mat)
handle = ax[:contourf](x, y, z, levelargs...;
zdir = zdir,
cmap = py_fillcolormap(series),
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane
offset = (zdir == "y" ? ignoreNaN_maximum : ignoreNaN_minimum)(mat) # where to draw the contour plane
)
push!(handles, handle)
needs_colorbar = true
@@ -778,7 +768,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, z = heatmap_edges(x), heatmap_edges(y), transpose_z(series, z.surf)
expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y)
@@ -788,7 +778,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
clims = sp[:clims]
zmin, zmax = ignorenan_extrema(z)
zmin, zmax = ignoreNaN_extrema(z)
extrakw[:vmin] = (is_2tuple(clims) && isfinite(clims[1])) ? clims[1] : zmin
extrakw[:vmax] = (is_2tuple(clims) && isfinite(clims[2])) ? clims[2] : zmax
@@ -807,13 +797,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
handle = []
for (i,rng) in enumerate(iter_segments(x, y))
if length(rng) > 1
path = pypath["Path"](hcat(x[rng], y[rng]))
patches = pypatches["PathPatch"](
path = pypath.pymember("Path")(hcat(x[rng], y[rng]))
patches = pypatches.pymember("PathPatch")(
path;
label = series[:label],
zorder = series[:series_plotindex],
edgecolor = py_color(_cycle(series[:linecolor], i)),
facecolor = py_color(_cycle(series[:fillcolor], i)),
edgecolor = py_color(cycle(series[:linecolor], i)),
facecolor = py_color(cycle(series[:fillcolor], i)),
linewidth = py_dpi_scale(plt, series[:linewidth]),
fill = true
)
@@ -936,7 +926,7 @@ function py_compute_axis_minval(axis::Axis)
for series in series_list(sp)
v = series.d[axis[:letter]]
if !isempty(v)
minval = NaNMath.min(minval, ignorenan_minimum(abs.(v)))
minval = NaNMath.min(minval, ignoreNaN_minimum(abs(v)))
end
end
end
@@ -995,7 +985,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
fig[:clear]()
dpi = plt[:dpi]
fig[:set_size_inches](w/dpi, h/dpi, forward = true)
fig[set_facecolor_sym](py_color(plt[:background_color_outside]))
fig[:set_facecolor](py_color(plt[:background_color_outside]))
fig[:set_dpi](dpi)
# resize the window
@@ -1054,8 +1044,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
end
py_set_scale(ax, axis)
py_set_lims(ax, axis)
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
py_set_ticks(ax, ticks, letter)
py_set_ticks(ax, get_ticks(axis), letter)
ax[Symbol("set_", letter, "label")](axis[:guide])
if get(axis.d, :flip, false)
ax[Symbol("invert_", letter, "axis")]()
@@ -1067,13 +1056,9 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
lab[:set_family](axis[:tickfont].family)
lab[:set_rotation](axis[:rotation])
end
if axis[:grid] && !(ticks in (:none, nothing, false))
fgcolor = py_color(axis[:foreground_color_grid])
pyaxis[:grid](true,
color = fgcolor,
linestyle = py_linestyle(:line, axis[:gridstyle]),
linewidth = axis[:gridlinewidth],
alpha = axis[:gridalpha])
if sp[:grid]
fgcolor = py_color(sp[:foreground_color_grid])
pyaxis[:grid](true, color = fgcolor, linestyle = ":")
ax[:set_axisbelow](true)
end
py_set_axis_colors(ax, axis)
@@ -1089,25 +1074,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
py_add_legend(plt, sp, ax)
# this sets the bg color inside the grid
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
# framestyle
if !ispolar(sp) && !is3d(sp)
if sp[:framestyle] == :semi
intensity = 0.5
ax[:spines]["right"][:set_alpha](intensity)
ax[:spines]["top"][:set_alpha](intensity)
ax[:spines]["right"][:set_linewidth](intensity)
ax[:spines]["top"][:set_linewidth](intensity)
elseif sp[:framestyle] == :axes
ax[:spines]["right"][:set_visible](false)
ax[:spines]["top"][:set_visible](false)
elseif sp[:framestyle] in (:grid, :none)
for (loc, spine) in ax[:spines]
spine[:set_visible](false)
end
end
end
ax[:set_facecolor](py_color(sp[:background_color_inside]))
end
py_drawfig(fig)
end
@@ -1199,7 +1166,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# add a line/marker and a label
push!(handles, if series[:seriestype] == :shape
PyPlot.plt[:Line2D]((0,1),(0,0),
color = py_color(_cycle(series[:fillcolor],1)),
color = py_color(cycle(series[:fillcolor],1)),
linewidth = py_dpi_scale(plt, 4)
)
else
@@ -1229,7 +1196,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# set some legend properties
frame = leg[:get_frame]()
frame[set_facecolor_sym](py_color(sp[:background_color_legend]))
frame[:set_facecolor](py_color(sp[:background_color_legend]))
frame[:set_edgecolor](fgcolor)
end
end
@@ -1253,8 +1220,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
if haskey(sp.attr, :cbar_ax)
cbw = sp.attr[:cbar_width]
# this is the bounding box of just the colors of the colorbar (not labels)
has_toplabel = sp[:zaxis][:extrema].emax >= 1e7
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm))
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox)+2mm, _cbar_width-1mm, height(sp.bbox)-4mm)
pcts = bbox_to_pcts(cb_bbox, figw, figh)
sp.attr[:cbar_ax][:set_position](pcts)
end
+9 -57
View File
@@ -22,13 +22,6 @@ immutable Shape
# end
# end
end
"""
Shape(x, y)
Shape(vertices)
Construct a polygon to be plotted
"""
Shape(verts::AVec) = Shape(unzip(verts)...)
Shape(s::Shape) = deepcopy(s)
@@ -39,7 +32,6 @@ vertices(shape::Shape) = collect(zip(shape.x, shape.y))
#deprecated
@deprecate shape_coords coords
"return the vertex points from a Shape or Segments object"
function coords(shape::Shape)
shape.x, shape.y
end
@@ -89,7 +81,7 @@ end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π
Shape(partialcircle(z, z + 2π, n+1., radius))
Shape(partialcircle(z, z + 2π, n+1, radius))
end
@@ -164,7 +156,6 @@ Shape(k::Symbol) = deepcopy(_shapes[k])
# uses the centroid calculation from https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
"return the centroid of a Shape"
function center(shape::Shape)
x, y = coords(shape)
n = length(x)
@@ -198,7 +189,6 @@ function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
scale!(shapecopy, x, y, c)
end
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape)
for i=1:length(sx)
@@ -237,7 +227,6 @@ function rotate!(shape::Shape, Θ::Real, c = center(shape))
shape
end
"rotate an object in space"
function rotate(shape::Shape, Θ::Real, c = center(shape))
shapecopy = deepcopy(shape)
rotate!(shapecopy, Θ, c)
@@ -308,33 +297,12 @@ function scalefontsize(k::Symbol, factor::Number)
f.pointsize = round(Int, factor * f.pointsize)
default(k, f)
end
"""
scalefontsizes(factor::Number)
Scales all **current** font sizes by `factor`. For example `scalefontsizes(1.1)` increases all current font sizes by 10%. To reset to initial sizes, use `scalefontsizes()`
"""
function scalefontsizes(factor::Number)
for k in (:titlefont, :guidefont, :tickfont, :legendfont)
scalefontsize(k, factor)
end
end
"""
scalefontsizes()
Resets font sizes to initial default values.
"""
function scalefontsizes()
for k in (:titlefont, :guidefont, :tickfont, :legendfont)
f = default(k)
if k in keys(_initial_fontsizes)
factor = f.pointsize / _initial_fontsizes[k]
scalefontsize(k, 1.0/factor)
end
end
end
"Wrap a string with font info"
immutable PlotText
str::AbstractString
@@ -342,11 +310,6 @@ immutable PlotText
end
PlotText(str) = PlotText(string(str), font())
"""
text(string, args...)
Create a PlotText object wrapping a string with font info, for plot annotations
"""
text(t::PlotText) = t
text(str::AbstractString, f::Font) = PlotText(str, f)
function text(str, args...)
@@ -366,11 +329,6 @@ immutable Stroke
style
end
"""
stroke(args...; alpha = nothing)
Define the properties of the stroke used in plotting lines
"""
function stroke(args...; alpha = nothing)
width = 1
color = :black
@@ -488,7 +446,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
msw,msh = anns.scalefactor
msize = Float64[]
shapes = Shape[begin
str = _cycle(anns.strs,i)
str = cycle(anns.strs,i)
# get the width and height of the string (in mm)
sw, sh = text_size(str, anns.font.pointsize)
@@ -504,7 +462,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# and then re-scale a copy of baseshape to match the w/h ratio
maxscale = max(xscale, yscale)
push!(msize, maxscale)
baseshape = _cycle(get(anns.baseshape),i)
baseshape = cycle(get(anns.baseshape),i)
shape = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
end for i=1:length(anns.strs)]
series[:markershape] = shapes
@@ -521,13 +479,13 @@ end
Base.start(ea::EachAnn) = 1
Base.done(ea::EachAnn, i) = ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
function Base.next(ea::EachAnn, i)
tmp = _cycle(ea.anns.strs,i)
tmp = cycle(ea.anns.strs,i)
str,fnt = if isa(tmp, PlotText)
tmp.str, tmp.font
else
tmp, ea.anns.font
end
((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1)
((cycle(ea.x,i), cycle(ea.y,i), str, fnt), i+1)
end
annotations(::Void) = []
@@ -543,13 +501,13 @@ immutable ZValues
zrange::Tuple{Float64,Float64}
end
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values)))
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (ignoreNaN_minimum(values), ignoreNaN_maximum(values)))
ZValues(collect(float(values)), map(Float64, zrange))
end
# -----------------------------------------------------------------------
abstract type AbstractSurface end
abstract AbstractSurface
"represents a contour or surface mesh"
immutable Surface{M<:AMat} <: AbstractSurface
@@ -618,12 +576,6 @@ immutable Arrow
headwidth::Float64
end
"""
arrow(args...)
Define arrowheads to apply to lines - args are `style` (`:open` or `:closed`),
`side` (`:head`, `:tail` or `:both`), `headlength` and `headwidth`
"""
function arrow(args...)
style = :simple
side = :head
@@ -679,7 +631,7 @@ immutable Formatted{T}
end
# -----------------------------------------------------------------------
"create a BezierCurve for plotting"
type BezierCurve{T <: FixedSizeArrays.Vec}
control_points::Vector{T}
end
@@ -707,7 +659,7 @@ function directed_curve(args...; kw...)
end
function extrema_plus_buffer(v, buffmult = 0.2)
vmin,vmax = ignorenan_extrema(v)
vmin,vmax = ignoreNaN_extrema(v)
vdiff = vmax-vmin
buffer = vdiff * buffmult
vmin - buffer, vmax + buffer
+1 -1
View File
@@ -84,7 +84,7 @@ function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray,
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in cycle(geom.vertices, i)]
end
Gadfly.polygon(polys, geom.tag)
end
+1 -1
View File
@@ -1,5 +1,5 @@
abstract type ColorScheme end
abstract ColorScheme
Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i)
+11 -39
View File
@@ -41,7 +41,7 @@ PlotExample("Colors",
[:(begin
y = rand(100)
plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=0, α=0.6)
scatter!(y, zcolor=abs.(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs.(y-0.5)+4, lab="grad")
scatter!(y, zcolor=abs(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs(y-0.5)+4, lab="grad")
end)]
),
@@ -66,8 +66,8 @@ PlotExample("Global",
PlotExample("Images",
"Plot an image. y-axis is set to flipped",
[:(begin
import FileIO
img = FileIO.load(Pkg.dir("PlotReferenceImages","Plots","pyplot","0.7.0","ref1.png"))
import Images
img = Images.load(Pkg.dir("PlotReferenceImages","Plots","pyplot","0.7.0","ref1.png"))
plot(img)
end)]
),
@@ -119,18 +119,17 @@ PlotExample("Line styles",
styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors
n = length(styles)
y = cumsum(randn(20,n),1)
plot(y, line = (5, styles), label = map(string,styles), legendtitle = "linestyle")
plot(y, line = (5, styles), label = map(string,styles))
end)]
),
PlotExample("Marker types",
"",
[:(begin
markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys)
markers = reshape(markers, 1, length(markers))
markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys)'
n = length(markers)
x = linspace(0,10,n+2)[2:end-1]
y = repmat(reshape(reverse(x),1,:), n, 1)
y = repmat(reverse(x)', n, 1)
scatter(x, y, m=(8,:auto), lab=map(string,markers), bg=:linen, xlim=(0,10), ylim=(0,10))
end)]
),
@@ -155,7 +154,7 @@ PlotExample("Subplots",
""",
[:(begin
l = @layout([a{0.1h}; b [c;d e]])
plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, ticks=nothing, border=:none)
plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, ticks=nothing, border=false)
end)]
),
@@ -216,7 +215,7 @@ PlotExample("Contours",
x = 1:0.5:20
y = 1:0.5:10
f(x,y) = (3x+y^2)*abs(sin(x)+cos(y))
X = repmat(reshape(x,1,:), length(y), 1)
X = repmat(x', length(y), 1)
Y = repmat(y, 1, length(x))
Z = map(f, X, Y)
p1 = contour(x, y, f, fill=true)
@@ -270,7 +269,7 @@ PlotExample("Polar Plots",
"",
[:(begin
Θ = linspace(0,1.5π,100)
r = abs.(0.1randn(100)+sin.(3Θ))
r = abs(0.1randn(100)+sin(3Θ))
plot(Θ, r, proj=:polar, m=2)
end)]
),
@@ -280,7 +279,7 @@ PlotExample("Heatmap, categorical axes, and aspect_ratio",
[:(begin
xs = [string("x",i) for i=1:10]
ys = [string("y",i) for i=1:4]
z = float((1:4)*reshape(1:10,1,:))
z = float((1:4)*(1:10)')
heatmap(xs, ys, z, aspect_ratio=1)
end)]
),
@@ -321,7 +320,7 @@ PlotExample("Animation with subplots",
),
PlotExample("Spy",
"For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has various different nonzero values, a colorbar is added. The colorbar can be disabled with `legend = nothing`. As always, the marker shape and size can be changed with `spy(mat, markersize = 3, markershape = :star)`.",
"For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has various different nonzero values, a colorbar is added. The colorbar can be disabled with `legend = nothing`. As always, the marker shape and size can be changed with `spy(mat, markersize = 3, markershape = :star)`",
[:(begin
a = spdiagm((ones(50), ones(49), ones(49), ones(40), ones(40)),(0, 1, -1, 10, -10))
b = spdiagm((1:50, 1:49, 1:49, 1:40, 1:40),(0, 1, -1, 10, -10))
@@ -329,26 +328,6 @@ PlotExample("Spy",
end)]
),
PlotExample("Magic grid argument",
"The grid lines can be modified individually for each axis with the magic `grid` argument.",
[:(begin
x = rand(10)
p1 = plot(x, title = "Default looks")
p2 = plot(x, grid = (:y, :olivedrab, :dot, 1, 0.9), title = "Modified y grid")
p3 = plot(deepcopy(p2), title = "Add x grid")
xgrid!(p3, :on, :cadetblue, 2, :dashdot, 0.4)
plot(p1, p2, p3, layout = (1, 3), label = "", fillrange = 0, fillalpha = 0.3)
end)]
),
PlotExample("Framestyle",
"The style of the frame/axes of a (sub)plot can be changed with the `framestyle` attribute. The default framestyle is `:axes`.",
[:(begin
histogram(fill(randn(1000), 5), framestyle = [:box :semi :axes :grid :none],
title = [":box" ":semi" ":axes" ":grid" ":none"], color = RowVector(1:5), layout = 5, label = "")
end)]
),
]
# ---------------------------------------------------------------------------------
@@ -368,13 +347,6 @@ function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
end
# generate all plots and create a dict mapping idx --> plt
"""
test_examples(pkgname[, idx]; debug = false, disp = true, sleep = nothing,
skip = [], only = nothing
Run the `idx` test example for a given backend, or all examples if `idx`
is not specified.
"""
function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = nothing,
skip = [], only = nothing)
Plots._debugMode.on = debug
+3 -15
View File
@@ -9,8 +9,8 @@ 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, n::Number) = m * n
Base.:.*(n::Number, m::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
@@ -133,12 +133,7 @@ make_measure_hor(m::Measure) = m
make_measure_vert(n::Number) = n * h
make_measure_vert(m::Measure) = m
"""
bbox(x, y, w, h [,originargs...])
bbox(layout)
Create a bounding box for plotting
"""
function bbox(x, y, w, h, oarg1::Symbol, originargs::Symbol...)
oargs = vcat(oarg1, originargs...)
orighor = :left
@@ -258,13 +253,6 @@ type GridLayout <: AbstractLayout
attr::KW
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
columns of different width.
"""
grid(args...; kw...) = GridLayout(args...; kw...)
function GridLayout(dims...;
@@ -716,7 +704,7 @@ function link_axes!(axes::Axis...)
a1 = axes[1]
for i=2:length(axes)
a2 = axes[i]
expand_extrema!(a1, ignorenan_extrema(a2))
expand_extrema!(a1, ignoreNaN_extrema(a2))
for k in (:extrema, :discrete_values, :continuous_values, :discrete_map)
a2[k] = a1[k]
end
+44 -52
View File
@@ -97,13 +97,6 @@ function addExtension(fn::AbstractString, ext::AbstractString)
end
end
"""
savefig([plot,] filename)
Save a Plot (the current plot if `plot` is not passed) to file. The file
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)
# get the extension
@@ -126,11 +119,7 @@ savefig(fn::AbstractString) = savefig(current(), fn)
# ---------------------------------------------------------
"""
gui([plot])
Display a plot using the backends' gui window
"""
gui(plt::Plot = current()) = display(PlotsDisplay(), plt)
# IJulia only... inline display
@@ -209,7 +198,6 @@ for mime in keys(_mimeformats)
end
end
"Close all open gui windows of the current backend"
closeall() = closeall(backend())
@@ -232,10 +220,14 @@ if is_installed("FileIO")
FileIO.save(pngfn, s)
# now write from the file
write(io, readstring(open(pngfn)))
write(io, readall(open(pngfn)))
end
end
# function html_output_format(fmt)
# if fmt == "png"
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
@@ -258,76 +250,76 @@ end
const _ijulia_output = String["text/html"]
using Requires
@require IJulia begin
if IJulia.inited
export set_ijulia_output
function setup_ijulia()
# override IJulia inline display
if isijulia()
@eval begin
import IJulia
export set_ijulia_output
function set_ijulia_output(mimestr::AbstractString)
# info("Setting IJulia output format to $mimestr")
global _ijulia_output
_ijulia_output[1] = mimestr
end
function IJulia.display_dict(plt::Plot)
global _ijulia_output
Dict{String, String}(_ijulia_output[1] => sprint(show, _ijulia_output[1], plt))
end
function set_ijulia_output(mimestr::AbstractString)
# info("Setting IJulia output format to $mimestr")
global _ijulia_output
_ijulia_output[1] = mimestr
# default text/plain passes to html... handles Interact issues
function Base.show(io::IO, m::MIME"text/plain", plt::Plot)
show(io, MIME("text/html"), plt)
end
end
function IJulia.display_dict(plt::Plot)
global _ijulia_output
Dict{String, String}(_ijulia_output[1] => sprint(show, _ijulia_output[1], plt))
end
# default text/plain passes to html... handles Interact issues
function Base.show(io::IO, m::MIME"text/plain", plt::Plot)
show(io, MIME("text/html"), plt)
end
ENV["MPLBACKEND"] = "Agg"
set_ijulia_output("text/html")
@eval set_ijulia_output("text/html")
end
end
# ---------------------------------------------------------
# Atom PlotPane
# ---------------------------------------------------------
@require Juno begin
import Hiccup, Media
if Juno.isactive()
function setup_atom()
if isatom()
@eval import Atom, Media
Media.media(Plot, Media.Plot)
# default text/plain so it doesn't complain
function Base.show{B}(io::IO, ::MIME"text/plain", plt::Plot{B})
print(io, "Plot{$B}()")
end
_show{B}(io::IO, m::MIME"text/plain", plt::Plot{B}) = print(io, "Plot{$B}()")
function Juno.render(e::Juno.Editor, plt::Plot)
Juno.render(e, nothing)
function Media.render(e::Atom.Editor, plt::Plot)
Media.render(e, nothing)
end
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
function Juno.render(pane::Juno.PlotPane, plt::Plot)
# this is like "display"... sends an html div with the plot to the PlotPane
function Media.render(pane::Atom.PlotPane, plt::Plot)
# temporarily overwrite size to be Atom.plotsize
sz = plt[:size]
jsize = Juno.plotsize()
jsize[1] == 0 && (jsize[1] = 400)
jsize[2] == 0 && (jsize[2] = 500)
plt[:size] = jsize
Juno.render(pane, HTML(stringmime(MIME("text/html"), plt)))
plt[:size] = Juno.plotsize()
Media.render(pane, Atom.div(".fill", Atom.HTML(stringmime(MIME("text/html"), plt))))
plt[:size] = sz
end
# special handling for PlotlyJS
function Juno.render(pane::Juno.PlotPane, plt::Plot{PlotlyJSBackend})
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend})
display(Plots.PlotsDisplay(), plt)
end
else
function Juno.render(pane::Juno.PlotPane, plt::Plot)
#
function Media.render(pane::Atom.PlotPane, plt::Plot)
display(Plots.PlotsDisplay(), plt)
s = "PlotPane turned off. Unset ENV[\"PLOTS_USE_ATOM_PLOTPANE\"] and restart Julia to enable it."
Juno.render(pane, HTML(s))
Media.render(pane, Atom.div(Atom.HTML(s)))
end
end
# special handling for plotly... use PlotsDisplay
function Juno.render(pane::Juno.PlotPane, plt::Plot{PlotlyBackend})
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
display(Plots.PlotsDisplay(), plt)
s = "PlotPane turned off. The plotly backend cannot render in the PlotPane due to javascript issues. Plotlyjs is similar to plotly and is compatible with the plot pane."
Juno.render(pane, HTML(s))
Media.render(pane, Atom.div(Atom.HTML(s)))
end
end
end
+21 -18
View File
@@ -60,26 +60,29 @@ function _process_userrecipes(plt::Plot, d::KW, args)
args = _preprocess_args(d, args, still_to_process)
# for plotting recipes, swap out the args and update the parameter dictionary
# we are keeping a stack of series that still need to be processed.
# we are keeping a queue of series that still need to be processed.
# each pass through the loop, we pop one off and apply the recipe.
# the recipe will return a list a Series objects... the ones that are
# finished (no more args) get added to the kw_list, the ones that are not
# are placed on top of the stack and are then processed further.
# finished (no more args) get added to the kw_list, and the rest go into the queue
# for processing.
kw_list = KW[]
while !isempty(still_to_process)
# grab the first in line to be processed and either add it to the kw_list or
# pass it through apply_recipe to generate a list of RecipeData objects (data + attributes)
# for further processing.
# grab the first in line to be processed and pass it through apply_recipe
# to generate a list of RecipeData objects (data + attributes)
next_series = shift!(still_to_process)
# recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
if !(typeof(next_series) <: RecipeData)
error("Inputs couldn't be processed... expected RecipeData but got: $next_series")
end
if isempty(next_series.args)
_process_userrecipe(plt, kw_list, next_series)
else
rd_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
prepend!(still_to_process,rd_list)
rd_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
for recipedata in rd_list
# recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
if !(typeof(recipedata) <: RecipeData)
error("Inputs couldn't be processed... expected RecipeData but got: $recipedata")
end
if isempty(recipedata.args)
_process_userrecipe(plt, kw_list, recipedata)
else
# args are non-empty, so there's still processing to do... add it back to the queue
push!(still_to_process, recipedata)
end
end
end
@@ -150,7 +153,7 @@ function _add_smooth_kw(kw_list::Vector{KW}, kw::KW)
if get(kw, :smooth, false)
x, y = kw[:x], kw[:y]
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
sx = [ignorenan_minimum(x), ignorenan_maximum(x)]
sx = [ignoreNaN_minimum(x), ignoreNaN_maximum(x)]
sy = β * sx + α
push!(kw_list, merge(copy(kw), KW(
:seriestype => :path,
@@ -210,7 +213,7 @@ function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
# TODO: init subplots here
_update_plot_args(plt, d)
if !plt.init
plt.o = Base.invokelatest(_create_backend_figure, plt)
plt.o = _create_backend_figure(plt)
# create the layout and subplots from the inputs
plt.layout, plt.subplots, plt.spmap = build_layout(plt.attr)
@@ -259,7 +262,7 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
for kw in kw_list
# get the Subplot object to which the series belongs.
sps = get(kw, :subplot, :auto)
sp = get_subplot(plt, _cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
sp = get_subplot(plt, cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
kw[:subplot] = sp
# extract subplot/axis attributes from kw and add to sp_attr
+1 -5
View File
@@ -6,10 +6,6 @@ const CURRENT_PLOT = CurrentPlot(Nullable{AbstractPlot}())
isplotnull() = isnull(CURRENT_PLOT.nullableplot)
"""
current()
Returns the Plot object for the current plot
"""
function current()
if isplotnull()
error("No current plot/subplot")
@@ -64,7 +60,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# build our plot vector from the args
n = length(plts_tail) + 1
plts = Array{Plot}(n)
plts = Array(Plot, n)
plts[1] = plt1
for (i,plt) in enumerate(plts_tail)
plts[i+1] = plt
-6
View File
@@ -14,12 +14,6 @@ function lookup_aliases(attrtype, attribute)
error("There is no attribute named $attribute in $attrtype")
end
"""
plotattr([attr])
Look up the properties of a Plots attribute, or specify an attribute type. Call `plotattr()` for options.
The information is the same as that given on https://juliaplots.github.io/attributes/.
"""
function plotattr()
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
end
+87 -39
View File
@@ -1,4 +1,53 @@
"""
You can easily define your own plotting recipes with convenience methods:
```
@userplot type GroupHist
args
end
@recipe function f(gh::GroupHist)
# set some attributes, add some series, using gh.args as input
end
# now you can plot like:
grouphist(rand(1000,4))
```
"""
macro userplot(expr)
_userplot(expr)
end
function _userplot(expr::Expr)
if expr.head != :type
errror("Must call userplot on a type/immutable expression. Got: $expr")
end
typename = expr.args[2]
funcname = Symbol(lowercase(string(typename)))
funcname2 = Symbol(funcname, "!")
# return a code block with the type definition and convenience plotting methods
esc(quote
$expr
export $funcname, $funcname2
$funcname(args...; kw...) = plot($typename(args); kw...)
$funcname2(args...; kw...) = plot!($typename(args); kw...)
end)
end
function _userplot(sym::Symbol)
_userplot(:(type $sym
args
end))
end
# ----------------------------------------------------------------------------------
const _series_recipe_deps = Dict()
function series_recipe_dependencies(st::Symbol, deps::Symbol...)
@@ -47,7 +96,7 @@ end
num_series(x::AMat) = size(x,2)
num_series(x) = 1
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::AbstractPlot) = throw(MethodError("Unmatched plot recipe: $T"))
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::Plot) = throw(MethodError("Unmatched plot recipe: $T"))
# ---------------------------------------------------------------------------
@@ -176,14 +225,14 @@ end
fr = if yaxis[:scale] == :identity
0.0
else
NaNMath.min(axis_limits(yaxis)[1], ignorenan_minimum(y))
NaNMath.min(axis_limits(yaxis)[1], ignoreNaN_minimum(y))
end
end
newx, newy = zeros(3n), zeros(3n)
for i=1:n
rng = 3i-2:3i
newx[rng] = [x[i], x[i], NaN]
newy[rng] = [_cycle(fr,i), y[i], NaN]
newy[rng] = [cycle(fr,i), y[i], NaN]
end
x := newx
y := newy
@@ -235,16 +284,16 @@ end
for rng in iter_segments(args...)
length(rng) < 2 && continue
ts = linspace(0, 1, npoints)
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts))
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
nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
nanappend!(newz, map(t -> bezier_value(cycle(z,rng), t), ts))
end
if fr != nothing
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
nanappend!(newfr, map(t -> bezier_value(cycle(fr,rng), t), ts))
end
# if lz != nothing
# lzrng = _cycle(lz, rng) # the line_z's for this segment
# 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))
# end
@@ -289,9 +338,9 @@ end
# compute half-width of bars
bw = d[:bar_width]
hw = if bw == nothing
0.5ignorenan_mean(diff(procx))
0.5ignoreNaN_mean(diff(procx))
else
Float64[0.5_cycle(bw,i) for i=1:length(procx)]
Float64[0.5cycle(bw,i) for i=1:length(procx)]
end
# make fillto a vector... default fills to 0
@@ -309,15 +358,15 @@ end
yi = procy[i]
if !isnan(yi)
center = procx[i]
hwi = _cycle(hw,i)
fi = _cycle(fillto,i)
hwi = cycle(hw,i)
fi = cycle(fillto,i)
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
push!(yseg, yi, fi, fi, yi, yi)
end
end
# widen limits out a bit
expand_extrema!(axis, widen(ignorenan_extrema(xseg.pts)...))
expand_extrema!(axis, widen(ignoreNaN_extrema(xseg.pts)...))
# switch back
if !isvertical(d)
@@ -365,8 +414,8 @@ end
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
w_adj = _scale_adjusted_values(T, w, wscale)
w_min = ignorenan_minimum(w_adj)
w_max = ignorenan_maximum(w_adj)
w_min = ignoreNaN_minimum(w_adj)
w_max = ignoreNaN_maximum(w_adj)
baseline = _binbarlike_baseline(w_min, wscale)
w_adj, baseline
end
@@ -501,7 +550,7 @@ Plots.@deps stepbins path
function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto)
_cl(x) = ceil(Int, NaNMath.max(x, one(x)))
_iqr(v) = quantile(v, 0.75) - quantile(v, 0.25)
_span(v) = ignorenan_maximum(v) - ignorenan_minimum(v)
_span(v) = ignoreNaN_maximum(v) - ignoreNaN_minimum(v)
n_samples = length(linearindices(first(vs)))
# Estimator for number of samples in one row/column of bins along each axis:
@@ -620,7 +669,7 @@ end
edge_x, edge_y, weights = x, y, z.surf
float_weights = float(weights)
if float_weights === weights
if is(float_weights, weights)
float_weights = deepcopy(float_weights)
end
for (i, c) in enumerate(float_weights)
@@ -703,12 +752,12 @@ end
function error_coords(xorig, yorig, ebar)
# init empty x/y, and zip errors if passed Tuple{Vector,Vector}
x, y = Array{float_extended_type(xorig)}(0), Array{Float64}(0)
x, y = Array(float_extended_type(xorig), 0), Array(Float64, 0)
# for each point, create a line segment from the bottom to the top of the errorbar
for i = 1:max(length(xorig), length(yorig))
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
ebi = _cycle(ebar, i)
xi = cycle(xorig, i)
yi = cycle(yorig, i)
ebi = cycle(ebar, i)
nanappend!(x, [xi, xi])
e1, e2 = if istuple(ebi)
first(ebi), last(ebi)
@@ -761,11 +810,11 @@ function quiver_using_arrows(d::KW)
x, y = zeros(0), zeros(0)
for i = 1:max(length(xorig), length(yorig))
# get the starting position
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
xi = cycle(xorig, i)
yi = cycle(yorig, i)
# get the velocity
vi = _cycle(velocity, i)
vi = cycle(velocity, i)
vx, vy = if istuple(vi)
first(vi), last(vi)
elseif isscalar(vi)
@@ -798,12 +847,12 @@ function quiver_using_hack(d::KW)
for i = 1:max(length(xorig), length(yorig))
# get the starting position
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
xi = cycle(xorig, i)
yi = cycle(yorig, i)
p = P2(xi, yi)
# get the velocity
vi = _cycle(velocity, i)
vi = cycle(velocity, i)
vx, vy = if istuple(vi)
first(vi), last(vi)
elseif isscalar(vi)
@@ -847,7 +896,6 @@ end
# TODO: move OHLC to PlotRecipes finance.jl
"Represent Open High Low Close data (used in finance)"
type OHLC{T<:Real}
open::T
high::T
@@ -871,7 +919,7 @@ end
# get the joined vector
function get_xy(v::AVec{OHLC}, x = 1:length(v))
xdiff = 0.3ignorenan_mean(abs.(diff(x)))
xdiff = 0.3ignoreNaN_mean(abs(diff(x)))
x_out, y_out = zeros(0), zeros(0)
for (i,ohlc) in enumerate(v)
ox,oy = get_xy(ohlc, x[i], xdiff)
@@ -912,7 +960,7 @@ end
# "Sparsity plot... heatmap of non-zero values of a matrix"
# function spy{T<:Real}(z::AMat{T}; kw...)
# mat = reshape(map(zi->float(zi!=0), z),1,:)
# mat = map(zi->float(zi!=0), z)'
# xn, yn = size(mat)
# heatmap(mat; leg=false, yflip=true, aspect_ratio=:equal,
# xlim=(0.5, xn+0.5), ylim=(0.5, yn+0.5),
@@ -939,8 +987,8 @@ end
yflip := true
aspect_ratio := 1
rs, cs, zs = findnz(z.surf)
xlim := ignorenan_extrema(cs)
ylim := ignorenan_extrema(rs)
xlim := ignoreNaN_extrema(cs)
ylim := ignoreNaN_extrema(rs)
if d[:markershape] == :none
markershape := :circle
end
@@ -962,7 +1010,7 @@ end
"Adds a+bx... straight line over the current plot"
function abline!(plt::Plot, a, b; kw...)
plot!(plt, [ignorenan_extrema(plt)...], x -> b + a*x; kw...)
plot!(plt, [ignoreNaN_extrema(plt)...], x -> b + a*x; kw...)
end
abline!(args...; kw...) = abline!(current(), args...; kw...)
@@ -971,11 +1019,11 @@ abline!(args...; kw...) = abline!(current(), args...; kw...)
# -------------------------------------------------
# Dates
dateformatter(dt) = string(Date(Dates.UTD(dt)))
datetimeformatter(dt) = string(DateTime(Dates.UTM(dt)))
dateformatter(dt) = string(convert(Date, dt))
datetimeformatter(dt) = string(convert(DateTime, dt))
@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{Date}, dt::Date) = (dt -> convert(Int, dt), dateformatter)
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int, dt), datetimeformatter)
# -------------------------------------------------
# Complex Numbers
@@ -1006,7 +1054,7 @@ end
end
library = PlotUtils.color_libraries[cl.args[1]]
z = sqrt.((1:15)*reshape(1:20,1,:))
z = sqrt.((1:15)*(1:20)')
seriestype := :heatmap
ticks := nothing
@@ -1030,7 +1078,7 @@ end
if !(length(grad.args) == 1 && isa(grad.args[1], Symbol))
error("showgradient takes the name of a color gradient as a Symbol")
end
z = sqrt.((1:15)*reshape(1:20,1,:))
z = sqrt.((1:15)*(1:20)')
seriestype := :heatmap
ticks := nothing
legend := false
+2 -15
View File
@@ -6,7 +6,7 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
typealias FuncOrFuncs{F} Union{F, Vector{F}, Matrix{F}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
@@ -318,7 +318,7 @@ end
@recipe function f{T<:Colorant}(mat::AMat{T})
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
SliceIt, 1:m, 1:n, Surface(mat)
@@ -509,25 +509,12 @@ end
# nothing
# end
splittable_kw(key, val, lengthGroup) = false
splittable_kw(key, val::AbstractArray, lengthGroup) = (key != :group) && size(val,1) == lengthGroup
splittable_kw(key, val::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup))
split_kw(key, val::AbstractArray, indices) = val[indices, fill(Colon(), ndims(val)-1)...]
split_kw(key, val::Tuple, indices) = Tuple(split_kw(key, v, indices) for v in val)
# split the group into 1 series per group, and set the label and idxfilter for each
@recipe function f(groupby::GroupBy, args...)
lengthGroup = maximum(union(groupby.groupIds...))
for (i,glab) in enumerate(groupby.groupLabels)
@series begin
label --> string(glab)
idxfilter --> groupby.groupIds[i]
for (key,val) in d
if splittable_kw(key, val, lengthGroup)
:($key) := split_kw(key, val, groupby.groupIds[i])
end
end
args
end
end
+1 -6
View File
@@ -13,11 +13,6 @@ function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
)
end
"""
plotarea(subplot)
Return the bounding box of a subplot
"""
plotarea(sp::Subplot) = sp.plotarea
plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox)
@@ -37,7 +32,7 @@ get_subplot(plt::Plot, k) = plt.spmap[k]
get_subplot(series::Series) = series.d[:subplot]
get_subplot_index(plt::Plot, idx::Integer) = Int(idx)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(x -> x === sp, plt.subplots)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(_ -> _ === sp, plt.subplots)
series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot] === sp, sp.plt.series_list)
-4
View File
@@ -1,8 +1,4 @@
"""
theme(s::Symbol)
Specify the colour theme for plots.
"""
function theme(s::Symbol; kw...)
# reset?
if s == :none || s == :default
+4
View File
@@ -8,6 +8,10 @@ const KW = Dict{Symbol,Any}
immutable PlotsDisplay <: Display end
abstract AbstractBackend
abstract AbstractPlot{T<:AbstractBackend}
abstract AbstractLayout
# -----------------------------------------------------------
immutable InputWrapper{T}
+33 -75
View File
@@ -3,7 +3,7 @@ calcMidpoints(edges::AbstractVector) = Float64[0.5 * (edges[i] + edges[i+1]) for
"Make histogram-like bins of data"
function binData(data, nbins)
lo, hi = ignorenan_extrema(data)
lo, hi = ignoreNaN_extrema(data)
edges = collect(linspace(lo, hi, nbins+1))
midpoints = calcMidpoints(edges)
buckets = Int[max(2, min(searchsortedfirst(edges, x), length(edges)))-1 for x in data]
@@ -109,7 +109,7 @@ function regressionXY(x, y)
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
# make a line segment
regx = [ignorenan_minimum(x), ignorenan_maximum(x)]
regx = [ignoreNaN_minimum(x), ignoreNaN_maximum(x)]
regy = β * regx + α
regx, regy
end
@@ -137,7 +137,7 @@ function imageHack(d::KW)
end
# ---------------------------------------------------------------
"Build line segments for plotting"
type Segments{T}
pts::Vector{T}
end
@@ -185,7 +185,6 @@ type SegmentsIterator
args::Tuple
n::Int
end
function iter_segments(args...)
tup = Plots.wraptuple(args)
n = maximum(map(length, tup))
@@ -193,7 +192,7 @@ function iter_segments(args...)
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> !isfinite(_cycle(a,i)), args)
anynan(i::Int, args::Tuple) = any(a -> !isfinite(cycle(a,i)), args)
anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(i -> anynan(i, args), istart:iend)
@@ -244,19 +243,19 @@ notimpl() = error("This has not been implemented yet")
isnothing(x::Void) = true
isnothing(x) = false
_cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
_cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
_cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
_cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
_cycle(v, idx::Int) = v
cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
cycle(v, idx::Int) = v
_cycle(v::AVec, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v::AMat, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v, indices::AVec{Int}) = fill(v, length(indices))
cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
cycle(v, indices::AVec{Int}) = fill(v, length(indices))
_cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
cycle(grad::ColorGradient, idx::Int) = cycle(grad.colors, idx)
cycle(grad::ColorGradient, indices::AVec{Int}) = cycle(grad.colors, indices)
makevec(v::AVec) = v
makevec{T}(v::T) = T[v]
@@ -284,7 +283,7 @@ unzip{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x)
try
e1, e2 = ignorenan_extrema(x)
e1, e2 = ignoreNaN_extrema(x)
lims[1] = NaNMath.min(lims[1], e1)
lims[2] = NaNMath.max(lims[2], e2)
# catch err
@@ -293,7 +292,7 @@ function _expand_limits(lims, x)
nothing
end
expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
expand_data(v, n::Integer) = [cycle(v, i) for i=1:n]
# if the type exists in a list, replace the first occurence. otherwise add it to the end
function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
@@ -325,7 +324,7 @@ function replaceAliases!(d::KW, aliases::Dict{Symbol,Symbol})
end
end
createSegments(z) = collect(repmat(reshape(z,1,:),2,1))[2:end]
createSegments(z) = collect(repmat(z',2,1))[2:end]
Base.first(c::Colorant) = c
Base.first(x::Symbol) = x
@@ -333,32 +332,19 @@ Base.first(x::Symbol) = x
sortedkeys(d::Dict) = sort(collect(keys(d)))
const _scale_base = Dict{Symbol, Real}(
:log10 => 10,
:log2 => 2,
:ln => e,
)
"create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges(v::AVec, scale::Symbol = :identity)
vmin, vmax = ignorenan_extrema(v)
extra_min = extra_max = 0.5 * (vmax-vmin) / (length(v)-1)
if scale in _logScales
vmin > 0 || error("The axis values must be positive for a $scale scale")
while vmin - extra_min <= 0
extra_min /= _scale_base[scale]
end
end
vcat(vmin-extra_min, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra_max)
function heatmap_edges(v::AVec)
vmin, vmax = ignoreNaN_extrema(v)
extra = 0.5 * (vmax-vmin) / (length(v)-1)
vcat(vmin-extra, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra)
end
function calc_r_extrema(x, y)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
xmin, xmax = ignoreNaN_extrema(x)
ymin, ymax = ignoreNaN_extrema(y)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
ignorenan_extrema(r)
ignoreNaN_extrema(r)
end
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
@@ -369,8 +355,8 @@ function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
x = zeros(n)
y = zeros(n)
for i in 1:n
x[i] = _cycle(r,i) * cos.(_cycle(phi,i))
y[i] = _cycle(r,i) * sin.(_cycle(phi,i))
x[i] = cycle(r,i) * cos(cycle(phi,i))
y[i] = cycle(r,i) * sin(cycle(phi,i))
end
x, y
end
@@ -483,7 +469,7 @@ ok(tup::Tuple) = ok(tup...)
# compute one side of a fill range from a ribbon
function make_fillrange_side(y, rib)
frs = zeros(length(y))
for (i, (yi, ri)) in enumerate(zip(y, Base.Iterators.cycle(rib)))
for (i, (yi, ri)) in enumerate(zip(y, Base.cycle(rib)))
frs[i] = yi + ri
end
frs
@@ -494,44 +480,16 @@ function make_fillrange_from_ribbon(kw::KW)
y, rib = kw[:y], kw[:ribbon]
rib = wraptuple(rib)
rib1, rib2 = -first(rib), last(rib)
# kw[:ribbon] = nothing
kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2)
(get(kw, :fillalpha, nothing) == nothing) && (kw[:fillalpha] = 0.5)
end
#turn tuple of fillranges to one path
function concatenate_fillrange(x,y::Tuple)
rib1, rib2 = first(y), last(y)
yline = vcat(rib1,(rib2)[end:-1:1])
xline = vcat(x,x[end:-1:1])
return xline, yline
end
function get_sp_lims(sp::Subplot, letter::Symbol)
axis_limits(sp[Symbol(letter, :axis)])
end
"""
xlims([plt])
Returns the x axis limits of the current plot or subplot
"""
xlims(sp::Subplot) = get_sp_lims(sp, :x)
"""
ylims([plt])
Returns the y axis limits of the current plot or subplot
"""
ylims(sp::Subplot) = get_sp_lims(sp, :y)
"""
zlims([plt])
Returns the z axis limits of the current plot or subplot
"""
zlims(sp::Subplot) = get_sp_lims(sp, :z)
xlims(plt::Plot, sp_idx::Int = 1) = xlims(plt[sp_idx])
ylims(plt::Plot, sp_idx::Int = 1) = ylims(plt[sp_idx])
zlims(plt::Plot, sp_idx::Int = 1) = zlims(plt[sp_idx])
@@ -565,7 +523,7 @@ allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg)
"""
Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example:
```
with(:gr, size=(400,400), type=:histogram) do
with(:gadfly, size=(400,400), type=:histogram) do
plot(rand(10))
plot(rand(10))
end
@@ -687,7 +645,7 @@ end
# used in updating an existing series
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + ignorenan_maximum(v))
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + ignoreNaN_maximum(v))
extendSeriesData{T}(v::Range{T}, z::Real) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v)
@@ -913,9 +871,9 @@ mm2px(mm::Real) = float(px / MM_PER_PX)
"Smallest x in plot"
xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.d[:x]) for series in plt.series_list])
xmin(plt::Plot) = ignoreNaN_minimum([ignoreNaN_minimum(series.d[:x]) for series in plt.series_list])
"Largest x in plot"
xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.d[:x]) for series in plt.series_list])
xmax(plt::Plot) = ignoreNaN_maximum([ignoreNaN_maximum(series.d[:x]) for series in plt.series_list])
"Extrema of x-values in plot"
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
ignoreNaN_extrema(plt::Plot) = (xmin(plt), xmax(plt))
+2
View File
@@ -1,4 +1,5 @@
StatPlots
FactCheck
Images
ImageMagick
@osx QuartzImageIO
@@ -6,3 +7,4 @@ GR
RDatasets
VisualRegressionTests
UnicodePlots
Glob
+10 -6
View File
@@ -13,9 +13,10 @@ try
end
using Plots
# using Plots # reexported by StatPlots
using StatPlots
using Base.Test
using FactCheck
using Glob
default(size=(500,300))
@@ -23,7 +24,7 @@ default(size=(500,300))
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
const _current_plots_version = v"0.12.3"
const _current_plots_version = v"0.11.3"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
@@ -42,8 +43,11 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
fn = "ref$idx.png"
# firgure out version info
vns = filter(x->x[1] != '.', readdir(refdir))
versions = sort(VersionNumber.(vns), rev = true)
G = glob(joinpath(relpath(refdir), "*"))
# @show refdir fn G
slash = (@static is_windows() ? "\\" : "/")
versions = map(fn -> VersionNumber(split(fn, slash)[end]), G)
versions = reverse(sort(versions))
versions = filter(v -> v <= _current_plots_version, versions)
# @show refdir fn versions
@@ -95,7 +99,7 @@ function image_comparison_facts(pkg::Symbol;
for i in 1:length(Plots._examples)
i in skip && continue
if only == nothing || i in only
@test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success == true
@fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success --> true
end
end
end
+2 -2
View File
@@ -6,8 +6,8 @@ sudo apt-get -qq update
# sudo apt-get install -y wkhtmltopdf
sudo apt-get install -y xfonts-75dpi xfonts-base
wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.2.1/wkhtmltox-0.12.2.1_linux-precise-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2.1_linux-precise-amd64.deb
wget https://downloads.wkhtmltopdf.org/0.12/0.12.2/wkhtmltox-0.12.2_linux-precise-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2_linux-precise-amd64.deb
# wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-trusty-amd64.deb
# sudo dpkg -i wkhtmltox-0.12.2_linux-trusty-amd64.deb
wkhtmltoimage http://www.google.com test.png
+51 -49
View File
@@ -7,36 +7,41 @@ srand(1234)
default(show=false, reuse=true)
img_eps = isinteractive() ? 1e-2 : 10e-2
@testset "GR" begin
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
# facts("Gadfly") do
# @fact gadfly() --> Plots.GadflyBackend()
# @fact backend() --> Plots.GadflyBackend()
#
# @fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyBackend}
# @fact plot(Int[1,2,3], rand(3)) --> not(nothing)
# @fact plot(sort(rand(10)), rand(Int, 10, 3)) --> not(nothing)
# @fact plot!(rand(10,3), rand(10,3)) --> not(nothing)
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# end
facts("GR") do
@fact gr() --> Plots.GRBackend()
@fact backend() --> Plots.GRBackend()
image_comparison_facts(:gr, eps=img_eps)
end
@testset "PyPlot" begin
@test pyplot() == Plots.PyPlotBackend()
@test backend() == Plots.PyPlotBackend()
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotBackend()
@fact backend() --> Plots.PyPlotBackend()
image_comparison_facts(:pyplot, eps=img_eps)
end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@test isa(plot(rand(10)), Plots.Plot) == true
end
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
# facts("PlotlyJS") do
# @fact plotlyjs() --> Plots.PlotlyJSBackend()
# @fact backend() --> Plots.PlotlyJSBackend()
#
# if is_linux() && isinteractive()
# image_comparison_facts(:plotlyjs,
@@ -54,9 +59,9 @@ end
# ERROR: LoadError: InitError: Cannot open display:
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
# @testset "InspectDR" begin
# @test inspectdr() == Plots.InspectDRBackend()
# @test backend() == Plots.InspectDRBackend()
# facts("InspectDR") do
# @fact inspectdr() --> Plots.InspectDRBackend()
# @fact backend() --> Plots.InspectDRBackend()
#
# image_comparison_facts(:inspectdr,
# skip=[
@@ -73,66 +78,61 @@ end
# end
# @testset "Plotly" begin
# @test plotly() == Plots.PlotlyBackend()
# @test backend() == Plots.PlotlyBackend()
# facts("Plotly") do
# @fact plotly() --> Plots.PlotlyBackend()
# @fact backend() --> Plots.PlotlyBackend()
#
# # # until png generation is reliable on OSX, just test on linux
# # @static is_linux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], eps=img_eps)
# end
# @testset "Immerse" begin
# @test immerse() == Plots.ImmerseBackend()
# @test backend() == Plots.ImmerseBackend()
# facts("Immerse") do
# @fact immerse() --> Plots.ImmerseBackend()
# @fact backend() --> Plots.ImmerseBackend()
#
# # as long as we can plot anything without error, it should be the same as Gadfly
# image_comparison_facts(:immerse, only=[1], eps=img_eps)
# end
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
# facts("PlotlyJS") do
# @fact plotlyjs() --> Plots.PlotlyJSBackend()
# @fact backend() --> Plots.PlotlyJSBackend()
#
# # as long as we can plot anything without error, it should be the same as Plotly
# image_comparison_facts(:plotlyjs, only=[1], eps=img_eps)
# end
# @testset "Gadfly" begin
# @test gadfly() == Plots.GadflyBackend()
# @test backend() == Plots.GadflyBackend()
#
# @test typeof(plot(1:10)) == Plots.Plot{Plots.GadflyBackend}
# @test plot(Int[1,2,3], rand(3)) == not(nothing)
# @test plot(sort(rand(10)), rand(Int, 10, 3)) == not(nothing)
# @test plot!(rand(10,3), rand(10,3)) == not(nothing)
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# end
facts("UnicodePlots") do
@fact unicodeplots() --> Plots.UnicodePlotsBackend()
@fact backend() --> Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@fact isa(plot(rand(10)), Plots.Plot) --> true
end
@testset "Axes" begin
facts("Axes") do
p = plot()
axis = p.subplots[1][:xaxis]
@test typeof(axis) == Plots.Axis
@test Plots.discrete_value!(axis, "HI") == (0.5, 1)
@test Plots.discrete_value!(axis, :yo) == (1.5, 2)
@test Plots.ignorenan_extrema(axis) == (0.5,1.5)
@test axis[:discrete_map] == Dict{Any,Any}(:yo => 2, "HI" => 1)
@fact typeof(axis) --> Plots.Axis
@fact Plots.discrete_value!(axis, "HI") --> (0.5, 1)
@fact Plots.discrete_value!(axis, :yo) --> (1.5, 2)
@fact Plots.ignoreNaN_extrema(axis) --> (0.5,1.5)
@fact axis[:discrete_map] --> Dict{Any,Any}(:yo => 2, "HI" => 1)
Plots.discrete_value!(axis, ["x$i" for i=1:5])
Plots.discrete_value!(axis, ["x$i" for i=0:2])
@test Plots.ignorenan_extrema(axis) == (0.5, 7.5)
@fact Plots.ignoreNaN_extrema(axis) --> (0.5, 7.5)
end
# tests for preprocessing recipes
# @testset "recipes" begin
# facts("recipes") do
# user recipe
@@ -169,4 +169,6 @@ end
# end
FactCheck.exitstatus()
end # module
+1 -1
View File
@@ -1,4 +1,4 @@
Pkg.add("ImageMagick")
Pkg.clone("ImageMagick")
Pkg.build("ImageMagick")
Pkg.clone("GR")